2000-10-09 16:24:57 +00:00
/* gfileutils.c - File utility functions
*
* Copyright 2000 Red Hat , Inc .
*
* GLib is free software ; you can redistribute it and / or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation ; either version 2 of the
* License , or ( at your option ) any later version .
*
* GLib is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with GLib ; see the file COPYING . LIB . If not ,
2014-01-23 12:58:29 +01:00
* see < http : //www.gnu.org/licenses/>.
2000-10-09 16:24:57 +00:00
*/
Some more debugging output. (g_io_channel_win32_poll): Remove unused vars.
2000-10-16 Tor Lillqvist <tml@iki.fi>
* giowin32.c (reader_thread): Some more debugging output.
(g_io_channel_win32_poll): Remove unused vars.
* gfileutils.c: Changes for Win32, with no unistd.h and no
S_ISLNK().
* gspawn-win32.c: Implementation of the g_spwan_* functions for
Win32. Due to the general non-Unixness of Win32, much of the
functionality that is relatively clean to implement on Unix, is
hard to do on Win32. We must use a separate helper program to
change directory, close extra file descriptors, redirect the std
ones, as needed, and only then start the child process. No child
process pid can be returned, unfortunately. Or if we used
CreateProcess directly, it probably could. (Now we use the spawnv*
functions from msvcrt.)
* glib.def: Add new entry points.
* glib.def
* giowin32.c: Remove g_io_channel_win32_wait_for_condition(),
g_io_channel_win32_poll() subsumes it.
* gbacktrace.h: G_BREAKPOINT for MSVC (on the ix86).
* gwin32.c (g_win32_getlocale): Use "sp" for
LANG_CROATIAN+SUBLANG_SERBIAN_LATIN.
* makefile.{mingw,msc}.in (glib_OBJECTS): Add new files.
Add gspawn-win32-helper.exe rule.
* tests/makefile.{mingw,msc}.in (TESTS): Add shell-test and
spawn-test.
* tests/spawn-test.c: (run_tests): On Win32, don't try to run
/bin/sh, but ipconfig (no special significance in choosing that,
just a program that outputs something to stdout).
2000-10-16 18:54:29 +00:00
# include "config.h"
2010-09-06 15:56:16 +03:00
# include "glibconfig.h"
Some more debugging output. (g_io_channel_win32_poll): Remove unused vars.
2000-10-16 Tor Lillqvist <tml@iki.fi>
* giowin32.c (reader_thread): Some more debugging output.
(g_io_channel_win32_poll): Remove unused vars.
* gfileutils.c: Changes for Win32, with no unistd.h and no
S_ISLNK().
* gspawn-win32.c: Implementation of the g_spwan_* functions for
Win32. Due to the general non-Unixness of Win32, much of the
functionality that is relatively clean to implement on Unix, is
hard to do on Win32. We must use a separate helper program to
change directory, close extra file descriptors, redirect the std
ones, as needed, and only then start the child process. No child
process pid can be returned, unfortunately. Or if we used
CreateProcess directly, it probably could. (Now we use the spawnv*
functions from msvcrt.)
* glib.def: Add new entry points.
* glib.def
* giowin32.c: Remove g_io_channel_win32_wait_for_condition(),
g_io_channel_win32_poll() subsumes it.
* gbacktrace.h: G_BREAKPOINT for MSVC (on the ix86).
* gwin32.c (g_win32_getlocale): Use "sp" for
LANG_CROATIAN+SUBLANG_SERBIAN_LATIN.
* makefile.{mingw,msc}.in (glib_OBJECTS): Add new files.
Add gspawn-win32-helper.exe rule.
* tests/makefile.{mingw,msc}.in (TESTS): Add shell-test and
spawn-test.
* tests/spawn-test.c: (run_tests): On Win32, don't try to run
/bin/sh, but ipconfig (no special significance in choosing that,
just a program that outputs something to stdout).
2000-10-16 18:54:29 +00:00
2000-10-09 16:24:57 +00:00
# include <sys/stat.h>
# include <stdio.h>
2000-12-05 20:45:33 +00:00
# include <stdlib.h>
2001-09-10 13:30:41 +00:00
# include <stdarg.h>
2000-10-09 16:24:57 +00:00
# include <string.h>
# include <errno.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
2000-11-21 15:27:44 +00:00
# include <stdlib.h>
2000-10-09 16:24:57 +00:00
Replace #ifdef HAVE_UNISTD_H checks with #ifdef G_OS_UNIX
In Windows development environments that have it, <unistd.h> is mostly
just a wrapper around several other native headers (in particular,
<io.h>, which contains read(), close(), etc, and <process.h>, which
contains getpid()). But given that some Windows dev environments don't
have <unistd.h>, everything that uses those functions on Windows
already needed to include the correct Windows header as well, and so
there is never any point to including <unistd.h> on Windows.
Also, remove some <unistd.h> includes (and a few others) that were
unnecessary even on unix.
https://bugzilla.gnome.org/show_bug.cgi?id=710519
2013-10-19 13:04:00 -04:00
# ifdef G_OS_UNIX
# include <unistd.h>
# endif
2000-10-19 17:52:12 +00:00
# ifdef G_OS_WIN32
2004-12-31 01:15:15 +00:00
# include <windows.h>
2005-01-09 01:18:32 +00:00
# include <io.h>
2000-10-19 17:52:12 +00:00
# endif /* G_OS_WIN32 */
Some more debugging output. (g_io_channel_win32_poll): Remove unused vars.
2000-10-16 Tor Lillqvist <tml@iki.fi>
* giowin32.c (reader_thread): Some more debugging output.
(g_io_channel_win32_poll): Remove unused vars.
* gfileutils.c: Changes for Win32, with no unistd.h and no
S_ISLNK().
* gspawn-win32.c: Implementation of the g_spwan_* functions for
Win32. Due to the general non-Unixness of Win32, much of the
functionality that is relatively clean to implement on Unix, is
hard to do on Win32. We must use a separate helper program to
change directory, close extra file descriptors, redirect the std
ones, as needed, and only then start the child process. No child
process pid can be returned, unfortunately. Or if we used
CreateProcess directly, it probably could. (Now we use the spawnv*
functions from msvcrt.)
* glib.def: Add new entry points.
* glib.def
* giowin32.c: Remove g_io_channel_win32_wait_for_condition(),
g_io_channel_win32_poll() subsumes it.
* gbacktrace.h: G_BREAKPOINT for MSVC (on the ix86).
* gwin32.c (g_win32_getlocale): Use "sp" for
LANG_CROATIAN+SUBLANG_SERBIAN_LATIN.
* makefile.{mingw,msc}.in (glib_OBJECTS): Add new files.
Add gspawn-win32-helper.exe rule.
* tests/makefile.{mingw,msc}.in (TESTS): Add shell-test and
spawn-test.
* tests/spawn-test.c: (run_tests): On Win32, don't try to run
/bin/sh, but ipconfig (no special significance in choosing that,
just a program that outputs something to stdout).
2000-10-16 18:54:29 +00:00
# ifndef S_ISLNK
2000-10-19 17:52:12 +00:00
# define S_ISLNK(x) 0
Some more debugging output. (g_io_channel_win32_poll): Remove unused vars.
2000-10-16 Tor Lillqvist <tml@iki.fi>
* giowin32.c (reader_thread): Some more debugging output.
(g_io_channel_win32_poll): Remove unused vars.
* gfileutils.c: Changes for Win32, with no unistd.h and no
S_ISLNK().
* gspawn-win32.c: Implementation of the g_spwan_* functions for
Win32. Due to the general non-Unixness of Win32, much of the
functionality that is relatively clean to implement on Unix, is
hard to do on Win32. We must use a separate helper program to
change directory, close extra file descriptors, redirect the std
ones, as needed, and only then start the child process. No child
process pid can be returned, unfortunately. Or if we used
CreateProcess directly, it probably could. (Now we use the spawnv*
functions from msvcrt.)
* glib.def: Add new entry points.
* glib.def
* giowin32.c: Remove g_io_channel_win32_wait_for_condition(),
g_io_channel_win32_poll() subsumes it.
* gbacktrace.h: G_BREAKPOINT for MSVC (on the ix86).
* gwin32.c (g_win32_getlocale): Use "sp" for
LANG_CROATIAN+SUBLANG_SERBIAN_LATIN.
* makefile.{mingw,msc}.in (glib_OBJECTS): Add new files.
Add gspawn-win32-helper.exe rule.
* tests/makefile.{mingw,msc}.in (TESTS): Add shell-test and
spawn-test.
* tests/spawn-test.c: (run_tests): On Win32, don't try to run
/bin/sh, but ipconfig (no special significance in choosing that,
just a program that outputs something to stdout).
2000-10-16 18:54:29 +00:00
# endif
2000-10-09 16:24:57 +00:00
2000-10-31 05:51:24 +00:00
# ifndef O_BINARY
# define O_BINARY 0
# endif
2010-09-03 23:03:14 -04:00
# include "gfileutils.h"
2004-10-27 16:46:29 +00:00
# include "gstdio.h"
2001-01-16 02:24:24 +00:00
# include "glibintl.h"
2000-10-09 16:24:57 +00:00
2011-03-08 07:36:15 +01:00
# ifdef HAVE_LINUX_MAGIC_H /* for btrfs check */
2010-12-18 18:52:32 -05:00
# include <linux/magic.h>
# include <sys/vfs.h>
# endif
2005-03-14 04:26:57 +00:00
2011-10-01 23:03:09 -04:00
/**
* SECTION : fileutils
* @ title : File Utilities
* @ short_description : various file - related functions
*
* There is a group of functions which wrap the common POSIX functions
* dealing with filenames ( g_open ( ) , g_rename ( ) , g_mkdir ( ) , g_stat ( ) ,
* g_unlink ( ) , g_remove ( ) , g_fopen ( ) , g_freopen ( ) ) . The point of these
* wrappers is to make it possible to handle file names with any Unicode
* characters in them on Windows without having to use ifdefs and the
* wide character API in the application code .
*
* The pathname argument should be in the GLib file name encoding .
* On POSIX this is the actual on - disk encoding which might correspond
2014-02-05 19:32:41 -05:00
* to the locale settings of the process ( or the ` G_FILENAME_ENCODING `
* environment variable ) , or not .
2011-10-01 23:03:09 -04:00
*
* On Windows the GLib file name encoding is UTF - 8. Note that the
* Microsoft C library does not use UTF - 8 , but has separate APIs for
* current system code page and wide characters ( UTF - 16 ) . The GLib
* wrappers call the wide character API if present ( on modern Windows
* systems ) , otherwise convert to / from the system code page .
*
* Another group of functions allows to open and read directories
* in the GLib file name encoding . These are g_dir_open ( ) ,
* g_dir_read_name ( ) , g_dir_rewind ( ) , g_dir_close ( ) .
*/
/**
* GFileError :
* @ G_FILE_ERROR_EXIST : Operation not permitted ; only the owner of
* the file ( or other resource ) or processes with special privileges
* can perform the operation .
* @ G_FILE_ERROR_ISDIR : File is a directory ; you cannot open a directory
* for writing , or create or remove hard links to it .
* @ G_FILE_ERROR_ACCES : Permission denied ; the file permissions do not
* allow the attempted operation .
* @ G_FILE_ERROR_NAMETOOLONG : Filename too long .
* @ G_FILE_ERROR_NOENT : No such file or directory . This is a " file
* doesn ' t exist " error for ordinary files that are referenced in
* contexts where they are expected to already exist .
* @ G_FILE_ERROR_NOTDIR : A file that isn ' t a directory was specified when
* a directory is required .
* @ G_FILE_ERROR_NXIO : No such device or address . The system tried to
* use the device represented by a file you specified , and it
* couldn ' t find the device . This can mean that the device file was
* installed incorrectly , or that the physical device is missing or
* not correctly attached to the computer .
* @ G_FILE_ERROR_NODEV : The underlying file system of the specified file
* does not support memory mapping .
2011-12-13 23:00:16 -05:00
* @ G_FILE_ERROR_ROFS : The directory containing the new link can ' t be
2011-10-01 23:03:09 -04:00
* modified because it ' s on a read - only file system .
* @ G_FILE_ERROR_TXTBSY : Text file busy .
* @ G_FILE_ERROR_FAULT : You passed in a pointer to bad memory .
* ( GLib won ' t reliably return this , don ' t pass in pointers to bad
* memory . )
* @ G_FILE_ERROR_LOOP : Too many levels of symbolic links were encountered
* in looking up a file name . This often indicates a cycle of symbolic
* links .
* @ G_FILE_ERROR_NOSPC : No space left on device ; write operation on a
* file failed because the disk is full .
* @ G_FILE_ERROR_NOMEM : No memory available . The system cannot allocate
* more virtual memory because its capacity is full .
* @ G_FILE_ERROR_MFILE : The current process has too many files open and
* can ' t open any more . Duplicate descriptors do count toward this
* limit .
* @ G_FILE_ERROR_NFILE : There are too many distinct file openings in the
* entire system .
* @ G_FILE_ERROR_BADF : Bad file descriptor ; for example , I / O on a
* descriptor that has been closed or reading from a descriptor open
* only for writing ( or vice versa ) .
* @ G_FILE_ERROR_INVAL : Invalid argument . This is used to indicate
* various kinds of problems with passing the wrong argument to a
* library function .
* @ G_FILE_ERROR_PIPE : Broken pipe ; there is no process reading from the
* other end of a pipe . Every library function that returns this
2013-05-20 17:54:48 -03:00
* error code also generates a ' SIGPIPE ' signal ; this signal
2011-10-01 23:03:09 -04:00
* terminates the program if not handled or blocked . Thus , your
* program will never actually see this code unless it has handled
2013-05-20 17:54:48 -03:00
* or blocked ' SIGPIPE ' .
2011-10-01 23:03:09 -04:00
* @ G_FILE_ERROR_AGAIN : Resource temporarily unavailable ; the call might
* work if you try again later .
* @ G_FILE_ERROR_INTR : Interrupted function call ; an asynchronous signal
* occurred and prevented completion of the call . When this
* happens , you should try the call again .
* @ G_FILE_ERROR_IO : Input / output error ; usually used for physical read
* or write errors . i . e . the disk or other physical device hardware
* is returning errors .
* @ G_FILE_ERROR_PERM : Operation not permitted ; only the owner of the
* file ( or other resource ) or processes with special privileges can
* perform the operation .
* @ G_FILE_ERROR_NOSYS : Function not implemented ; this indicates that
* the system is missing some functionality .
* @ G_FILE_ERROR_FAILED : Does not correspond to a UNIX error code ; this
* is the standard " failed for unspecified reason " error code present
* in all # GError error code enumerations . Returned if no specific
* code applies .
*
* Values corresponding to @ errno codes returned from file operations
* on UNIX . Unlike @ errno codes , GFileError values are available on
* all systems , even Windows . The exact meaning of each code depends
* on what sort of file operation you were performing ; the UNIX
* documentation gives more details . The following error code descriptions
* come from the GNU C Library manual , and are under the copyright
* of that manual .
*
* It ' s not very portable to make detailed assumptions about exactly
* which errors will be returned from a given operation . Some errors
* don ' t occur on some systems , etc . , sometimes there are subtle
* differences in when a system will report a given error , etc .
*/
/**
* G_FILE_ERROR :
*
* Error domain for file operations . Errors in this domain will
* be from the # GFileError enumeration . See # GError for information
* on error domains .
*/
/**
* GFileTest :
* @ G_FILE_TEST_IS_REGULAR : % TRUE if the file is a regular file
* ( not a directory ) . Note that this test will also return % TRUE
* if the tested file is a symlink to a regular file .
* @ G_FILE_TEST_IS_SYMLINK : % TRUE if the file is a symlink .
* @ G_FILE_TEST_IS_DIR : % TRUE if the file is a directory .
* @ G_FILE_TEST_IS_EXECUTABLE : % TRUE if the file is executable .
* @ G_FILE_TEST_EXISTS : % TRUE if the file exists . It may or may not
* be a regular file .
*
* A test to perform on a file using g_file_test ( ) .
*/
2005-06-22 09:43:37 +00:00
/**
2005-06-22 18:55:33 +00:00
* g_mkdir_with_parents :
2005-06-22 09:43:37 +00:00
* @ pathname : a pathname in the GLib file name encoding
* @ mode : permissions to use for newly created directories
*
* Create a directory if it doesn ' t already exist . Create intermediate
* parent directories as needed , too .
*
2005-07-13 18:59:46 +00:00
* Returns : 0 if the directory already exists , or was successfully
2005-06-22 09:43:37 +00:00
* created . Returns - 1 if an error occurred , with errno set .
*
* Since : 2.8
*/
int
2005-06-22 18:55:33 +00:00
g_mkdir_with_parents ( const gchar * pathname ,
int mode )
2005-06-22 09:43:37 +00:00
{
gchar * fn , * p ;
2005-06-24 13:26:45 +00:00
if ( pathname = = NULL | | * pathname = = ' \0 ' )
2005-06-22 09:43:37 +00:00
{
errno = EINVAL ;
return - 1 ;
}
fn = g_strdup ( pathname ) ;
if ( g_path_is_absolute ( fn ) )
p = ( gchar * ) g_path_skip_root ( fn ) ;
else
p = fn ;
do
{
while ( * p & & ! G_IS_DIR_SEPARATOR ( * p ) )
p + + ;
if ( ! * p )
p = NULL ;
else
* p = ' \0 ' ;
if ( ! g_file_test ( fn , G_FILE_TEST_EXISTS ) )
{
2011-06-03 22:45:51 -04:00
if ( g_mkdir ( fn , mode ) = = - 1 & & errno ! = EEXIST )
2005-06-22 09:43:37 +00:00
{
int errno_save = errno ;
g_free ( fn ) ;
errno = errno_save ;
return - 1 ;
}
}
else if ( ! g_file_test ( fn , G_FILE_TEST_IS_DIR ) )
{
g_free ( fn ) ;
errno = ENOTDIR ;
return - 1 ;
}
if ( p )
{
* p + + = G_DIR_SEPARATOR ;
while ( * p & & G_IS_DIR_SEPARATOR ( * p ) )
p + + ;
}
}
while ( p ) ;
g_free ( fn ) ;
return 0 ;
}
2000-10-09 16:24:57 +00:00
/**
* g_file_test :
2004-12-31 01:15:15 +00:00
* @ filename : a filename to test in the GLib file name encoding
2000-10-09 16:24:57 +00:00
* @ test : bitfield of # GFileTest flags
*
2001-12-16 19:31:36 +00:00
* Returns % TRUE if any of the tests in the bitfield @ test are
2014-02-06 08:04:52 -05:00
* % TRUE . For example , ` ( G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR ) `
* will return % TRUE if the file exists ; the check whether it ' s a
* directory doesn ' t matter since the existence test is % TRUE . With
* the current set of available tests , there ' s no point passing in
* more than one test at a time .
2002-02-07 20:14:00 +00:00
*
2002-12-09 04:52:52 +00:00
* Apart from % G_FILE_TEST_IS_SYMLINK all tests follow symbolic links ,
2002-02-07 20:14:00 +00:00
* so for a symbolic link to a regular file g_file_test ( ) will return
2002-12-09 04:52:52 +00:00
* % TRUE for both % G_FILE_TEST_IS_SYMLINK and % G_FILE_TEST_IS_REGULAR .
2000-10-09 16:24:57 +00:00
*
2002-02-08 08:25:49 +00:00
* Note , that for a dangling symbolic link g_file_test ( ) will return
2002-12-09 04:52:52 +00:00
* % TRUE for % G_FILE_TEST_IS_SYMLINK and % FALSE for all other flags .
*
* You should never use g_file_test ( ) to test whether it is safe
2004-12-30 05:18:56 +00:00
* to perform an operation , because there is always the possibility
2002-12-09 04:52:52 +00:00
* of the condition changing before you actually perform the operation .
* For example , you might think you could use % G_FILE_TEST_IS_SYMLINK
2008-01-18 09:41:46 +00:00
* to know whether it is safe to write to a file without being
2002-12-09 04:52:52 +00:00
* tricked into writing into a different location . It doesn ' t work !
2014-02-01 15:11:49 -05:00
* | [ < ! - - language = " C " - - >
2014-02-14 21:33:36 -05:00
* // DON'T DO THIS
2007-11-25 06:05:06 +00:00
* if ( ! g_file_test ( filename , G_FILE_TEST_IS_SYMLINK ) )
* {
* fd = g_open ( filename , O_WRONLY ) ;
2014-02-14 21:33:36 -05:00
* // write to fd
2007-11-25 06:05:06 +00:00
* }
* ] |
2002-12-09 04:52:52 +00:00
*
* Another thing to note is that % G_FILE_TEST_EXISTS and
* % G_FILE_TEST_IS_EXECUTABLE are implemented using the access ( )
* system call . This usually doesn ' t matter , but if your program
* is setuid or setgid it means that these tests will give you
2004-12-30 05:18:56 +00:00
* the answer for the real user ID and group ID , rather than the
2002-12-09 04:52:52 +00:00
* effective user ID and group ID .
2002-02-08 08:25:49 +00:00
*
2004-12-31 01:15:15 +00:00
* On Windows , there are no symlinks , so testing for
* % G_FILE_TEST_IS_SYMLINK will always return % FALSE . Testing for
* % G_FILE_TEST_IS_EXECUTABLE will just check that the file exists and
* its name indicates that it is executable , checking for well - known
2014-02-05 19:32:41 -05:00
* extensions and those listed in the ` PATHEXT ` environment variable .
2004-12-31 01:15:15 +00:00
*
2014-02-19 19:35:23 -05:00
* Returns : whether a test was % TRUE
2000-10-09 16:24:57 +00:00
* */
gboolean
g_file_test ( const gchar * filename ,
GFileTest test )
{
2004-10-27 16:46:29 +00:00
# ifdef G_OS_WIN32
2005-01-09 21:43:40 +00:00
/* stuff missing in std vc6 api */
# ifndef INVALID_FILE_ATTRIBUTES
# define INVALID_FILE_ATTRIBUTES -1
# endif
# ifndef FILE_ATTRIBUTE_DEVICE
# define FILE_ATTRIBUTE_DEVICE 64
# endif
2004-12-31 01:15:15 +00:00
int attributes ;
2006-08-29 22:45:00 +00:00
wchar_t * wfilename = g_utf8_to_utf16 ( filename , - 1 , NULL , NULL , NULL ) ;
2004-12-31 01:15:15 +00:00
2006-08-29 22:45:00 +00:00
if ( wfilename = = NULL )
return FALSE ;
2004-10-27 16:46:29 +00:00
2006-08-29 22:45:00 +00:00
attributes = GetFileAttributesW ( wfilename ) ;
2004-10-27 16:46:29 +00:00
2006-08-29 22:45:00 +00:00
g_free ( wfilename ) ;
2004-12-31 01:15:15 +00:00
if ( attributes = = INVALID_FILE_ATTRIBUTES )
return FALSE ;
if ( test & G_FILE_TEST_EXISTS )
return TRUE ;
if ( test & G_FILE_TEST_IS_REGULAR )
2009-11-03 14:26:25 +02:00
{
if ( ( attributes & ( FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE ) ) = = 0 )
return TRUE ;
}
2004-12-31 01:15:15 +00:00
if ( test & G_FILE_TEST_IS_DIR )
2009-11-03 14:26:25 +02:00
{
if ( ( attributes & FILE_ATTRIBUTE_DIRECTORY ) ! = 0 )
return TRUE ;
}
2004-12-31 01:15:15 +00:00
2009-11-03 14:26:25 +02:00
/* "while" so that we can exit this "loop" with a simple "break" */
while ( test & G_FILE_TEST_IS_EXECUTABLE )
2004-12-31 01:15:15 +00:00
{
const gchar * lastdot = strrchr ( filename , ' . ' ) ;
2005-01-01 02:09:51 +00:00
const gchar * pathext = NULL , * p ;
2004-12-31 01:15:15 +00:00
int extlen ;
if ( lastdot = = NULL )
2009-11-03 14:26:25 +02:00
break ;
2004-12-31 01:15:15 +00:00
2007-12-09 14:38:26 +00:00
if ( _stricmp ( lastdot , " .exe " ) = = 0 | |
_stricmp ( lastdot , " .cmd " ) = = 0 | |
_stricmp ( lastdot , " .bat " ) = = 0 | |
_stricmp ( lastdot , " .com " ) = = 0 )
2004-12-31 01:15:15 +00:00
return TRUE ;
/* Check if it is one of the types listed in %PATHEXT% */
2005-01-01 02:09:51 +00:00
pathext = g_getenv ( " PATHEXT " ) ;
2004-12-31 01:15:15 +00:00
if ( pathext = = NULL )
2009-11-03 14:26:25 +02:00
break ;
2004-12-31 01:15:15 +00:00
pathext = g_utf8_casefold ( pathext , - 1 ) ;
lastdot = g_utf8_casefold ( lastdot , - 1 ) ;
extlen = strlen ( lastdot ) ;
p = pathext ;
while ( TRUE )
{
2005-01-01 02:09:51 +00:00
const gchar * q = strchr ( p , ' ; ' ) ;
2004-12-31 01:15:15 +00:00
if ( q = = NULL )
q = p + strlen ( p ) ;
if ( extlen = = q - p & &
memcmp ( lastdot , p , extlen ) = = 0 )
2004-10-27 16:46:29 +00:00
{
2005-01-01 02:09:51 +00:00
g_free ( ( gchar * ) pathext ) ;
2004-12-31 01:15:15 +00:00
g_free ( ( gchar * ) lastdot ) ;
return TRUE ;
2004-10-27 16:46:29 +00:00
}
2004-12-31 01:15:15 +00:00
if ( * q )
p = q + 1 ;
else
break ;
2004-10-27 16:46:29 +00:00
}
2005-01-01 02:09:51 +00:00
g_free ( ( gchar * ) pathext ) ;
2004-12-31 01:15:15 +00:00
g_free ( ( gchar * ) lastdot ) ;
2009-11-03 14:26:25 +02:00
break ;
2004-10-27 16:46:29 +00:00
}
2004-12-31 01:15:15 +00:00
return FALSE ;
2004-10-27 16:46:29 +00:00
# else
2002-02-07 20:14:00 +00:00
if ( ( test & G_FILE_TEST_EXISTS ) & & ( access ( filename , F_OK ) = = 0 ) )
return TRUE ;
if ( ( test & G_FILE_TEST_IS_EXECUTABLE ) & & ( access ( filename , X_OK ) = = 0 ) )
2002-12-09 04:52:52 +00:00
{
if ( getuid ( ) ! = 0 )
return TRUE ;
/* For root, on some POSIX systems, access (filename, X_OK)
* will succeed even if no executable bits are set on the
* file . We fall through to a stat test to avoid that .
*/
}
else
test & = ~ G_FILE_TEST_IS_EXECUTABLE ;
2002-02-07 20:14:00 +00:00
if ( test & G_FILE_TEST_IS_SYMLINK )
2000-10-09 16:24:57 +00:00
{
struct stat s ;
2002-02-07 20:14:00 +00:00
if ( ( lstat ( filename , & s ) = = 0 ) & & S_ISLNK ( s . st_mode ) )
2000-10-09 16:24:57 +00:00
return TRUE ;
}
2002-02-07 20:14:00 +00:00
2002-12-09 04:52:52 +00:00
if ( test & ( G_FILE_TEST_IS_REGULAR |
G_FILE_TEST_IS_DIR |
G_FILE_TEST_IS_EXECUTABLE ) )
2002-02-07 20:14:00 +00:00
{
struct stat s ;
if ( stat ( filename , & s ) = = 0 )
{
if ( ( test & G_FILE_TEST_IS_REGULAR ) & & S_ISREG ( s . st_mode ) )
return TRUE ;
if ( ( test & G_FILE_TEST_IS_DIR ) & & S_ISDIR ( s . st_mode ) )
return TRUE ;
2002-12-09 04:52:52 +00:00
/* The extra test for root when access (file, X_OK) succeeds.
*/
if ( ( test & G_FILE_TEST_IS_EXECUTABLE ) & &
( ( s . st_mode & S_IXOTH ) | |
( s . st_mode & S_IXUSR ) | |
( s . st_mode & S_IXGRP ) ) )
return TRUE ;
2002-02-07 20:14:00 +00:00
}
}
return FALSE ;
2004-10-27 16:46:29 +00:00
# endif
}
2012-08-28 13:15:56 -04:00
G_DEFINE_QUARK ( g - file - error - quark , g_file_error )
2000-10-09 16:24:57 +00:00
2001-04-16 20:05:25 +00:00
/**
* g_file_error_from_errno :
* @ err_no : an " errno " value
*
2011-12-13 23:00:16 -05:00
* Gets a # GFileError constant based on the passed - in @ err_no .
2014-02-06 08:04:52 -05:00
* For example , if you pass in ` EEXIST ` this function returns
* # G_FILE_ERROR_EXIST . Unlike ` errno ` values , you can portably
2001-04-16 20:05:25 +00:00
* assume that all # GFileError values will exist .
*
* Normally a # GFileError value goes into a # GError returned
* from a function that manipulates files . So you would use
* g_file_error_from_errno ( ) when constructing a # GError .
*
2014-02-19 19:35:23 -05:00
* Returns : # GFileError corresponding to the given @ errno
2001-04-16 20:05:25 +00:00
* */
2000-10-09 16:24:57 +00:00
GFileError
2001-04-16 20:05:25 +00:00
g_file_error_from_errno ( gint err_no )
2000-10-09 16:24:57 +00:00
{
2001-04-16 20:05:25 +00:00
switch ( err_no )
2000-10-09 16:24:57 +00:00
{
# ifdef EEXIST
case EEXIST :
return G_FILE_ERROR_EXIST ;
# endif
# ifdef EISDIR
case EISDIR :
return G_FILE_ERROR_ISDIR ;
# endif
# ifdef EACCES
case EACCES :
return G_FILE_ERROR_ACCES ;
# endif
# ifdef ENAMETOOLONG
case ENAMETOOLONG :
return G_FILE_ERROR_NAMETOOLONG ;
# endif
# ifdef ENOENT
case ENOENT :
return G_FILE_ERROR_NOENT ;
# endif
# ifdef ENOTDIR
case ENOTDIR :
return G_FILE_ERROR_NOTDIR ;
# endif
# ifdef ENXIO
case ENXIO :
return G_FILE_ERROR_NXIO ;
# endif
# ifdef ENODEV
case ENODEV :
return G_FILE_ERROR_NODEV ;
# endif
# ifdef EROFS
case EROFS :
return G_FILE_ERROR_ROFS ;
# endif
# ifdef ETXTBSY
case ETXTBSY :
return G_FILE_ERROR_TXTBSY ;
# endif
# ifdef EFAULT
case EFAULT :
return G_FILE_ERROR_FAULT ;
# endif
# ifdef ELOOP
case ELOOP :
return G_FILE_ERROR_LOOP ;
# endif
# ifdef ENOSPC
case ENOSPC :
return G_FILE_ERROR_NOSPC ;
# endif
# ifdef ENOMEM
case ENOMEM :
return G_FILE_ERROR_NOMEM ;
# endif
# ifdef EMFILE
case EMFILE :
return G_FILE_ERROR_MFILE ;
# endif
# ifdef ENFILE
case ENFILE :
return G_FILE_ERROR_NFILE ;
# endif
# ifdef EBADF
case EBADF :
return G_FILE_ERROR_BADF ;
# endif
# ifdef EINVAL
case EINVAL :
return G_FILE_ERROR_INVAL ;
# endif
# ifdef EPIPE
case EPIPE :
return G_FILE_ERROR_PIPE ;
# endif
# ifdef EAGAIN
case EAGAIN :
return G_FILE_ERROR_AGAIN ;
# endif
# ifdef EINTR
case EINTR :
return G_FILE_ERROR_INTR ;
# endif
# ifdef EIO
case EIO :
return G_FILE_ERROR_IO ;
# endif
# ifdef EPERM
case EPERM :
return G_FILE_ERROR_PERM ;
# endif
2004-08-27 14:57:34 +00:00
# ifdef ENOSYS
case ENOSYS :
return G_FILE_ERROR_NOSYS ;
# endif
2000-10-09 16:24:57 +00:00
default :
return G_FILE_ERROR_FAILED ;
}
}
2013-12-24 23:24:40 -05:00
static char *
format_error_message ( const gchar * filename ,
2014-04-21 15:55:59 +00:00
const gchar * format_string ,
int saved_errno ) G_GNUC_FORMAT ( 2 ) ;
2013-12-24 23:24:40 -05:00
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wformat-nonliteral"
static char *
format_error_message ( const gchar * filename ,
2014-04-21 15:55:59 +00:00
const gchar * format_string ,
int saved_errno )
2013-12-24 23:24:40 -05:00
{
gchar * display_name ;
gchar * msg ;
display_name = g_filename_display_name ( filename ) ;
msg = g_strdup_printf ( format_string , display_name , g_strerror ( saved_errno ) ) ;
g_free ( display_name ) ;
return msg ;
}
# pragma GCC diagnostic pop
/* format string must have two '%s':
*
* - the place for the filename
* - the place for the strerror
*/
static void
set_file_error ( GError * * error ,
const gchar * filename ,
2014-04-21 15:55:59 +00:00
const gchar * format_string ,
int saved_errno )
2013-12-24 23:24:40 -05:00
{
2014-04-21 15:55:59 +00:00
char * msg = format_error_message ( filename , format_string , saved_errno ) ;
2013-12-24 23:24:40 -05:00
g_set_error_literal ( error , G_FILE_ERROR , g_file_error_from_errno ( saved_errno ) ,
msg ) ;
g_free ( msg ) ;
}
2000-10-09 16:24:57 +00:00
static gboolean
2013-12-24 23:24:40 -05:00
get_contents_stdio ( const gchar * filename ,
2008-12-31 05:51:47 +00:00
FILE * f ,
gchar * * contents ,
gsize * length ,
GError * * error )
2000-10-09 16:24:57 +00:00
{
2005-03-10 12:56:01 +00:00
gchar buf [ 4096 ] ;
2013-11-25 14:06:01 +00:00
gsize bytes ; /* always <= sizeof(buf) */
2005-03-10 12:56:01 +00:00
gchar * str = NULL ;
2006-12-28 04:48:06 +00:00
gsize total_bytes = 0 ;
gsize total_allocated = 0 ;
2005-04-05 04:09:49 +00:00
gchar * tmp ;
2013-12-24 23:24:40 -05:00
gchar * display_filename ;
2005-03-10 12:56:01 +00:00
2000-10-09 16:24:57 +00:00
g_assert ( f ! = NULL ) ;
2001-12-18 18:46:41 +00:00
2000-10-09 16:24:57 +00:00
while ( ! feof ( f ) )
{
2005-03-10 12:56:01 +00:00
gint save_errno ;
2005-02-02 23:28:18 +00:00
2005-03-10 12:56:01 +00:00
bytes = fread ( buf , 1 , sizeof ( buf ) , f ) ;
2005-02-02 23:28:18 +00:00
save_errno = errno ;
2001-12-18 18:46:41 +00:00
2013-11-25 14:06:01 +00:00
if ( total_bytes > G_MAXSIZE - bytes )
goto file_too_large ;
/* Possibility of overflow eliminated above. */
while ( total_bytes + bytes > = total_allocated )
2001-12-18 18:46:41 +00:00
{
2005-03-10 12:56:01 +00:00
if ( str )
2013-11-25 14:06:01 +00:00
{
if ( total_allocated > G_MAXSIZE / 2 )
goto file_too_large ;
total_allocated * = 2 ;
}
2005-03-10 12:56:01 +00:00
else
2013-11-25 14:06:01 +00:00
{
total_allocated = MIN ( bytes + 1 , sizeof ( buf ) ) ;
}
2005-03-10 12:56:01 +00:00
2005-04-05 04:09:49 +00:00
tmp = g_try_realloc ( str , total_allocated ) ;
2001-12-18 18:46:41 +00:00
2005-04-05 04:09:49 +00:00
if ( tmp = = NULL )
2001-12-18 18:46:41 +00:00
{
2013-12-24 23:24:40 -05:00
display_filename = g_filename_display_name ( filename ) ;
2001-12-18 18:46:41 +00:00
g_set_error ( error ,
G_FILE_ERROR ,
G_FILE_ERROR_NOMEM ,
2013-01-25 00:17:18 +01:00
g_dngettext ( GETTEXT_PACKAGE , " Could not allocate %lu byte to read file \" %s \" " , " Could not allocate %lu bytes to read file \" %s \" " , ( gulong ) total_allocated ) ,
2005-03-10 12:56:01 +00:00
( gulong ) total_allocated ,
2004-11-04 00:37:47 +00:00
display_filename ) ;
2013-12-24 23:24:40 -05:00
g_free ( display_filename ) ;
2004-09-30 04:03:16 +00:00
2001-12-18 18:46:41 +00:00
goto error ;
}
2005-04-05 04:09:49 +00:00
str = tmp ;
2001-12-18 18:46:41 +00:00
}
2005-03-10 12:56:01 +00:00
2000-10-09 16:24:57 +00:00
if ( ferror ( f ) )
{
2013-12-24 23:24:40 -05:00
display_filename = g_filename_display_name ( filename ) ;
2000-10-09 16:24:57 +00:00
g_set_error ( error ,
G_FILE_ERROR ,
2005-02-02 23:28:18 +00:00
g_file_error_from_errno ( save_errno ) ,
2000-10-09 16:24:57 +00:00
_ ( " Error reading file '%s': %s " ) ,
2004-11-04 00:37:47 +00:00
display_filename ,
2005-02-02 23:28:18 +00:00
g_strerror ( save_errno ) ) ;
2013-12-24 23:24:40 -05:00
g_free ( display_filename ) ;
2000-10-09 16:24:57 +00:00
2001-12-18 18:46:41 +00:00
goto error ;
2000-10-09 16:24:57 +00:00
}
2013-11-25 14:06:01 +00:00
g_assert ( str ! = NULL ) ;
2001-12-18 18:46:41 +00:00
memcpy ( str + total_bytes , buf , bytes ) ;
2008-07-16 21:42:48 +00:00
2001-12-18 18:46:41 +00:00
total_bytes + = bytes ;
2000-10-09 16:24:57 +00:00
}
fclose ( f ) ;
2005-04-05 04:09:49 +00:00
if ( total_allocated = = 0 )
2008-07-16 21:42:48 +00:00
{
str = g_new ( gchar , 1 ) ;
total_bytes = 0 ;
}
2005-03-30 21:59:40 +00:00
2001-12-18 18:46:41 +00:00
str [ total_bytes ] = ' \0 ' ;
2005-03-10 12:56:01 +00:00
2000-10-09 16:24:57 +00:00
if ( length )
2001-12-18 18:46:41 +00:00
* length = total_bytes ;
2005-03-10 12:56:01 +00:00
2001-12-18 18:46:41 +00:00
* contents = str ;
2005-03-10 12:56:01 +00:00
2001-12-18 18:46:41 +00:00
return TRUE ;
2013-11-25 14:06:01 +00:00
file_too_large :
2013-12-24 23:24:40 -05:00
display_filename = g_filename_display_name ( filename ) ;
2013-11-25 14:06:01 +00:00
g_set_error ( error ,
G_FILE_ERROR ,
G_FILE_ERROR_FAILED ,
_ ( " File \" %s \" is too large " ) ,
display_filename ) ;
2013-12-24 23:24:40 -05:00
g_free ( display_filename ) ;
2013-11-25 14:06:01 +00:00
2001-12-18 18:46:41 +00:00
error :
2000-10-09 16:24:57 +00:00
2001-12-18 18:46:41 +00:00
g_free ( str ) ;
fclose ( f ) ;
2005-03-10 12:56:01 +00:00
return FALSE ;
2000-10-09 16:24:57 +00:00
}
Some more debugging output. (g_io_channel_win32_poll): Remove unused vars.
2000-10-16 Tor Lillqvist <tml@iki.fi>
* giowin32.c (reader_thread): Some more debugging output.
(g_io_channel_win32_poll): Remove unused vars.
* gfileutils.c: Changes for Win32, with no unistd.h and no
S_ISLNK().
* gspawn-win32.c: Implementation of the g_spwan_* functions for
Win32. Due to the general non-Unixness of Win32, much of the
functionality that is relatively clean to implement on Unix, is
hard to do on Win32. We must use a separate helper program to
change directory, close extra file descriptors, redirect the std
ones, as needed, and only then start the child process. No child
process pid can be returned, unfortunately. Or if we used
CreateProcess directly, it probably could. (Now we use the spawnv*
functions from msvcrt.)
* glib.def: Add new entry points.
* glib.def
* giowin32.c: Remove g_io_channel_win32_wait_for_condition(),
g_io_channel_win32_poll() subsumes it.
* gbacktrace.h: G_BREAKPOINT for MSVC (on the ix86).
* gwin32.c (g_win32_getlocale): Use "sp" for
LANG_CROATIAN+SUBLANG_SERBIAN_LATIN.
* makefile.{mingw,msc}.in (glib_OBJECTS): Add new files.
Add gspawn-win32-helper.exe rule.
* tests/makefile.{mingw,msc}.in (TESTS): Add shell-test and
spawn-test.
* tests/spawn-test.c: (run_tests): On Win32, don't try to run
/bin/sh, but ipconfig (no special significance in choosing that,
just a program that outputs something to stdout).
2000-10-16 18:54:29 +00:00
# ifndef G_OS_WIN32
2000-10-09 16:24:57 +00:00
static gboolean
2013-12-24 23:24:40 -05:00
get_contents_regfile ( const gchar * filename ,
2008-12-31 05:51:47 +00:00
struct stat * stat_buf ,
gint fd ,
gchar * * contents ,
gsize * length ,
GError * * error )
2000-10-09 16:24:57 +00:00
{
gchar * buf ;
2006-12-28 04:48:06 +00:00
gsize bytes_read ;
gsize size ;
gsize alloc_size ;
2013-12-24 23:24:40 -05:00
gchar * display_filename ;
2001-12-18 18:46:41 +00:00
2000-10-09 16:24:57 +00:00
size = stat_buf - > st_size ;
2001-12-18 18:46:41 +00:00
alloc_size = size + 1 ;
buf = g_try_malloc ( alloc_size ) ;
if ( buf = = NULL )
{
2013-12-24 23:24:40 -05:00
display_filename = g_filename_display_name ( filename ) ;
2001-12-18 18:46:41 +00:00
g_set_error ( error ,
G_FILE_ERROR ,
G_FILE_ERROR_NOMEM ,
2013-01-25 00:17:18 +01:00
g_dngettext ( GETTEXT_PACKAGE , " Could not allocate %lu byte to read file \" %s \" " , " Could not allocate %lu bytes to read file \" %s \" " , ( gulong ) alloc_size ) ,
2004-09-30 04:03:16 +00:00
( gulong ) alloc_size ,
2004-11-04 00:37:47 +00:00
display_filename ) ;
2013-12-24 23:24:40 -05:00
g_free ( display_filename ) ;
2002-03-20 16:21:58 +00:00
goto error ;
2001-12-18 18:46:41 +00:00
}
2000-10-09 16:24:57 +00:00
bytes_read = 0 ;
while ( bytes_read < size )
{
Changes for 64-bit cleanliness, loosely based on patch from Mark Murnane.
Wed Jun 20 12:00:54 2001 Owen Taylor <otaylor@redhat.com>
Changes for 64-bit cleanliness, loosely based on patch
from Mark Murnane.
* gconvert.c (g_convert/g_convert_with_fallback): Remove
workarounds for since-fixed GNU libc bugs. Minor
doc fix.
* gconvert.[ch]: Change gint to gsize/gssize as
appropriate.
* gconvert.c (g_locale/filename_to/from_utf8): Fix incorrect
computation of bytes_read / bytes_written.
* gfileutils.[ch] (g_file_get_contents): Make length
out parameter 'gsize *len'.
* ghook.c (g_hook_compare_ids): Don't compare a
and b as 'a - b'.
* gmacros.h (GSIZE_TO_POINTER): Add GPOINTER_TO_SIZE,
GSIZE_TO_POINTER.
* gmain.c (g_timeout_prepare): Rewrite to avoid
overflows. (Fixes bug when system clock skews
backwards more than 24 days.)
* gmarkup.[ch]: Make lengths passed to callbacks
gsize, length for g_markup_parse-context_parse(),
g_markup_escape_text() gssize.
* gmessages.[ch] (g_printf_string_upper_bound): Change
return value to gsize.
* gmessages.c (printf_string_upper_bound): Remove
a ridiculous use of 'inline' on a 300 line function.
* gstring.[ch]: Represent size of string as a gsize,
not gint. Make parameters to functions take gsize,
or gssize where -1 is allowed.
* gstring.c (g_string_erase): Make
g_string_erase (string, pos, -1) a synonym for
g_string_truncate for consistency with other G*
APIs.
* gstrfuncs.[ch]: Make all functions taking a string
length, take a gsize, or gssize if -1 is allowed.
(g_strstr_len, g_strrstr_len). Also fix some boundary
conditions in g_str[r]str[_len].
* gutf8.c tests/unicode-encoding.c: Make parameters that
are byte lengths gsize, gssize as appropriate. Make
character offsets, other counts, glong.
* gasyncqueue.c gcompletion.c
timeloop.c timeloop-basic.c gutils.c gspawn.c.
Small 64 bit cleanliness fixups.
* glist.c (g_list_sort2, g_list_sort_real): Fix functions
that should have been static.
* gdate.c (g_date_fill_parse_tokens): Fix extra
declaration that was shadowing another.
* tests/module-test.c: Include string.h
Mon Jun 18 15:43:29 2001 Owen Taylor <otaylor@redhat.com>
* gutf8.c (g_get_charset): Make argument
G_CONST_RETURN char **.
2001-06-23 13:55:09 +00:00
gssize rc ;
2000-10-09 16:24:57 +00:00
rc = read ( fd , buf + bytes_read , size - bytes_read ) ;
if ( rc < 0 )
{
if ( errno ! = EINTR )
{
2005-02-02 23:28:18 +00:00
int save_errno = errno ;
2004-10-06 15:05:40 +00:00
g_free ( buf ) ;
2013-12-24 23:24:40 -05:00
display_filename = g_filename_display_name ( filename ) ;
2000-10-09 16:24:57 +00:00
g_set_error ( error ,
G_FILE_ERROR ,
2005-02-02 23:28:18 +00:00
g_file_error_from_errno ( save_errno ) ,
2000-10-09 16:24:57 +00:00
_ ( " Failed to read from file '%s': %s " ) ,
2004-11-04 00:37:47 +00:00
display_filename ,
2005-02-02 23:28:18 +00:00
g_strerror ( save_errno ) ) ;
2013-12-24 23:24:40 -05:00
g_free ( display_filename ) ;
2002-03-20 16:21:58 +00:00
goto error ;
2000-10-09 16:24:57 +00:00
}
}
else if ( rc = = 0 )
break ;
else
bytes_read + = rc ;
}
buf [ bytes_read ] = ' \0 ' ;
if ( length )
* length = bytes_read ;
* contents = buf ;
2002-03-20 16:21:58 +00:00
close ( fd ) ;
2000-10-09 16:24:57 +00:00
return TRUE ;
2002-03-20 16:21:58 +00:00
error :
close ( fd ) ;
return FALSE ;
2000-10-09 16:24:57 +00:00
}
static gboolean
2008-12-31 05:51:47 +00:00
get_contents_posix ( const gchar * filename ,
gchar * * contents ,
gsize * length ,
GError * * error )
2000-10-09 16:24:57 +00:00
{
struct stat stat_buf ;
gint fd ;
2004-10-27 16:46:29 +00:00
2001-03-09 21:18:33 +00:00
/* O_BINARY useful on Cygwin */
fd = open ( filename , O_RDONLY | O_BINARY ) ;
2000-10-09 16:24:57 +00:00
if ( fd < 0 )
{
2014-04-21 15:55:59 +00:00
int saved_errno = errno ;
2013-12-24 23:24:40 -05:00
set_file_error ( error ,
filename ,
2014-04-21 15:55:59 +00:00
_ ( " Failed to open file '%s': %s " ) ,
saved_errno ) ;
2000-10-09 16:24:57 +00:00
return FALSE ;
}
/* I don't think this will ever fail, aside from ENOMEM, but. */
if ( fstat ( fd , & stat_buf ) < 0 )
{
2014-04-21 15:55:59 +00:00
int saved_errno = errno ;
2013-12-24 23:24:40 -05:00
set_file_error ( error ,
filename ,
2014-04-21 15:55:59 +00:00
_ ( " Failed to get attributes of file '%s': fstat() failed: %s " ) ,
saved_errno ) ;
2004-10-06 15:05:40 +00:00
close ( fd ) ;
2000-10-09 16:24:57 +00:00
return FALSE ;
}
if ( stat_buf . st_size > 0 & & S_ISREG ( stat_buf . st_mode ) )
{
2013-12-24 23:24:40 -05:00
gboolean retval = get_contents_regfile ( filename ,
2004-10-27 16:46:29 +00:00
& stat_buf ,
fd ,
contents ,
length ,
error ) ;
return retval ;
2000-10-09 16:24:57 +00:00
}
else
{
FILE * f ;
2004-10-27 16:46:29 +00:00
gboolean retval ;
2000-10-09 16:24:57 +00:00
f = fdopen ( fd , " r " ) ;
if ( f = = NULL )
{
2014-04-21 15:55:59 +00:00
int saved_errno = errno ;
2013-12-24 23:24:40 -05:00
set_file_error ( error ,
filename ,
2014-04-21 15:55:59 +00:00
_ ( " Failed to open file '%s': fdopen() failed: %s " ) ,
saved_errno ) ;
2004-09-30 04:03:16 +00:00
2000-10-09 16:24:57 +00:00
return FALSE ;
}
2013-12-24 23:24:40 -05:00
retval = get_contents_stdio ( filename , f , contents , length , error ) ;
2004-10-27 16:46:29 +00:00
return retval ;
2000-10-09 16:24:57 +00:00
}
}
Some more debugging output. (g_io_channel_win32_poll): Remove unused vars.
2000-10-16 Tor Lillqvist <tml@iki.fi>
* giowin32.c (reader_thread): Some more debugging output.
(g_io_channel_win32_poll): Remove unused vars.
* gfileutils.c: Changes for Win32, with no unistd.h and no
S_ISLNK().
* gspawn-win32.c: Implementation of the g_spwan_* functions for
Win32. Due to the general non-Unixness of Win32, much of the
functionality that is relatively clean to implement on Unix, is
hard to do on Win32. We must use a separate helper program to
change directory, close extra file descriptors, redirect the std
ones, as needed, and only then start the child process. No child
process pid can be returned, unfortunately. Or if we used
CreateProcess directly, it probably could. (Now we use the spawnv*
functions from msvcrt.)
* glib.def: Add new entry points.
* glib.def
* giowin32.c: Remove g_io_channel_win32_wait_for_condition(),
g_io_channel_win32_poll() subsumes it.
* gbacktrace.h: G_BREAKPOINT for MSVC (on the ix86).
* gwin32.c (g_win32_getlocale): Use "sp" for
LANG_CROATIAN+SUBLANG_SERBIAN_LATIN.
* makefile.{mingw,msc}.in (glib_OBJECTS): Add new files.
Add gspawn-win32-helper.exe rule.
* tests/makefile.{mingw,msc}.in (TESTS): Add shell-test and
spawn-test.
* tests/spawn-test.c: (run_tests): On Win32, don't try to run
/bin/sh, but ipconfig (no special significance in choosing that,
just a program that outputs something to stdout).
2000-10-16 18:54:29 +00:00
# else /* G_OS_WIN32 */
2000-10-09 16:24:57 +00:00
static gboolean
2008-12-31 05:51:47 +00:00
get_contents_win32 ( const gchar * filename ,
gchar * * contents ,
gsize * length ,
GError * * error )
2000-10-09 16:24:57 +00:00
{
FILE * f ;
2004-10-27 16:46:29 +00:00
gboolean retval ;
2005-02-24 23:46:36 +00:00
f = g_fopen ( filename , " rb " ) ;
2000-10-09 16:24:57 +00:00
if ( f = = NULL )
{
2014-04-21 15:55:59 +00:00
int saved_errno = errno ;
2013-12-24 23:24:40 -05:00
set_file_error ( error ,
filename ,
2014-04-21 15:55:59 +00:00
_ ( " Failed to open file '%s': %s " ) ,
saved_errno ) ;
2004-09-30 04:03:16 +00:00
2000-10-09 16:24:57 +00:00
return FALSE ;
}
2013-12-24 23:24:40 -05:00
retval = get_contents_stdio ( filename , f , contents , length , error ) ;
2004-10-27 16:46:29 +00:00
return retval ;
2000-10-09 16:24:57 +00:00
}
Some more debugging output. (g_io_channel_win32_poll): Remove unused vars.
2000-10-16 Tor Lillqvist <tml@iki.fi>
* giowin32.c (reader_thread): Some more debugging output.
(g_io_channel_win32_poll): Remove unused vars.
* gfileutils.c: Changes for Win32, with no unistd.h and no
S_ISLNK().
* gspawn-win32.c: Implementation of the g_spwan_* functions for
Win32. Due to the general non-Unixness of Win32, much of the
functionality that is relatively clean to implement on Unix, is
hard to do on Win32. We must use a separate helper program to
change directory, close extra file descriptors, redirect the std
ones, as needed, and only then start the child process. No child
process pid can be returned, unfortunately. Or if we used
CreateProcess directly, it probably could. (Now we use the spawnv*
functions from msvcrt.)
* glib.def: Add new entry points.
* glib.def
* giowin32.c: Remove g_io_channel_win32_wait_for_condition(),
g_io_channel_win32_poll() subsumes it.
* gbacktrace.h: G_BREAKPOINT for MSVC (on the ix86).
* gwin32.c (g_win32_getlocale): Use "sp" for
LANG_CROATIAN+SUBLANG_SERBIAN_LATIN.
* makefile.{mingw,msc}.in (glib_OBJECTS): Add new files.
Add gspawn-win32-helper.exe rule.
* tests/makefile.{mingw,msc}.in (TESTS): Add shell-test and
spawn-test.
* tests/spawn-test.c: (run_tests): On Win32, don't try to run
/bin/sh, but ipconfig (no special significance in choosing that,
just a program that outputs something to stdout).
2000-10-16 18:54:29 +00:00
2000-10-09 16:24:57 +00:00
# endif
/**
* g_file_get_contents :
2011-05-31 12:00:41 -04:00
* @ filename : ( type filename ) : name of a file to read contents from , in the GLib file name encoding
* @ contents : ( out ) ( array length = length ) ( element - type guint8 ) : location to store an allocated string , use g_free ( ) to free
2009-02-23 04:23:14 +00:00
* the returned string
2011-05-31 12:00:41 -04:00
* @ length : ( allow - none ) : location to store length in bytes of the contents , or % NULL
2005-01-03 18:56:20 +00:00
* @ error : return location for a # GError , or % NULL
2009-02-23 04:23:14 +00:00
*
2000-10-09 16:24:57 +00:00
* Reads an entire file into allocated memory , with good error
2009-02-23 04:23:14 +00:00
* checking .
2000-10-09 16:24:57 +00:00
*
2009-02-23 04:23:14 +00:00
* If the call was successful , it returns % TRUE and sets @ contents to the file
* contents and @ length to the length of the file contents in bytes . The string
* stored in @ contents will be nul - terminated , so for text files you can pass
* % NULL for the @ length argument . If the call was not successful , it returns
* % FALSE and sets @ error . The error domain is # G_FILE_ERROR . Possible error
* codes are those in the # GFileError enumeration . In the error case ,
2005-01-03 18:56:20 +00:00
* @ contents is set to % NULL and @ length is set to zero .
*
2014-02-19 19:35:23 -05:00
* Returns : % TRUE on success , % FALSE if an error occurred
2000-10-09 16:24:57 +00:00
* */
gboolean
2008-12-31 05:51:47 +00:00
g_file_get_contents ( const gchar * filename ,
gchar * * contents ,
gsize * length ,
GError * * error )
2000-10-09 16:24:57 +00:00
{
g_return_val_if_fail ( filename ! = NULL , FALSE ) ;
g_return_val_if_fail ( contents ! = NULL , FALSE ) ;
* contents = NULL ;
if ( length )
* length = 0 ;
# ifdef G_OS_WIN32
return get_contents_win32 ( filename , contents , length , error ) ;
# else
return get_contents_posix ( filename , contents , length , error ) ;
# endif
}
2000-10-30 22:06:22 +00:00
2005-03-08 20:51:49 +00:00
static gboolean
2008-12-31 05:51:47 +00:00
rename_file ( const char * old_name ,
const char * new_name ,
GError * * err )
2005-03-08 20:51:49 +00:00
{
errno = 0 ;
if ( g_rename ( old_name , new_name ) = = - 1 )
{
int save_errno = errno ;
gchar * display_old_name = g_filename_display_name ( old_name ) ;
gchar * display_new_name = g_filename_display_name ( new_name ) ;
2005-04-17 00:16:51 +00:00
2005-03-08 20:51:49 +00:00
g_set_error ( err ,
G_FILE_ERROR ,
g_file_error_from_errno ( save_errno ) ,
_ ( " Failed to rename file '%s' to '%s': g_rename() failed: %s " ) ,
display_old_name ,
display_new_name ,
g_strerror ( save_errno ) ) ;
g_free ( display_old_name ) ;
g_free ( display_new_name ) ;
return FALSE ;
}
return TRUE ;
}
static gchar *
2008-12-31 05:51:47 +00:00
write_to_temp_file ( const gchar * contents ,
gssize length ,
2009-03-16 16:03:13 +00:00
const gchar * dest_file ,
2008-12-31 05:51:47 +00:00
GError * * err )
2005-03-08 20:51:49 +00:00
{
gchar * tmp_name ;
gchar * retval ;
gint fd ;
retval = NULL ;
2013-06-03 16:16:25 -04:00
2009-03-16 16:03:13 +00:00
tmp_name = g_strdup_printf ( " %s.XXXXXX " , dest_file ) ;
2005-03-08 20:51:49 +00:00
errno = 0 ;
2009-09-03 15:36:37 +02:00
fd = g_mkstemp_full ( tmp_name , O_RDWR | O_BINARY , 0666 ) ;
2007-07-09 05:32:15 +00:00
2005-03-08 20:51:49 +00:00
if ( fd = = - 1 )
{
2014-04-21 15:55:59 +00:00
int saved_errno = errno ;
set_file_error ( err ,
tmp_name , _ ( " Failed to create file '%s': %s " ) ,
saved_errno ) ;
2005-03-08 20:51:49 +00:00
goto out ;
}
2013-06-03 22:55:20 -04:00
# ifdef HAVE_FALLOCATE
2005-03-08 20:51:49 +00:00
if ( length > 0 )
{
2013-06-03 15:43:01 -04:00
/* We do this on a 'best effort' basis... It may not be supported
* on the underlying filesystem .
*/
2013-06-03 22:55:20 -04:00
( void ) fallocate ( fd , 0 , 0 , length ) ;
2013-06-03 17:49:06 -04:00
}
2013-06-03 15:43:01 -04:00
# endif
2013-06-03 17:49:06 -04:00
while ( length > 0 )
{
gssize s ;
2013-06-03 16:16:25 -04:00
2013-06-03 17:49:06 -04:00
s = write ( fd , contents , length ) ;
2005-04-17 00:16:51 +00:00
2013-06-03 17:49:06 -04:00
if ( s < 0 )
2013-06-03 16:16:25 -04:00
{
2014-04-21 15:55:59 +00:00
int saved_errno = errno ;
if ( saved_errno = = EINTR )
2013-06-03 17:49:06 -04:00
continue ;
2014-04-21 15:55:59 +00:00
set_file_error ( err ,
tmp_name , _ ( " Failed to write file '%s': write() failed: %s " ) ,
saved_errno ) ;
2013-06-03 17:49:06 -04:00
close ( fd ) ;
2013-06-03 16:16:25 -04:00
g_unlink ( tmp_name ) ;
2013-06-03 17:49:06 -04:00
2013-06-03 16:16:25 -04:00
goto out ;
}
2009-03-16 16:03:13 +00:00
2013-06-03 17:49:06 -04:00
g_assert ( s < = length ) ;
2013-06-03 16:16:25 -04:00
2013-06-03 17:49:06 -04:00
contents + = s ;
length - = s ;
2009-03-16 16:03:13 +00:00
}
2010-12-18 18:52:32 -05:00
2011-01-04 09:38:14 -05:00
# ifdef BTRFS_SUPER_MAGIC
2010-12-18 18:52:32 -05:00
{
struct statfs buf ;
/* On Linux, on btrfs, skip the fsync since rename-over-existing is
* guaranteed to be atomic and this is the only case in which we
* would fsync ( ) anyway .
*/
2013-06-20 13:13:29 -04:00
if ( fstatfs ( fd , & buf ) = = 0 & & buf . f_type = = BTRFS_SUPER_MAGIC )
2010-12-18 18:52:32 -05:00
goto no_fsync ;
}
# endif
2013-06-03 16:16:25 -04:00
2009-03-16 16:03:13 +00:00
# ifdef HAVE_FSYNC
2009-08-11 20:22:51 +02:00
{
struct stat statbuf ;
errno = 0 ;
/* If the final destination exists and is > 0 bytes, we want to sync the
* newly written file to ensure the data is on disk when we rename over
* the destination . Otherwise if we get a system crash we can lose both
* the new and the old file on some filesystems . ( I . E . those that don ' t
* guarantee the data is written to the disk before the metadata . )
*/
2013-06-03 17:49:06 -04:00
if ( g_lstat ( dest_file , & statbuf ) = = 0 & & statbuf . st_size > 0 & & fsync ( fd ) ! = 0 )
2009-08-11 20:22:51 +02:00
{
2014-04-21 15:55:59 +00:00
int saved_errno = errno ;
set_file_error ( err ,
tmp_name , _ ( " Failed to write file '%s': fsync() failed: %s " ) ,
saved_errno ) ;
2013-06-03 17:49:06 -04:00
close ( fd ) ;
2013-06-03 16:16:25 -04:00
g_unlink ( tmp_name ) ;
2009-08-11 20:22:51 +02:00
2013-06-03 16:16:25 -04:00
goto out ;
2009-08-11 20:22:51 +02:00
}
}
2009-03-16 16:03:13 +00:00
# endif
2011-09-04 17:17:11 -04:00
# ifdef BTRFS_SUPER_MAGIC
2010-12-18 18:52:32 -05:00
no_fsync :
2011-09-04 17:17:11 -04:00
# endif
2013-06-03 16:16:25 -04:00
2005-03-08 20:51:49 +00:00
errno = 0 ;
2013-06-03 17:59:29 -04:00
if ( ! g_close ( fd , err ) )
2013-06-03 16:16:25 -04:00
{
2005-03-08 20:51:49 +00:00
g_unlink ( tmp_name ) ;
2013-06-03 16:16:25 -04:00
2005-03-08 20:51:49 +00:00
goto out ;
}
2005-04-17 00:16:51 +00:00
retval = g_strdup ( tmp_name ) ;
2013-06-03 16:16:25 -04:00
2005-03-08 20:51:49 +00:00
out :
g_free ( tmp_name ) ;
2013-06-03 16:16:25 -04:00
2005-03-08 20:51:49 +00:00
return retval ;
}
/**
2005-05-05 14:57:29 +00:00
* g_file_set_contents :
2011-05-31 12:00:41 -04:00
* @ filename : ( type filename ) : name of a file to write @ contents to , in the GLib file name
2005-03-08 20:51:49 +00:00
* encoding
2011-05-31 12:00:41 -04:00
* @ contents : ( array length = length ) ( element - type guint8 ) : string to write to the file
2005-03-08 20:51:49 +00:00
* @ length : length of @ contents , or - 1 if @ contents is a nul - terminated string
* @ error : return location for a # GError , or % NULL
*
* Writes all of @ contents to a file named @ filename , with good error checking .
* If a file called @ filename already exists it will be overwritten .
*
* This write is atomic in the sense that it is first written to a temporary
* file which is then renamed to the final name . Notes :
2014-02-01 10:13:41 -05:00
*
* - On UNIX , if @ filename already exists hard links to @ filename will break .
* Also since the file is recreated , existing permissions , access control
* lists , metadata etc . may be lost . If @ filename is a symbolic link ,
* the link itself will be replaced , not the linked file .
*
* - On Windows renaming a file will not remove an existing file with the
2005-03-08 20:51:49 +00:00
* new name , so on Windows there is a race condition between the existing
* file being removed and the temporary file being renamed .
2014-02-01 10:13:41 -05:00
*
* - On Windows there is no way to remove a file that is open to some
2005-03-08 20:51:49 +00:00
* process , or mapped into memory . Thus , this function will fail if
* @ filename already exists and is open .
*
2011-08-29 14:49:32 -04:00
* If the call was successful , it returns % TRUE . If the call was not successful ,
2005-03-08 20:51:49 +00:00
* it returns % FALSE and sets @ error . The error domain is # G_FILE_ERROR .
* Possible error codes are those in the # GFileError enumeration .
*
2010-08-26 00:00:56 -04:00
* Note that the name for the temporary file is constructed by appending up
* to 7 characters to @ filename .
*
2014-02-19 19:35:23 -05:00
* Returns : % TRUE on success , % FALSE if an error occurred
2005-03-08 20:51:49 +00:00
*
* Since : 2.8
2014-02-01 10:13:41 -05:00
*/
2005-03-08 20:51:49 +00:00
gboolean
2008-12-31 05:51:47 +00:00
g_file_set_contents ( const gchar * filename ,
const gchar * contents ,
gssize length ,
GError * * error )
2005-03-08 20:51:49 +00:00
{
2005-03-09 11:22:09 +00:00
gchar * tmp_filename ;
2005-03-08 20:51:49 +00:00
gboolean retval ;
GError * rename_error = NULL ;
g_return_val_if_fail ( filename ! = NULL , FALSE ) ;
g_return_val_if_fail ( error = = NULL | | * error = = NULL , FALSE ) ;
g_return_val_if_fail ( contents ! = NULL | | length = = 0 , FALSE ) ;
2005-03-12 05:45:32 +00:00
g_return_val_if_fail ( length > = - 1 , FALSE ) ;
2005-03-08 20:51:49 +00:00
if ( length = = - 1 )
length = strlen ( contents ) ;
tmp_filename = write_to_temp_file ( contents , length , filename , error ) ;
if ( ! tmp_filename )
{
retval = FALSE ;
goto out ;
}
if ( ! rename_file ( tmp_filename , filename , & rename_error ) )
{
# ifndef G_OS_WIN32
g_unlink ( tmp_filename ) ;
g_propagate_error ( error , rename_error ) ;
retval = FALSE ;
goto out ;
# else /* G_OS_WIN32 */
/* Renaming failed, but on Windows this may just mean
* the file already exists . So if the target file
* exists , try deleting it and do the rename again .
*/
if ( ! g_file_test ( filename , G_FILE_TEST_EXISTS ) )
{
g_unlink ( tmp_filename ) ;
g_propagate_error ( error , rename_error ) ;
retval = FALSE ;
goto out ;
}
g_error_free ( rename_error ) ;
if ( g_unlink ( filename ) = = - 1 )
{
2014-04-21 15:55:59 +00:00
int saved_errno = errno ;
2013-12-24 23:24:40 -05:00
set_file_error ( error ,
filename ,
2014-04-21 15:55:59 +00:00
_ ( " Existing file '%s' could not be removed: g_unlink() failed: %s " ) ,
saved_errno ) ;
2005-03-08 20:51:49 +00:00
g_unlink ( tmp_filename ) ;
retval = FALSE ;
goto out ;
}
if ( ! rename_file ( tmp_filename , filename , error ) )
{
g_unlink ( tmp_filename ) ;
retval = FALSE ;
goto out ;
}
# endif
}
retval = TRUE ;
out :
g_free ( tmp_filename ) ;
return retval ;
}
2000-11-05 16:38:16 +00:00
/*
2011-08-14 14:09:58 -04:00
* get_tmp_file based on the mkstemp implementation from the GNU C library .
2000-11-05 16:38:16 +00:00
* Copyright ( C ) 1991 , 92 , 93 , 94 , 95 , 96 , 97 , 98 , 99 Free Software Foundation , Inc .
*/
2012-11-05 12:22:49 -05:00
typedef gint ( * GTmpFileCallback ) ( const gchar * , gint , gint ) ;
2011-08-14 14:09:58 -04:00
static gint
get_tmp_file ( gchar * tmpl ,
GTmpFileCallback f ,
int flags ,
int mode )
2000-10-30 22:06:22 +00:00
{
char * XXXXXX ;
int count , fd ;
static const char letters [ ] =
2000-11-10 23:43:33 +00:00
" ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 " ;
static const int NLETTERS = sizeof ( letters ) - 1 ;
2000-10-30 22:06:22 +00:00
glong value ;
GTimeVal tv ;
2000-11-11 13:46:15 +00:00
static int counter = 0 ;
2000-10-30 22:06:22 +00:00
2009-09-03 15:36:37 +02:00
g_return_val_if_fail ( tmpl ! = NULL , - 1 ) ;
2006-06-16 15:12:32 +00:00
/* find the last occurrence of "XXXXXX" */
XXXXXX = g_strrstr ( tmpl , " XXXXXX " ) ;
if ( ! XXXXXX | | strncmp ( XXXXXX , " XXXXXX " , 6 ) )
2005-02-02 23:28:18 +00:00
{
errno = EINVAL ;
return - 1 ;
}
2000-10-30 22:06:22 +00:00
/* Get some more or less random data. */
g_get_current_time ( & tv ) ;
2000-11-11 13:46:15 +00:00
value = ( tv . tv_usec ^ tv . tv_sec ) + counter + + ;
2000-10-30 22:06:22 +00:00
for ( count = 0 ; count < 100 ; value + = 7777 , + + count )
{
glong v = value ;
/* Fill in the random bits. */
2000-11-10 23:43:33 +00:00
XXXXXX [ 0 ] = letters [ v % NLETTERS ] ;
v / = NLETTERS ;
XXXXXX [ 1 ] = letters [ v % NLETTERS ] ;
v / = NLETTERS ;
XXXXXX [ 2 ] = letters [ v % NLETTERS ] ;
v / = NLETTERS ;
XXXXXX [ 3 ] = letters [ v % NLETTERS ] ;
v / = NLETTERS ;
XXXXXX [ 4 ] = letters [ v % NLETTERS ] ;
v / = NLETTERS ;
XXXXXX [ 5 ] = letters [ v % NLETTERS ] ;
2000-10-30 22:06:22 +00:00
2011-08-14 14:09:58 -04:00
fd = f ( tmpl , flags , mode ) ;
2000-10-30 22:06:22 +00:00
if ( fd > = 0 )
2011-08-14 14:09:58 -04:00
return fd ;
2000-10-30 22:06:22 +00:00
else if ( errno ! = EEXIST )
2011-08-14 14:09:58 -04:00
/* Any other error will apply also to other names we might
* try , and there are 2 ^ 32 or so of them , so give up now .
*/
return - 1 ;
2000-10-30 22:06:22 +00:00
}
/* We got out of the loop because we ran out of combinations to try. */
2005-02-02 23:28:18 +00:00
errno = EEXIST ;
2000-10-30 22:06:22 +00:00
return - 1 ;
2005-12-03 06:10:52 +00:00
}
2012-11-05 12:22:49 -05:00
/* Some GTmpFileCallback implementations.
*
* Note : we cannot use open ( ) or g_open ( ) directly because even though
* they appear compatible , they may be vararg functions and calling
* varargs functions through a non - varargs type is undefined .
*/
2011-10-16 21:17:10 -04:00
static gint
2012-11-05 12:22:49 -05:00
wrap_g_mkdir ( const gchar * filename ,
int flags G_GNUC_UNUSED ,
int mode )
2011-08-14 14:09:58 -04:00
{
/* tmpl is in UTF-8 on Windows, thus use g_mkdir() */
2012-11-05 12:22:49 -05:00
return g_mkdir ( filename , mode ) ;
}
static gint
wrap_g_open ( const gchar * filename ,
int flags ,
int mode )
{
return g_open ( filename , flags , mode ) ;
2011-08-14 14:09:58 -04:00
}
2005-12-03 06:10:52 +00:00
/**
2011-08-14 14:09:58 -04:00
* g_mkdtemp_full :
2011-08-22 11:37:48 -04:00
* @ tmpl : ( type filename ) : template directory name
2011-08-14 14:09:58 -04:00
* @ mode : permissions to create the temporary directory with
*
* Creates a temporary directory . See the mkdtemp ( ) documentation
* on most UNIX - like systems .
*
* The parameter is a string that should follow the rules for
* mkdtemp ( ) templates , i . e . contain the string " XXXXXX " .
* g_mkdtemp ( ) is slightly more flexible than mkdtemp ( ) in that the
* sequence does not have to occur at the very end of the template
* and you can pass a @ mode . The X string will be modified to form
* the name of a directory that didn ' t exist . The string should be
* in the GLib file name encoding . Most importantly , on Windows it
* should be in UTF - 8.
*
2014-02-19 19:35:23 -05:00
* Returns : A pointer to @ tmpl , which has been modified
2011-08-22 11:37:48 -04:00
* to hold the directory name . In case of errors , % NULL is
* returned , and % errno will be set .
2011-08-14 14:09:58 -04:00
*
2011-12-29 11:57:42 -05:00
* Since : 2.30
2011-08-14 14:09:58 -04:00
*/
gchar *
g_mkdtemp_full ( gchar * tmpl ,
gint mode )
{
2012-11-05 12:22:49 -05:00
if ( get_tmp_file ( tmpl , wrap_g_mkdir , 0 , mode ) = = - 1 )
2011-08-14 14:09:58 -04:00
return NULL ;
else
return tmpl ;
}
/**
* g_mkdtemp :
2011-08-22 11:37:48 -04:00
* @ tmpl : ( type filename ) : template directory name
2011-08-14 14:09:58 -04:00
*
* Creates a temporary directory . See the mkdtemp ( ) documentation
* on most UNIX - like systems .
*
* The parameter is a string that should follow the rules for
* mkdtemp ( ) templates , i . e . contain the string " XXXXXX " .
* g_mkdtemp ( ) is slightly more flexible than mkdtemp ( ) in that the
* sequence does not have to occur at the very end of the template
* and you can pass a @ mode and additional @ flags . The X string will
* be modified to form the name of a directory that didn ' t exist .
* The string should be in the GLib file name encoding . Most importantly ,
* on Windows it should be in UTF - 8.
*
2014-02-19 19:35:23 -05:00
* Returns : A pointer to @ tmpl , which has been modified
2011-08-22 11:37:48 -04:00
* to hold the directory name . In case of errors , % NULL is
* returned and % errno will be set .
2011-08-14 14:09:58 -04:00
*
2011-12-29 11:57:42 -05:00
* Since : 2.30
2011-08-14 14:09:58 -04:00
*/
gchar *
g_mkdtemp ( gchar * tmpl )
{
return g_mkdtemp_full ( tmpl , 0700 ) ;
}
/**
* g_mkstemp_full :
2011-08-22 11:37:48 -04:00
* @ tmpl : ( type filename ) : template filename
2011-08-14 14:09:58 -04:00
* @ flags : flags to pass to an open ( ) call in addition to O_EXCL
* and O_CREAT , which are passed automatically
* @ mode : permissions to create the temporary file with
2005-12-03 06:10:52 +00:00
*
* Opens a temporary file . See the mkstemp ( ) documentation
2011-08-14 14:09:58 -04:00
* on most UNIX - like systems .
2005-12-03 06:10:52 +00:00
*
2006-06-16 15:12:32 +00:00
* The parameter is a string that should follow the rules for
2011-08-14 14:09:58 -04:00
* mkstemp ( ) templates , i . e . contain the string " XXXXXX " .
* g_mkstemp_full ( ) is slightly more flexible than mkstemp ( )
* in that the sequence does not have to occur at the very end of the
* template and you can pass a @ mode and additional @ flags . The X
* string will be modified to form the name of a file that didn ' t exist .
* The string should be in the GLib file name encoding . Most importantly ,
2005-12-03 06:10:52 +00:00
* on Windows it should be in UTF - 8.
*
2014-02-19 19:35:23 -05:00
* Returns : A file handle ( as from open ( ) ) to the file
2011-08-14 14:09:58 -04:00
* opened for reading and writing . The file handle should be
2011-08-22 11:37:48 -04:00
* closed with close ( ) . In case of errors , - 1 is returned
* and % errno will be set .
2011-08-14 14:09:58 -04:00
*
* Since : 2.22
*/
2005-12-03 06:10:52 +00:00
gint
2011-08-14 14:09:58 -04:00
g_mkstemp_full ( gchar * tmpl ,
gint flags ,
gint mode )
2005-12-03 06:10:52 +00:00
{
2011-08-14 14:09:58 -04:00
/* tmpl is in UTF-8 on Windows, thus use g_open() */
2012-11-05 12:22:49 -05:00
return get_tmp_file ( tmpl , wrap_g_open ,
2011-08-14 14:09:58 -04:00
flags | O_CREAT | O_EXCL , mode ) ;
2000-10-30 22:06:22 +00:00
}
2000-11-10 23:43:33 +00:00
/**
2011-08-14 14:09:58 -04:00
* g_mkstemp :
2011-08-22 11:37:48 -04:00
* @ tmpl : ( type filename ) : template filename
2000-11-10 23:43:33 +00:00
*
2011-08-14 14:09:58 -04:00
* Opens a temporary file . See the mkstemp ( ) documentation
* on most UNIX - like systems .
2000-11-10 23:49:37 +00:00
*
2011-08-14 14:09:58 -04:00
* The parameter is a string that should follow the rules for
* mkstemp ( ) templates , i . e . contain the string " XXXXXX " .
* g_mkstemp ( ) is slightly more flexible than mkstemp ( ) in that the
* sequence does not have to occur at the very end of the template .
* The X string will be modified to form the name of a file that
* didn ' t exist . The string should be in the GLib file name encoding .
* Most importantly , on Windows it should be in UTF - 8.
2000-11-10 23:43:33 +00:00
*
2014-02-19 19:35:23 -05:00
* Returns : A file handle ( as from open ( ) ) to the file
2011-08-14 14:09:58 -04:00
* opened for reading and writing . The file is opened in binary
* mode on platforms where there is a difference . The file handle
2011-08-22 11:37:48 -04:00
* should be closed with close ( ) . In case of errors , - 1 is
* returned and % errno will be set .
2011-08-14 14:09:58 -04:00
*/
Use gchar, gint, gsize instead of char, int, size_t in the interface for
2003-07-29 Matthias Clasen <maclas@gmx.de>
* glib/gqsort.[hc] (g_qsort_with_data):
* glib/gconvert.[hc] (g_filename_to_uri, g_filename_from_uri):
* glib/gfileutils.[hc] (g_mkstemp, g_file_open_tmp): Use gchar, gint, gsize instead of char, int, size_t
in the interface for consistency. (#118567)
2003-07-29 18:59:23 +00:00
gint
2011-08-14 14:09:58 -04:00
g_mkstemp ( gchar * tmpl )
{
return g_mkstemp_full ( tmpl , O_RDWR | O_BINARY , 0600 ) ;
}
static gint
g_get_tmp_name ( const gchar * tmpl ,
gchar * * name_used ,
GTmpFileCallback f ,
gint flags ,
gint mode ,
GError * * error )
2000-11-10 23:43:33 +00:00
{
int retval ;
2001-02-17 23:30:48 +00:00
const char * tmpdir ;
2008-12-31 05:51:47 +00:00
const char * sep ;
2000-11-10 23:43:33 +00:00
char * fulltemplate ;
2003-08-16 19:45:25 +00:00
const char * slash ;
2000-11-10 23:43:33 +00:00
2000-11-12 20:38:19 +00:00
if ( tmpl = = NULL )
tmpl = " .XXXXXX " ;
2000-11-10 23:43:33 +00:00
2003-08-16 19:45:25 +00:00
if ( ( slash = strchr ( tmpl , G_DIR_SEPARATOR ) ) ! = NULL
2001-01-05 19:30:13 +00:00
# ifdef G_OS_WIN32
2003-08-16 19:45:25 +00:00
| | ( strchr ( tmpl , ' / ' ) ! = NULL & & ( slash = " / " ) )
2001-01-05 19:30:13 +00:00
# endif
2003-08-16 19:45:25 +00:00
)
2000-11-10 23:43:33 +00:00
{
2004-11-04 00:37:47 +00:00
gchar * display_tmpl = g_filename_display_name ( tmpl ) ;
2003-08-16 19:45:25 +00:00
char c [ 2 ] ;
c [ 0 ] = * slash ;
c [ 1 ] = ' \0 ' ;
2000-11-10 23:43:33 +00:00
g_set_error ( error ,
2011-08-14 14:09:58 -04:00
G_FILE_ERROR ,
G_FILE_ERROR_FAILED ,
_ ( " Template '%s' invalid, should not contain a '%s' " ) ,
display_tmpl , c ) ;
2004-11-04 00:37:47 +00:00
g_free ( display_tmpl ) ;
2000-11-10 23:43:33 +00:00
return - 1 ;
}
2011-08-14 14:09:58 -04:00
2006-06-16 15:12:32 +00:00
if ( strstr ( tmpl , " XXXXXX " ) = = NULL )
2000-11-10 23:43:33 +00:00
{
2004-11-04 00:37:47 +00:00
gchar * display_tmpl = g_filename_display_name ( tmpl ) ;
2000-11-10 23:43:33 +00:00
g_set_error ( error ,
2011-08-14 14:09:58 -04:00
G_FILE_ERROR ,
G_FILE_ERROR_FAILED ,
_ ( " Template '%s' doesn't contain XXXXXX " ) ,
display_tmpl ) ;
2004-11-04 00:37:47 +00:00
g_free ( display_tmpl ) ;
2000-11-10 23:43:33 +00:00
return - 1 ;
}
tmpdir = g_get_tmp_dir ( ) ;
2003-08-16 19:45:25 +00:00
if ( G_IS_DIR_SEPARATOR ( tmpdir [ strlen ( tmpdir ) - 1 ] ) )
2000-11-10 23:43:33 +00:00
sep = " " ;
else
sep = G_DIR_SEPARATOR_S ;
2000-11-12 20:38:19 +00:00
fulltemplate = g_strconcat ( tmpdir , sep , tmpl , NULL ) ;
2000-11-10 23:43:33 +00:00
2011-08-14 14:09:58 -04:00
retval = get_tmp_file ( fulltemplate , f , flags , mode ) ;
2000-11-10 23:43:33 +00:00
if ( retval = = - 1 )
{
2014-04-21 15:55:59 +00:00
int saved_errno = errno ;
2013-12-24 23:24:40 -05:00
set_file_error ( error ,
fulltemplate ,
2014-04-21 15:55:59 +00:00
_ ( " Failed to create file '%s': %s " ) ,
saved_errno ) ;
2000-11-10 23:43:33 +00:00
g_free ( fulltemplate ) ;
return - 1 ;
}
2011-08-14 14:09:58 -04:00
* name_used = fulltemplate ;
2000-11-10 23:43:33 +00:00
return retval ;
}
2001-09-10 13:30:41 +00:00
2011-08-14 14:09:58 -04:00
/**
* g_file_open_tmp :
2011-08-22 11:37:48 -04:00
* @ tmpl : ( type filename ) ( allow - none ) : Template for file name , as in
* g_mkstemp ( ) , basename only , or % NULL for a default template
* @ name_used : ( out ) ( type filename ) : location to store actual name used ,
* or % NULL
2011-08-14 14:09:58 -04:00
* @ error : return location for a # GError
*
* Opens a file for writing in the preferred directory for temporary
* files ( as returned by g_get_tmp_dir ( ) ) .
*
* @ tmpl should be a string in the GLib file name encoding containing
* a sequence of six ' X ' characters , as the parameter to g_mkstemp ( ) .
* However , unlike these functions , the template should only be a
* basename , no directory components are allowed . If template is
* % NULL , a default template is used .
*
* Note that in contrast to g_mkstemp ( ) ( and mkstemp ( ) ) @ tmpl is not
* modified , and might thus be a read - only literal string .
*
* Upon success , and if @ name_used is non - % NULL , the actual name used
* is returned in @ name_used . This string should be freed with g_free ( )
* when not needed any longer . The returned name is in the GLib file
* name encoding .
*
2014-02-19 19:35:23 -05:00
* Returns : A file handle ( as from open ( ) ) to the file opened for
2011-08-14 14:09:58 -04:00
* reading and writing . The file is opened in binary mode on platforms
* where there is a difference . The file handle should be closed with
* close ( ) . In case of errors , - 1 is returned and @ error will be set .
*/
gint
g_file_open_tmp ( const gchar * tmpl ,
gchar * * name_used ,
GError * * error )
{
gchar * fulltemplate ;
gint result ;
result = g_get_tmp_name ( tmpl , & fulltemplate ,
2012-11-05 12:22:49 -05:00
wrap_g_open ,
2011-08-14 14:09:58 -04:00
O_CREAT | O_EXCL | O_RDWR | O_BINARY ,
0600 ,
error ) ;
if ( result ! = - 1 )
{
if ( name_used )
* name_used = fulltemplate ;
else
g_free ( fulltemplate ) ;
}
return result ;
}
/**
* g_dir_make_tmp :
2011-08-22 11:37:48 -04:00
* @ tmpl : ( type filename ) ( allow - none ) : Template for directory name ,
* as in g_mkdtemp ( ) , basename only , or % NULL for a default template
2011-08-14 14:09:58 -04:00
* @ error : return location for a # GError
*
* Creates a subdirectory in the preferred directory for temporary
* files ( as returned by g_get_tmp_dir ( ) ) .
*
* @ tmpl should be a string in the GLib file name encoding containing
* a sequence of six ' X ' characters , as the parameter to g_mkstemp ( ) .
* However , unlike these functions , the template should only be a
* basename , no directory components are allowed . If template is
* % NULL , a default template is used .
*
* Note that in contrast to g_mkdtemp ( ) ( and mkdtemp ( ) ) @ tmpl is not
* modified , and might thus be a read - only literal string .
*
2014-02-19 19:35:23 -05:00
* Returns : ( type filename ) : The actual name used . This string
2011-08-22 11:37:48 -04:00
* should be freed with g_free ( ) when not needed any longer and is
* is in the GLib file name encoding . In case of errors , % NULL is
* returned and @ error will be set .
2011-08-14 14:09:58 -04:00
*
* Since : 2.30
*/
gchar *
g_dir_make_tmp ( const gchar * tmpl ,
GError * * error )
{
gchar * fulltemplate ;
2012-11-05 12:22:49 -05:00
if ( g_get_tmp_name ( tmpl , & fulltemplate , wrap_g_mkdir , 0 , 0700 , error ) = = - 1 )
2011-08-14 14:09:58 -04:00
return NULL ;
else
return fulltemplate ;
}
2001-09-10 13:30:41 +00:00
static gchar *
2005-06-23 05:50:53 +00:00
g_build_path_va ( const gchar * separator ,
const gchar * first_element ,
2005-08-10 04:07:47 +00:00
va_list * args ,
2005-06-23 05:50:53 +00:00
gchar * * str_array )
2001-09-10 13:30:41 +00:00
{
GString * result ;
gint separator_len = strlen ( separator ) ;
gboolean is_first = TRUE ;
2002-07-26 19:59:07 +00:00
gboolean have_leading = FALSE ;
const gchar * single_element = NULL ;
2001-09-10 13:30:41 +00:00
const gchar * next_element ;
2002-07-26 19:59:07 +00:00
const gchar * last_trailing = NULL ;
2005-06-23 05:50:53 +00:00
gint i = 0 ;
2001-09-10 13:30:41 +00:00
result = g_string_new ( NULL ) ;
2005-06-23 05:50:53 +00:00
if ( str_array )
next_element = str_array [ i + + ] ;
else
next_element = first_element ;
2001-09-10 13:30:41 +00:00
while ( TRUE )
{
const gchar * element ;
const gchar * start ;
const gchar * end ;
if ( next_element )
{
element = next_element ;
2005-06-23 05:50:53 +00:00
if ( str_array )
next_element = str_array [ i + + ] ;
else
2005-08-10 04:07:47 +00:00
next_element = va_arg ( * args , gchar * ) ;
2001-09-10 13:30:41 +00:00
}
else
break ;
2002-07-26 19:59:07 +00:00
/* Ignore empty elements */
if ( ! * element )
continue ;
2001-09-10 13:30:41 +00:00
2002-07-26 19:59:07 +00:00
start = element ;
if ( separator_len )
2001-09-10 13:30:41 +00:00
{
2009-09-09 00:18:23 -04:00
while ( strncmp ( start , separator , separator_len ) = = 0 )
2001-09-10 13:30:41 +00:00
start + = separator_len ;
2002-07-26 19:59:07 +00:00
}
2001-09-10 13:30:41 +00:00
end = start + strlen ( start ) ;
2002-07-26 19:59:07 +00:00
if ( separator_len )
2001-09-10 13:30:41 +00:00
{
2002-07-26 19:59:07 +00:00
while ( end > = start + separator_len & &
2001-09-10 13:30:41 +00:00
strncmp ( end - separator_len , separator , separator_len ) = = 0 )
end - = separator_len ;
2002-07-26 19:59:07 +00:00
last_trailing = end ;
while ( last_trailing > = element + separator_len & &
strncmp ( last_trailing - separator_len , separator , separator_len ) = = 0 )
last_trailing - = separator_len ;
if ( ! have_leading )
{
/* If the leading and trailing separator strings are in the
* same element and overlap , the result is exactly that element
*/
if ( last_trailing < = start )
single_element = element ;
g_string_append_len ( result , element , start - element ) ;
have_leading = TRUE ;
}
else
single_element = NULL ;
2001-09-10 13:30:41 +00:00
}
2002-07-26 19:59:07 +00:00
if ( end = = start )
continue ;
2001-09-10 13:30:41 +00:00
2002-07-26 19:59:07 +00:00
if ( ! is_first )
g_string_append ( result , separator ) ;
g_string_append_len ( result , start , end - start ) ;
is_first = FALSE ;
2001-09-10 13:30:41 +00:00
}
2002-07-26 19:59:07 +00:00
if ( single_element )
{
g_string_free ( result , TRUE ) ;
return g_strdup ( single_element ) ;
}
else
{
if ( last_trailing )
g_string_append ( result , last_trailing ) ;
2001-09-10 13:30:41 +00:00
2002-07-26 19:59:07 +00:00
return g_string_free ( result , FALSE ) ;
}
2001-09-10 13:30:41 +00:00
}
2005-06-23 05:50:53 +00:00
/**
* g_build_pathv :
* @ separator : a string used to separator the elements of the path .
2011-06-07 17:07:46 -04:00
* @ args : ( array zero - terminated = 1 ) : % NULL - terminated array of strings containing the path elements .
2005-06-23 05:50:53 +00:00
*
* Behaves exactly like g_build_path ( ) , but takes the path elements
* as a string array , instead of varargs . This function is mainly
* meant for language bindings .
*
2014-02-19 19:35:23 -05:00
* Returns : a newly - allocated string that must be freed with g_free ( ) .
2005-06-23 05:50:53 +00:00
*
* Since : 2.8
*/
gchar *
g_build_pathv ( const gchar * separator ,
gchar * * args )
{
if ( ! args )
return NULL ;
2005-08-10 04:07:47 +00:00
return g_build_path_va ( separator , NULL , NULL , args ) ;
2005-06-23 05:50:53 +00:00
}
2001-09-10 13:30:41 +00:00
/**
* g_build_path :
* @ separator : a string used to separator the elements of the path .
* @ first_element : the first element in the path
2011-07-22 13:25:32 +02:00
* @ . . . : remaining elements in path , terminated by % NULL
2001-09-10 13:30:41 +00:00
*
2001-12-16 19:31:36 +00:00
* Creates a path from a series of elements using @ separator as the
2001-09-10 13:30:41 +00:00
* separator between elements . At the boundary between two elements ,
* any trailing occurrences of separator in the first element , or
* leading occurrences of separator in the second element are removed
* and exactly one copy of the separator is inserted .
2002-07-26 19:59:07 +00:00
*
* Empty elements are ignored .
*
* The number of leading copies of the separator on the result is
* the same as the number of leading copies of the separator on
* the first non - empty element .
*
* The number of trailing copies of the separator on the result is
* the same as the number of trailing copies of the separator on
* the last non - empty element . ( Determination of the number of
* trailing copies is done without stripping leading copies , so
2014-02-06 08:04:52 -05:00
* if the separator is ` ABA ` , then ` ABABA ` has 1 trailing copy . )
2002-07-26 19:59:07 +00:00
*
* However , if there is only a single non - empty element , and there
* are no characters in that element not part of the leading or
* trailing separators , then the result is exactly the original value
* of that element .
*
* Other than for determination of the number of leading and trailing
* copies of the separator , elements consisting only of copies
* of the separator are ignored .
2001-09-10 13:30:41 +00:00
*
2014-02-19 19:35:23 -05:00
* Returns : a newly - allocated string that must be freed with g_free ( ) .
2001-09-10 13:30:41 +00:00
* */
gchar *
g_build_path ( const gchar * separator ,
const gchar * first_element ,
. . . )
{
gchar * str ;
va_list args ;
g_return_val_if_fail ( separator ! = NULL , NULL ) ;
va_start ( args , first_element ) ;
2005-08-10 04:07:47 +00:00
str = g_build_path_va ( separator , first_element , & args , NULL ) ;
2001-09-10 13:30:41 +00:00
va_end ( args ) ;
return str ;
}
2005-06-23 22:52:49 +00:00
# ifdef G_OS_WIN32
2005-06-23 05:50:53 +00:00
static gchar *
2005-06-24 13:26:45 +00:00
g_build_pathname_va ( const gchar * first_element ,
2005-08-10 04:07:47 +00:00
va_list * args ,
2005-06-23 05:50:53 +00:00
gchar * * str_array )
2001-09-10 13:30:41 +00:00
{
2005-06-23 05:50:53 +00:00
/* Code copied from g_build_pathv(), and modified to use two
2003-08-16 19:45:25 +00:00
* alternative single - character separators .
*/
GString * result ;
gboolean is_first = TRUE ;
gboolean have_leading = FALSE ;
const gchar * single_element = NULL ;
const gchar * next_element ;
const gchar * last_trailing = NULL ;
gchar current_separator = ' \\ ' ;
2005-06-23 05:50:53 +00:00
gint i = 0 ;
2003-08-16 19:45:25 +00:00
result = g_string_new ( NULL ) ;
2005-06-23 05:50:53 +00:00
if ( str_array )
next_element = str_array [ i + + ] ;
else
next_element = first_element ;
2003-08-16 19:45:25 +00:00
while ( TRUE )
{
const gchar * element ;
const gchar * start ;
const gchar * end ;
if ( next_element )
{
element = next_element ;
2005-06-23 05:50:53 +00:00
if ( str_array )
next_element = str_array [ i + + ] ;
else
2005-08-10 04:07:47 +00:00
next_element = va_arg ( * args , gchar * ) ;
2003-08-16 19:45:25 +00:00
}
else
break ;
/* Ignore empty elements */
if ( ! * element )
continue ;
start = element ;
if ( TRUE )
{
while ( start & &
( * start = = ' \\ ' | | * start = = ' / ' ) )
{
current_separator = * start ;
start + + ;
}
}
end = start + strlen ( start ) ;
if ( TRUE )
{
while ( end > = start + 1 & &
( end [ - 1 ] = = ' \\ ' | | end [ - 1 ] = = ' / ' ) )
{
current_separator = end [ - 1 ] ;
end - - ;
}
last_trailing = end ;
while ( last_trailing > = element + 1 & &
( last_trailing [ - 1 ] = = ' \\ ' | | last_trailing [ - 1 ] = = ' / ' ) )
last_trailing - - ;
if ( ! have_leading )
{
/* If the leading and trailing separator strings are in the
* same element and overlap , the result is exactly that element
*/
if ( last_trailing < = start )
single_element = element ;
g_string_append_len ( result , element , start - element ) ;
have_leading = TRUE ;
}
else
single_element = NULL ;
}
if ( end = = start )
continue ;
if ( ! is_first )
g_string_append_len ( result , & current_separator , 1 ) ;
g_string_append_len ( result , start , end - start ) ;
is_first = FALSE ;
}
if ( single_element )
{
g_string_free ( result , TRUE ) ;
return g_strdup ( single_element ) ;
}
else
{
if ( last_trailing )
g_string_append ( result , last_trailing ) ;
return g_string_free ( result , FALSE ) ;
}
2005-06-23 05:50:53 +00:00
}
2005-06-23 22:52:49 +00:00
# endif
2005-06-23 05:50:53 +00:00
/**
* g_build_filenamev :
2011-05-31 12:00:41 -04:00
* @ args : ( array zero - terminated = 1 ) : % NULL - terminated array of strings containing the path elements .
2005-06-23 05:50:53 +00:00
*
* Behaves exactly like g_build_filename ( ) , but takes the path elements
* as a string array , instead of varargs . This function is mainly
* meant for language bindings .
*
2014-02-19 19:35:23 -05:00
* Returns : a newly - allocated string that must be freed with g_free ( ) .
2005-06-23 05:50:53 +00:00
*
* Since : 2.8
*/
gchar *
g_build_filenamev ( gchar * * args )
{
gchar * str ;
# ifndef G_OS_WIN32
2005-08-10 04:07:47 +00:00
str = g_build_path_va ( G_DIR_SEPARATOR_S , NULL , NULL , args ) ;
2005-06-23 05:50:53 +00:00
# else
2005-08-10 04:07:47 +00:00
str = g_build_pathname_va ( NULL , NULL , args ) ;
2005-06-23 05:50:53 +00:00
# endif
return str ;
}
/**
* g_build_filename :
* @ first_element : the first element in the path
2011-07-22 13:25:32 +02:00
* @ . . . : remaining elements in path , terminated by % NULL
2005-06-23 05:50:53 +00:00
*
* Creates a filename from a series of elements using the correct
* separator for filenames .
*
2014-02-06 08:04:52 -05:00
* On Unix , this function behaves identically to ` g_build_path
* ( G_DIR_SEPARATOR_S , first_element , . . . . ) ` .
2005-06-23 05:50:53 +00:00
*
* On Windows , it takes into account that either the backslash
2014-02-06 08:04:52 -05:00
* ( ` \ ` or slash ( ` / ` ) can be used as separator in filenames , but
* otherwise behaves as on UNIX . When file pathname separators need
* to be inserted , the one that last previously occurred in the
* parameters ( reading from left to right ) is used .
2005-06-23 05:50:53 +00:00
*
* No attempt is made to force the resulting filename to be an absolute
* path . If the first element is a relative path , the result will
* be a relative path .
*
2014-02-19 19:35:23 -05:00
* Returns : a newly - allocated string that must be freed with g_free ( ) .
2005-06-23 05:50:53 +00:00
* */
gchar *
g_build_filename ( const gchar * first_element ,
. . . )
{
gchar * str ;
va_list args ;
va_start ( args , first_element ) ;
# ifndef G_OS_WIN32
2005-08-10 04:07:47 +00:00
str = g_build_path_va ( G_DIR_SEPARATOR_S , first_element , & args , NULL ) ;
2005-06-23 05:50:53 +00:00
# else
2005-08-10 04:07:47 +00:00
str = g_build_pathname_va ( first_element , & args , NULL ) ;
2003-08-16 19:45:25 +00:00
# endif
2005-06-23 05:50:53 +00:00
va_end ( args ) ;
return str ;
2001-09-10 13:30:41 +00:00
}
2003-07-28 19:49:47 +00:00
/**
2003-07-29 22:31:40 +00:00
* g_file_read_link :
2003-07-28 19:49:47 +00:00
* @ filename : the symbolic link
* @ error : return location for a # GError
*
2004-11-04 00:37:47 +00:00
* Reads the contents of the symbolic link @ filename like the POSIX
* readlink ( ) function . The returned string is in the encoding used
* for filenames . Use g_filename_to_utf8 ( ) to convert it to UTF - 8.
2003-07-28 19:49:47 +00:00
*
2008-10-06 18:50:39 +00:00
* Returns : A newly - allocated string with the contents of the symbolic link ,
2003-07-28 19:49:47 +00:00
* or % NULL if an error occurred .
*
* Since : 2.4
*/
gchar *
2008-12-31 05:51:47 +00:00
g_file_read_link ( const gchar * filename ,
GError * * error )
2003-07-28 19:49:47 +00:00
{
# ifdef HAVE_READLINK
gchar * buffer ;
guint size ;
gint read_size ;
size = 256 ;
buffer = g_malloc ( size ) ;
while ( TRUE )
{
read_size = readlink ( filename , buffer , size ) ;
2013-12-24 23:24:40 -05:00
if ( read_size < 0 )
{
2014-04-21 15:55:59 +00:00
int saved_errno = errno ;
2013-12-24 23:24:40 -05:00
set_file_error ( error ,
filename ,
2014-04-21 15:55:59 +00:00
_ ( " Failed to read the symbolic link '%s': %s " ) ,
saved_errno ) ;
2014-07-22 14:00:23 -04:00
g_free ( buffer ) ;
2013-12-24 23:24:40 -05:00
return NULL ;
}
2003-07-28 19:49:47 +00:00
if ( read_size < size )
2013-12-24 23:24:40 -05:00
{
buffer [ read_size ] = 0 ;
return buffer ;
}
2003-07-28 19:49:47 +00:00
size * = 2 ;
buffer = g_realloc ( buffer , size ) ;
}
# else
2008-06-16 16:53:58 +00:00
g_set_error_literal ( error ,
G_FILE_ERROR ,
G_FILE_ERROR_INVAL ,
_ ( " Symbolic links not supported " ) ) ;
2003-07-28 19:49:47 +00:00
return NULL ;
# endif
}
2005-03-14 04:26:57 +00:00
2011-10-17 01:30:31 -04:00
/**
* g_path_is_absolute :
* @ file_name : a file name
*
* Returns % TRUE if the given @ file_name is an absolute file name .
* Note that this is a somewhat vague concept on Windows .
*
* On POSIX systems , an absolute file name is well - defined . It always
* starts from the single root directory . For example " /usr/local " .
*
* On Windows , the concepts of current drive and drive - specific
* current directory introduce vagueness . This function interprets as
* an absolute file name one that either begins with a directory
* separator such as " \ Users \t ml " or begins with the root on a drive ,
* for example " C: \ Windows " . The first case also includes UNC paths
* such as " \\ myserver \ docs \f oo " . In all cases , either slashes or
* backslashes are accepted .
*
* Note that a file name relative to the current drive root does not
* truly specify a file uniquely over time and across processes , as
* the current drive is a per - process value and can be changed .
*
* File names relative the current directory on some specific drive ,
* such as " D:foo/bar " , are not interpreted as absolute by this
* function , but they obviously are not relative to the normal current
* directory as returned by getcwd ( ) or g_get_current_dir ( )
* either . Such paths should be avoided , or need to be handled using
* Windows - specific code .
*
* Returns : % TRUE if @ file_name is absolute
*/
gboolean
g_path_is_absolute ( const gchar * file_name )
{
g_return_val_if_fail ( file_name ! = NULL , FALSE ) ;
if ( G_IS_DIR_SEPARATOR ( file_name [ 0 ] ) )
return TRUE ;
# ifdef G_OS_WIN32
/* Recognize drive letter on native Windows */
if ( g_ascii_isalpha ( file_name [ 0 ] ) & &
file_name [ 1 ] = = ' : ' & & G_IS_DIR_SEPARATOR ( file_name [ 2 ] ) )
return TRUE ;
# endif
return FALSE ;
}
/**
* g_path_skip_root :
* @ file_name : a file name
*
* Returns a pointer into @ file_name after the root component ,
* i . e . after the " / " in UNIX or " C: \" under Windows. If @file_name
* is not an absolute path it returns % NULL .
*
* Returns : a pointer into @ file_name after the root component
*/
const gchar *
g_path_skip_root ( const gchar * file_name )
{
g_return_val_if_fail ( file_name ! = NULL , NULL ) ;
# ifdef G_PLATFORM_WIN32
/* Skip \\server\share or //server/share */
if ( G_IS_DIR_SEPARATOR ( file_name [ 0 ] ) & &
G_IS_DIR_SEPARATOR ( file_name [ 1 ] ) & &
file_name [ 2 ] & &
! G_IS_DIR_SEPARATOR ( file_name [ 2 ] ) )
{
gchar * p ;
p = strchr ( file_name + 2 , G_DIR_SEPARATOR ) ;
# ifdef G_OS_WIN32
{
gchar * q ;
q = strchr ( file_name + 2 , ' / ' ) ;
if ( p = = NULL | | ( q ! = NULL & & q < p ) )
p = q ;
}
# endif
if ( p & & p > file_name + 2 & & p [ 1 ] )
{
file_name = p + 1 ;
while ( file_name [ 0 ] & & ! G_IS_DIR_SEPARATOR ( file_name [ 0 ] ) )
file_name + + ;
/* Possibly skip a backslash after the share name */
if ( G_IS_DIR_SEPARATOR ( file_name [ 0 ] ) )
file_name + + ;
return ( gchar * ) file_name ;
}
}
# endif
/* Skip initial slashes */
if ( G_IS_DIR_SEPARATOR ( file_name [ 0 ] ) )
{
while ( G_IS_DIR_SEPARATOR ( file_name [ 0 ] ) )
file_name + + ;
return ( gchar * ) file_name ;
}
# ifdef G_OS_WIN32
/* Skip X:\ */
if ( g_ascii_isalpha ( file_name [ 0 ] ) & &
file_name [ 1 ] = = ' : ' & &
G_IS_DIR_SEPARATOR ( file_name [ 2 ] ) )
return ( gchar * ) file_name + 3 ;
# endif
return NULL ;
}
/**
* g_basename :
* @ file_name : the name of the file
*
* Gets the name of the file without any leading directory
* components . It returns a pointer into the given file name
* string .
*
2014-02-19 19:35:23 -05:00
* Returns : the name of the file without any leading
2011-10-17 01:30:31 -04:00
* directory components
*
* Deprecated : 2.2 : Use g_path_get_basename ( ) instead , but notice
* that g_path_get_basename ( ) allocates new memory for the
* returned string , unlike this function which returns a pointer
* into the argument .
*/
const gchar *
g_basename ( const gchar * file_name )
{
gchar * base ;
g_return_val_if_fail ( file_name ! = NULL , NULL ) ;
base = strrchr ( file_name , G_DIR_SEPARATOR ) ;
# ifdef G_OS_WIN32
{
gchar * q ;
q = strrchr ( file_name , ' / ' ) ;
if ( base = = NULL | | ( q ! = NULL & & q > base ) )
base = q ;
}
# endif
if ( base )
return base + 1 ;
# ifdef G_OS_WIN32
if ( g_ascii_isalpha ( file_name [ 0 ] ) & & file_name [ 1 ] = = ' : ' )
return ( gchar * ) file_name + 2 ;
# endif
return ( gchar * ) file_name ;
}
/**
* g_path_get_basename :
* @ file_name : the name of the file
*
* Gets the last component of the filename .
*
* If @ file_name ends with a directory separator it gets the component
* before the last slash . If @ file_name consists only of directory
* separators ( and on Windows , possibly a drive letter ) , a single
* separator is returned . If @ file_name is empty , it gets " . " .
*
2014-02-19 19:35:23 -05:00
* Returns : a newly allocated string containing the last
2011-10-17 01:30:31 -04:00
* component of the filename
*/
gchar *
g_path_get_basename ( const gchar * file_name )
{
gssize base ;
gssize last_nonslash ;
gsize len ;
gchar * retval ;
g_return_val_if_fail ( file_name ! = NULL , NULL ) ;
if ( file_name [ 0 ] = = ' \0 ' )
return g_strdup ( " . " ) ;
last_nonslash = strlen ( file_name ) - 1 ;
while ( last_nonslash > = 0 & & G_IS_DIR_SEPARATOR ( file_name [ last_nonslash ] ) )
last_nonslash - - ;
if ( last_nonslash = = - 1 )
/* string only containing slashes */
return g_strdup ( G_DIR_SEPARATOR_S ) ;
# ifdef G_OS_WIN32
if ( last_nonslash = = 1 & &
g_ascii_isalpha ( file_name [ 0 ] ) & &
file_name [ 1 ] = = ' : ' )
/* string only containing slashes and a drive */
return g_strdup ( G_DIR_SEPARATOR_S ) ;
# endif
base = last_nonslash ;
while ( base > = 0 & & ! G_IS_DIR_SEPARATOR ( file_name [ base ] ) )
base - - ;
# ifdef G_OS_WIN32
if ( base = = - 1 & &
g_ascii_isalpha ( file_name [ 0 ] ) & &
file_name [ 1 ] = = ' : ' )
base = 1 ;
# endif /* G_OS_WIN32 */
len = last_nonslash - base ;
retval = g_malloc ( len + 1 ) ;
memcpy ( retval , file_name + base + 1 , len ) ;
retval [ len ] = ' \0 ' ;
return retval ;
}
/**
* g_dirname :
* @ file_name : the name of the file
*
* Gets the directory components of a file name .
*
* If the file name has no directory components " . " is returned .
* The returned string should be freed when no longer needed .
*
* Returns : the directory components of the file
*
* Deprecated : use g_path_get_dirname ( ) instead
*/
/**
* g_path_get_dirname :
* @ file_name : the name of the file
*
* Gets the directory components of a file name .
*
* If the file name has no directory components " . " is returned .
* The returned string should be freed when no longer needed .
*
* Returns : the directory components of the file
*/
gchar *
g_path_get_dirname ( const gchar * file_name )
{
gchar * base ;
gsize len ;
g_return_val_if_fail ( file_name ! = NULL , NULL ) ;
base = strrchr ( file_name , G_DIR_SEPARATOR ) ;
# ifdef G_OS_WIN32
{
gchar * q ;
q = strrchr ( file_name , ' / ' ) ;
if ( base = = NULL | | ( q ! = NULL & & q > base ) )
base = q ;
}
# endif
if ( ! base )
{
# ifdef G_OS_WIN32
if ( g_ascii_isalpha ( file_name [ 0 ] ) & & file_name [ 1 ] = = ' : ' )
{
gchar drive_colon_dot [ 4 ] ;
drive_colon_dot [ 0 ] = file_name [ 0 ] ;
drive_colon_dot [ 1 ] = ' : ' ;
drive_colon_dot [ 2 ] = ' . ' ;
drive_colon_dot [ 3 ] = ' \0 ' ;
return g_strdup ( drive_colon_dot ) ;
}
# endif
return g_strdup ( " . " ) ;
}
while ( base > file_name & & G_IS_DIR_SEPARATOR ( * base ) )
base - - ;
# ifdef G_OS_WIN32
/* base points to the char before the last slash.
*
* In case file_name is the root of a drive ( X : \ ) or a child of the
* root of a drive ( X : \ foo ) , include the slash .
*
* In case file_name is the root share of an UNC path
* ( \ \ server \ share ) , add a slash , returning \ \ server \ share \ .
*
* In case file_name is a direct child of a share in an UNC path
* ( \ \ server \ share \ foo ) , include the slash after the share name ,
* returning \ \ server \ share \ .
*/
if ( base = = file_name + 1 & &
g_ascii_isalpha ( file_name [ 0 ] ) & &
file_name [ 1 ] = = ' : ' )
base + + ;
else if ( G_IS_DIR_SEPARATOR ( file_name [ 0 ] ) & &
G_IS_DIR_SEPARATOR ( file_name [ 1 ] ) & &
file_name [ 2 ] & &
! G_IS_DIR_SEPARATOR ( file_name [ 2 ] ) & &
base > = file_name + 2 )
{
const gchar * p = file_name + 2 ;
while ( * p & & ! G_IS_DIR_SEPARATOR ( * p ) )
p + + ;
if ( p = = base + 1 )
{
len = ( guint ) strlen ( file_name ) + 1 ;
base = g_new ( gchar , len + 1 ) ;
strcpy ( base , file_name ) ;
base [ len - 1 ] = G_DIR_SEPARATOR ;
base [ len ] = 0 ;
return base ;
}
if ( G_IS_DIR_SEPARATOR ( * p ) )
{
p + + ;
while ( * p & & ! G_IS_DIR_SEPARATOR ( * p ) )
p + + ;
if ( p = = base + 1 )
base + + ;
}
}
# endif
len = ( guint ) 1 + base - file_name ;
base = g_new ( gchar , len + 1 ) ;
Require C90 compliance
Assume all supported platforms implement C90, and therefore they
(correctly) implement atexit(), memmove(), setlocale(), strerror(),
and vprintf(), and have <float.h> and <limits.h>.
(Also remove the configure check testing that "do ... while (0)" works
correctly; the non-do/while-based version of G_STMT_START and
G_STMT_END was removed years ago, but the check remained. Also, remove
some checks that configure.ac claimed were needed for libcharset, but
aren't actually used.)
Note that removing the g_memmove() function is not an ABI break even
on systems where g_memmove() was previously not a macro, because it
was never marked GLIB_AVAILABLE_IN_ALL or listed in glib.symbols, so
it would have been glib-internal since 2004.
https://bugzilla.gnome.org/show_bug.cgi?id=710519
2013-10-19 13:03:58 -04:00
memmove ( base , file_name , len ) ;
2011-10-17 01:30:31 -04:00
base [ len ] = 0 ;
return base ;
}
# if defined(MAXPATHLEN)
# define G_PATH_LENGTH MAXPATHLEN
# elif defined(PATH_MAX)
# define G_PATH_LENGTH PATH_MAX
# elif defined(_PC_PATH_MAX)
# define G_PATH_LENGTH sysconf(_PC_PATH_MAX)
# else
# define G_PATH_LENGTH 2048
# endif
/**
* g_get_current_dir :
*
* Gets the current directory .
*
* The returned string should be freed when no longer needed .
* The encoding of the returned string is system defined .
* On Windows , it is always UTF - 8.
*
2013-12-08 18:18:16 -05:00
* Since GLib 2.40 , this function will return the value of the " PWD "
* environment variable if it is set and it happens to be the same as
* the current directory . This can make a difference in the case that
* the current directory is the target of a symbolic link .
*
2011-10-17 01:30:31 -04:00
* Returns : the current directory
*/
gchar *
g_get_current_dir ( void )
{
# ifdef G_OS_WIN32
gchar * dir = NULL ;
wchar_t dummy [ 2 ] , * wdir ;
int len ;
len = GetCurrentDirectoryW ( 2 , dummy ) ;
wdir = g_new ( wchar_t , len ) ;
if ( GetCurrentDirectoryW ( len , wdir ) = = len - 1 )
dir = g_utf16_to_utf8 ( wdir , - 1 , NULL , NULL , NULL ) ;
g_free ( wdir ) ;
if ( dir = = NULL )
dir = g_strdup ( " \\ " ) ;
return dir ;
# else
2013-12-08 18:18:16 -05:00
const gchar * pwd ;
2011-10-17 01:30:31 -04:00
gchar * buffer = NULL ;
gchar * dir = NULL ;
static gulong max_len = 0 ;
2013-12-08 18:18:16 -05:00
struct stat pwdbuf , dotbuf ;
pwd = g_getenv ( " PWD " ) ;
if ( pwd ! = NULL & &
g_stat ( " . " , & dotbuf ) = = 0 & & g_stat ( pwd , & pwdbuf ) = = 0 & &
dotbuf . st_dev = = pwdbuf . st_dev & & dotbuf . st_ino = = pwdbuf . st_ino )
return g_strdup ( pwd ) ;
2011-10-17 01:30:31 -04:00
if ( max_len = = 0 )
max_len = ( G_PATH_LENGTH = = - 1 ) ? 2048 : G_PATH_LENGTH ;
while ( max_len < G_MAXULONG / 2 )
{
g_free ( buffer ) ;
buffer = g_new ( gchar , max_len + 1 ) ;
* buffer = 0 ;
dir = getcwd ( buffer , max_len ) ;
if ( dir | | errno ! = ERANGE )
break ;
max_len * = 2 ;
}
if ( ! dir | | ! * buffer )
{
/* hm, should we g_error() out here?
* this can happen if e . g . " ./ " has mode \ 0000
*/
buffer [ 0 ] = G_DIR_SEPARATOR ;
buffer [ 1 ] = 0 ;
}
dir = g_strdup ( buffer ) ;
g_free ( buffer ) ;
return dir ;
# endif /* !G_OS_WIN32 */
}
/* NOTE : Keep this part last to ensure nothing in this file uses thn
2009-01-05 10:08:00 +00:00
* below binary compatibility versions .
*/
# if defined (G_OS_WIN32) && !defined (_WIN64)
/* Binary compatibility versions. Will be called by code compiled
* against quite old ( pre - 2.8 , I think ) headers only , not from more
* recently compiled code .
*/
# undef g_file_test
gboolean
g_file_test ( const gchar * filename ,
GFileTest test )
{
gchar * utf8_filename = g_locale_to_utf8 ( filename , - 1 , NULL , NULL , NULL ) ;
gboolean retval ;
if ( utf8_filename = = NULL )
return FALSE ;
retval = g_file_test_utf8 ( utf8_filename , test ) ;
g_free ( utf8_filename ) ;
return retval ;
}
# undef g_file_get_contents
gboolean
g_file_get_contents ( const gchar * filename ,
gchar * * contents ,
gsize * length ,
GError * * error )
{
gchar * utf8_filename = g_locale_to_utf8 ( filename , - 1 , NULL , NULL , error ) ;
gboolean retval ;
if ( utf8_filename = = NULL )
return FALSE ;
retval = g_file_get_contents_utf8 ( utf8_filename , contents , length , error ) ;
g_free ( utf8_filename ) ;
return retval ;
}
# undef g_mkstemp
2012-11-05 12:22:49 -05:00
static gint
wrap_libc_open ( const gchar * filename ,
int flags ,
int mode )
{
return open ( filename , flags , mode ) ;
}
2009-01-05 10:08:00 +00:00
gint
g_mkstemp ( gchar * tmpl )
{
2011-08-14 14:09:58 -04:00
/* This is the backward compatibility system codepage version,
* thus use normal open ( ) .
*/
2012-11-05 12:22:49 -05:00
return get_tmp_file ( tmpl , wrap_libc_open ,
2011-08-14 14:09:58 -04:00
O_RDWR | O_CREAT | O_EXCL , 0600 ) ;
2009-01-05 10:08:00 +00:00
}
# undef g_file_open_tmp
gint
g_file_open_tmp ( const gchar * tmpl ,
gchar * * name_used ,
GError * * error )
{
gchar * utf8_tmpl = g_locale_to_utf8 ( tmpl , - 1 , NULL , NULL , error ) ;
gchar * utf8_name_used ;
gint retval ;
if ( utf8_tmpl = = NULL )
return - 1 ;
retval = g_file_open_tmp_utf8 ( utf8_tmpl , & utf8_name_used , error ) ;
if ( retval = = - 1 )
return - 1 ;
if ( name_used )
* name_used = g_locale_from_utf8 ( utf8_name_used , - 1 , NULL , NULL , NULL ) ;
g_free ( utf8_name_used ) ;
return retval ;
}
2011-10-17 01:30:31 -04:00
# undef g_get_current_dir
gchar *
g_get_current_dir ( void )
{
gchar * utf8_dir = g_get_current_dir_utf8 ( ) ;
gchar * dir = g_locale_from_utf8 ( utf8_dir , - 1 , NULL , NULL , NULL ) ;
g_free ( utf8_dir ) ;
return dir ;
}
2009-01-05 10:08:00 +00:00
# endif
2011-10-17 01:30:31 -04:00