Introduce the idea of a filename encoding, which is *literally* the

2004-10-27  Matthias Clasen  <mclasen@redhat.com>

	Introduce the idea of a filename encoding, which is
	*literally* the filename encoding on Unix. On windows,
	use the Unicode name converted to UTF-8. (#156325,
	Tor Lillqvist, Owen Taylor)

	* glib/gdir.[hc]:
	* glib/gconvert.[hc]:
	* glib/gfileutils.[hc]:
	* glib/gutils.[hc]:
	* glib/giowin32.c: On Windows, keep old ABI versions
	of GLib pathname api for DLL ABI stability. Use different
	names for the new-style UTF-8 versions. Hide this through
	a #define.

	* glib/gstdio.[hc]: New files containing wrappers for
	POSIX pathname api.

	* glib/glib.symbols: Add new symbols.

	* glib/makegalias.pl: Drop Win32 specific .def syntax,
	include gstdio.h
This commit is contained in:
Matthias Clasen 2004-10-27 16:46:29 +00:00 committed by Matthias Clasen
parent 8e6b272126
commit 8a7eecd7c6
24 changed files with 1503 additions and 96 deletions

View File

@ -1,3 +1,27 @@
2004-10-27 Matthias Clasen <mclasen@redhat.com>
Introduce the idea of a filename encoding, which is
*literally* the filename encoding on Unix. On windows,
use the Unicode name converted to UTF-8. (#156325,
Tor Lillqvist, Owen Taylor)
* glib/gdir.[hc]:
* glib/gconvert.[hc]:
* glib/gfileutils.[hc]:
* glib/gutils.[hc]:
* glib/giowin32.c: On Windows, keep old ABI versions
of GLib pathname api for DLL ABI stability. Use different
names for the new-style UTF-8 versions. Hide this through
a #define.
* glib/gstdio.[hc]: New files containing wrappers for
POSIX pathname api.
* glib/glib.symbols: Add new symbols.
* glib/makegalias.pl: Drop Win32 specific .def syntax,
include gstdio.h
2004-10-27 Matthias Clasen <mclasen@redhat.com>
* glib/gkeyfile.c: Fix includes. (#156500, #156499,

View File

@ -1,3 +1,27 @@
2004-10-27 Matthias Clasen <mclasen@redhat.com>
Introduce the idea of a filename encoding, which is
*literally* the filename encoding on Unix. On windows,
use the Unicode name converted to UTF-8. (#156325,
Tor Lillqvist, Owen Taylor)
* glib/gdir.[hc]:
* glib/gconvert.[hc]:
* glib/gfileutils.[hc]:
* glib/gutils.[hc]:
* glib/giowin32.c: On Windows, keep old ABI versions
of GLib pathname api for DLL ABI stability. Use different
names for the new-style UTF-8 versions. Hide this through
a #define.
* glib/gstdio.[hc]: New files containing wrappers for
POSIX pathname api.
* glib/glib.symbols: Add new symbols.
* glib/makegalias.pl: Drop Win32 specific .def syntax,
include gstdio.h
2004-10-27 Matthias Clasen <mclasen@redhat.com>
* glib/gkeyfile.c: Fix includes. (#156500, #156499,

View File

@ -1,3 +1,27 @@
2004-10-27 Matthias Clasen <mclasen@redhat.com>
Introduce the idea of a filename encoding, which is
*literally* the filename encoding on Unix. On windows,
use the Unicode name converted to UTF-8. (#156325,
Tor Lillqvist, Owen Taylor)
* glib/gdir.[hc]:
* glib/gconvert.[hc]:
* glib/gfileutils.[hc]:
* glib/gutils.[hc]:
* glib/giowin32.c: On Windows, keep old ABI versions
of GLib pathname api for DLL ABI stability. Use different
names for the new-style UTF-8 versions. Hide this through
a #define.
* glib/gstdio.[hc]: New files containing wrappers for
POSIX pathname api.
* glib/glib.symbols: Add new symbols.
* glib/makegalias.pl: Drop Win32 specific .def syntax,
include gstdio.h
2004-10-27 Matthias Clasen <mclasen@redhat.com>
* glib/gkeyfile.c: Fix includes. (#156500, #156499,

View File

@ -1,3 +1,27 @@
2004-10-27 Matthias Clasen <mclasen@redhat.com>
Introduce the idea of a filename encoding, which is
*literally* the filename encoding on Unix. On windows,
use the Unicode name converted to UTF-8. (#156325,
Tor Lillqvist, Owen Taylor)
* glib/gdir.[hc]:
* glib/gconvert.[hc]:
* glib/gfileutils.[hc]:
* glib/gutils.[hc]:
* glib/giowin32.c: On Windows, keep old ABI versions
of GLib pathname api for DLL ABI stability. Use different
names for the new-style UTF-8 versions. Hide this through
a #define.
* glib/gstdio.[hc]: New files containing wrappers for
POSIX pathname api.
* glib/glib.symbols: Add new symbols.
* glib/makegalias.pl: Drop Win32 specific .def syntax,
include gstdio.h
2004-10-27 Matthias Clasen <mclasen@redhat.com>
* glib/gkeyfile.c: Fix includes. (#156500, #156499,

View File

@ -1,3 +1,27 @@
2004-10-27 Matthias Clasen <mclasen@redhat.com>
Introduce the idea of a filename encoding, which is
*literally* the filename encoding on Unix. On windows,
use the Unicode name converted to UTF-8. (#156325,
Tor Lillqvist, Owen Taylor)
* glib/gdir.[hc]:
* glib/gconvert.[hc]:
* glib/gfileutils.[hc]:
* glib/gutils.[hc]:
* glib/giowin32.c: On Windows, keep old ABI versions
of GLib pathname api for DLL ABI stability. Use different
names for the new-style UTF-8 versions. Hide this through
a #define.
* glib/gstdio.[hc]: New files containing wrappers for
POSIX pathname api.
* glib/glib.symbols: Add new symbols.
* glib/makegalias.pl: Drop Win32 specific .def syntax,
include gstdio.h
2004-10-27 Matthias Clasen <mclasen@redhat.com>
* glib/gkeyfile.c: Fix includes. (#156500, #156499,

View File

@ -1,3 +1,7 @@
2004-10-27 Matthias Clasen <mclasen@redhat.com>
* glib/tmpl/fileutils.sgml: Add some intro.
2004-10-26 Matthias Clasen <mclasen@redhat.com>
* gobject/gobject-docs.sgml: Add an index for 2.6 additions.

View File

@ -967,6 +967,7 @@ g_option_error_quark
<SECTION>
<TITLE>File Utilities</TITLE>
<FILE>fileutils</FILE>
<INCLUDE>glib.h,glib/gstdio.h</INCLUDE>
GFileError
G_FILE_ERROR
GFileTest
@ -984,6 +985,16 @@ g_dir_read_name
g_dir_rewind
g_dir_close
<SUBSECTION>
g_open
g_rename
g_mkdir
g_stat
g_unlink
g_remove
g_fopen
g_freopen
<SUBSECTION Private>
g_file_error_quark
</SECTION>

View File

@ -6,7 +6,31 @@ various file-related functions.
<!-- ##### SECTION Long_Description ##### -->
<para>
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.
</para>
<para>
The pathname argument should be in the GLib file name encoding. On
POSIX this is the actual on-disk encoding which might correspond to
the locale settings of the process (or the
<envar>G_FILENAME_ENCODING</envar> environment variable), or not.
</para>
<para>
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.
</para>
<para>
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().
</para>
<!-- ##### SECTION See_Also ##### -->
@ -223,3 +247,83 @@ An opaque structure representing an opened directory.
@dir:
<!-- ##### FUNCTION g_open ##### -->
<para>
</para>
@filename:
@flags:
@mode:
@Returns:
<!-- ##### FUNCTION g_rename ##### -->
<para>
</para>
@oldfilename:
@newfilename:
@Returns:
<!-- ##### FUNCTION g_mkdir ##### -->
<para>
</para>
@filename:
@mode:
@Returns:
<!-- ##### FUNCTION g_stat ##### -->
<para>
</para>
@filename:
@buf:
@Returns:
<!-- ##### FUNCTION g_unlink ##### -->
<para>
</para>
@filename:
@Returns:
<!-- ##### FUNCTION g_remove ##### -->
<para>
</para>
@filename:
@Returns:
<!-- ##### FUNCTION g_fopen ##### -->
<para>
</para>
@filename:
@mode:
@Returns:
<!-- ##### FUNCTION g_freopen ##### -->
<para>
</para>
@filename:
@mode:
@stream:
@Returns:

View File

@ -260,6 +260,7 @@ attributes (currently only <command>gcc</command>).
Since: 2.6
<!-- ##### MACRO G_GNUC_INTERNAL ##### -->
<para>
Expands to the GNU C <literal>visibility(hidden)</literal> attribute if the

View File

@ -610,7 +610,7 @@ The type of functions to be called when a child exists.
@pid: the process id of the child process
@status: Status information about the child process,
see waitpid(2) for more information about this field
@data: user data passed to g_child_watch_add()
@data: user data passed to g_child_watch_add()
<!-- ##### FUNCTION g_child_watch_source_new ##### -->

View File

@ -90,6 +90,7 @@ libglib_2_0_la_SOURCES = \
gscanner.c \
gshell.c \
gslist.c \
gstdio.c \
gstrfuncs.c \
gstring.c \
gthread.c \
@ -164,6 +165,7 @@ glibsubinclude_HEADERS = \
gshell.h \
gslist.h \
gspawn.h \
gstdio.h \
gstrfuncs.h \
gstring.h \
gthread.h \

View File

@ -1014,8 +1014,9 @@ filename_charset_cache_free (gpointer data)
* get_filename_charset:
* @charset: return location for the name of the filename encoding
*
* Determines the character set used for filenames by consulting the
* environment variables G_FILENAME_ENCODING and G_BROKEN_FILENAMES.
* Determines the preferred character set used for filenames by
* consulting the environment variables G_FILENAME_ENCODING and
* G_BROKEN_FILENAMES.
*
* G_FILENAME_ENCODING may be set to a comma-separated list of character
* set names. The special token "@locale" is taken to mean the character set
@ -1025,8 +1026,13 @@ filename_charset_cache_free (gpointer data)
* character set of the current locale is taken as the filename encoding.
*
* The returned @charset belongs to GLib and must not be freed.
*
* Return value: %TRUE if the charset used for filename is UTF-8.
*
* Note that on Unix, regardless of the locale character set or
* G_FILENAME_ENCODING value, the actual file names present on a
* system might be in any random encoding or just gibberish.
*
* Return value: %TRUE
* if the charset used for filename is UTF-8.
*/
static gboolean
get_filename_charset (const gchar **filename_charset)
@ -1089,12 +1095,33 @@ get_filename_charset (const gchar **filename_charset)
}
#else /* G_PLATFORM_WIN32 */
static gboolean
get_filename_charset (const gchar **filename_charset)
{
#ifdef G_OS_WIN32
/* On Windows GLib pretends that the filename charset is UTF-8 */
if (filename_charset)
*filename_charset = "UTF-8";
return TRUE;
#else
/* Cygwin works like before */
g_get_charset (filename_charset);
return FALSE;
#endif
}
#ifdef G_OS_WIN32
static gboolean
old_get_filename_charset (const gchar **filename_charset)
{
g_get_charset (filename_charset);
return FALSE;
}
#endif
#endif /* G_PLATFORM_WIN32 */
/* This is called from g_thread_init(). It's used to
@ -1146,6 +1173,30 @@ g_filename_to_utf8 (const gchar *opsysstring,
"UTF-8", charset, bytes_read, bytes_written, error);
}
#ifdef G_OS_WIN32
#undef g_filename_to_utf8
/* Binary compatibility version. Not for newly compiled code. */
gchar*
g_filename_to_utf8 (const gchar *opsysstring,
gssize len,
gsize *bytes_read,
gsize *bytes_written,
GError **error)
{
const gchar *charset;
if (old_get_filename_charset (&charset))
return strdup_len (opsysstring, len, bytes_read, bytes_written, error);
else
return g_convert (opsysstring, len,
"UTF-8", charset, bytes_read, bytes_written, error);
}
#endif
/**
* g_filename_from_utf8:
* @utf8string: a UTF-8 encoded string.
@ -1184,6 +1235,30 @@ g_filename_from_utf8 (const gchar *utf8string,
charset, "UTF-8", bytes_read, bytes_written, error);
}
#ifdef G_OS_WIN32
#undef g_filename_from_utf8
/* Binary compatibility version. Not for newly compiled code. */
gchar*
g_filename_from_utf8 (const gchar *utf8string,
gssize len,
gsize *bytes_read,
gsize *bytes_written,
GError **error)
{
const gchar *charset;
if (old_get_filename_charset (&charset))
return strdup_len (utf8string, len, bytes_read, bytes_written, error);
else
return g_convert (utf8string, len,
charset, "UTF-8", bytes_read, bytes_written, error);
}
#endif
/* Test of haystack has the needle prefix, comparing case
* insensitive. haystack may be UTF-8, but needle must
* contain only ascii. */

View File

@ -98,6 +98,11 @@ gchar* g_locale_from_utf8 (const gchar *utf8string,
/* Convert between the operating system (or C runtime)
* representation of file names and UTF-8.
*/
#ifdef G_OS_WIN32
#define g_filename_to_utf8 g_filename_to_utf8_utf8
#define g_filename_from_utf8 g_filename_from_utf8_utf8
#endif
gchar* g_filename_to_utf8 (const gchar *opsysstring,
gssize len,
gsize *bytes_read,

View File

@ -4,6 +4,7 @@
* gdir.c: Simplified wrapper around the DIRENT functions.
*
* Copyright 2001 Hans Breuer
* Copyright 2004 Tor Lillqvist
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -39,20 +40,28 @@
struct _GDir
{
DIR *dir;
union {
DIR *dirp;
#ifdef G_OS_WIN32
_WDIR *wdirp;
#endif
} u;
#ifdef G_OS_WIN32
gchar utf8_buf[FILENAME_MAX*4];
#endif
};
/**
* g_dir_open:
* @path: the path to the directory you are interested in
* @path: the path to the directory you are interested in. On Unix
* in the on-disk encoding. On Windows in UTF-8
* @flags: Currently must be set to 0. Reserved for future use.
* @error: return location for a #GError, or %NULL.
* If non-%NULL, an error will be set if and only if
* g_dir_open_fails.
*
* Opens a directory for reading. The names of the files
* in the directory can then be retrieved using
* g_dir_read_name().
* Opens a directory for reading. The names of the files in the
* directory can then be retrieved using g_dir_read_name().
*
* Return value: a newly allocated #GDir on success, %NULL on failure.
* If non-%NULL, you must free the result with g_dir_close()
@ -64,15 +73,62 @@ g_dir_open (const gchar *path,
GError **error)
{
GDir *dir;
#ifndef G_OS_WIN32
gchar *utf8_path;
#endif
g_return_val_if_fail (path != NULL, NULL);
#ifdef G_OS_WIN32
if (G_WIN32_HAVE_WIDECHAR_API ())
{
wchar_t *wpath = g_utf8_to_utf16 (path, -1, NULL, NULL, error);
if (wpath == NULL)
return NULL;
dir = g_new (GDir, 1);
dir->u.wdirp = _wopendir (wpath);
g_free (wpath);
if (dir->u.wdirp)
return dir;
}
else
{
gchar *cp_path = g_locale_from_utf8 (path, -1, NULL, NULL, error);
if (cp_path == NULL)
return NULL;
dir = g_new (GDir, 1);
dir->u.dirp = opendir (cp_path);
g_free (cp_path);
if (dir->u.dirp)
return dir;
}
/* error case */
g_set_error (error,
G_FILE_ERROR,
g_file_error_from_errno (errno),
_("Error opening directory '%s': %s"),
path, g_strerror (errno));
g_free (dir);
return NULL;
#else
dir = g_new (GDir, 1);
dir->dir = opendir (path);
dir->u.dirp = opendir (path);
if (dir->dir)
if (dir->u.dirp)
return dir;
/* error case */
@ -88,18 +144,48 @@ g_dir_open (const gchar *path,
g_free (dir);
return NULL;
#endif
}
#ifdef G_OS_WIN32
/* The above function actually is called g_dir_open_utf8, and it's
* that what applications compiled with this GLib version will
* use.
*/
#undef g_dir_open
/* Binary compatibility version. Not for newly compiled code. */
GDir *
g_dir_open (const gchar *path,
guint flags,
GError **error)
{
gchar *utf8_path = g_locale_to_utf8 (path, -1, NULL, NULL, error);
GDir *retval;
if (utf8_path == NULL)
return NULL;
retval = g_dir_open_utf8 (utf8_path, flags, error);
g_free (utf8_path);
return retval;
}
#endif
/**
* g_dir_read_name:
* @dir: a #GDir* created by g_dir_open()
*
* Retrieves the name of the next entry in the directory.
* The '.' and '..' entries are omitted. The returned name is in
* the encoding used for filenames. Use g_filename_to_utf8() to
* convert it to UTF-8.
* Retrieves the name of the next entry in the directory. The '.' and
* '..' entries are omitted. On Windows, the returned name is in
* UTF-8. On Unix, it is in the on-disk encoding.
*
* Return value: The entries name or %NULL if there are no
* Return value: The entry's name or %NULL if there are no
* more entries. The return value is owned by GLib and
* must not be modified or freed.
**/
@ -110,18 +196,107 @@ g_dir_read_name (GDir *dir)
g_return_val_if_fail (dir != NULL, NULL);
entry = readdir (dir->dir);
#ifdef G_OS_WIN32
if (G_WIN32_HAVE_WIDECHAR_API ())
{
gchar *utf8_name;
struct _wdirent *wentry;
while (1)
{
wentry = _wreaddir (dir->u.wdirp);
while (wentry
&& (0 == wcscmp (wentry->d_name, L".") ||
0 == wcscmp (wentry->d_name, L"..")))
wentry = _wreaddir (dir->u.wdirp);
if (wentry == NULL)
return NULL;
utf8_name = g_utf16_to_utf8 (wentry->d_name, -1, NULL, NULL, NULL);
if (utf8_name == NULL)
continue; /* Huh, impossible? Skip it anyway */
strcpy (dir->utf8_buf, utf8_name);
g_free (utf8_name);
return dir->utf8_buf;
}
}
else
{
while (1)
{
gchar *utf8_name;
entry = readdir (dir->u.dirp);
while (entry
&& (0 == strcmp (entry->d_name, ".") ||
0 == strcmp (entry->d_name, "..")))
entry = readdir (dir->u.dirp);
if (entry == NULL)
return NULL;
utf8_name = g_locale_to_utf8 (entry->d_name, -1, NULL, NULL, NULL);
if (utf8_name != NULL)
{
strcpy (dir->utf8_buf, utf8_name);
g_free (utf8_name);
return dir->utf8_buf;
}
}
}
#else
entry = readdir (dir->u.dirp);
while (entry
&& (0 == strcmp (entry->d_name, ".") ||
0 == strcmp (entry->d_name, "..")))
entry = readdir (dir->dir);
entry = readdir (dir->u.dirp);
if (entry)
return entry->d_name;
else
return NULL;
#endif
}
#ifdef G_OS_WIN32
/* Ditto for g_dir_read_name */
#undef g_dir_read_name
/* Binary compatibility version. Not for newly compiled code. */
G_CONST_RETURN gchar*
g_dir_read_name (GDir *dir)
{
while (1)
{
const gchar *utf8_name = g_dir_read_name_utf8 (dir);
gchar *retval;
if (utf8_name == NULL)
return NULL;
retval = g_locale_from_utf8 (utf8_name, -1, NULL, NULL, NULL);
if (retval != NULL)
{
strcpy (dir->utf8_buf, retval);
g_free (retval);
return dir->utf8_buf;
}
}
}
#endif
/**
* g_dir_rewind:
* @dir: a #GDir* created by g_dir_open()
@ -134,7 +309,15 @@ g_dir_rewind (GDir *dir)
{
g_return_if_fail (dir != NULL);
rewinddir (dir->dir);
#ifdef G_OS_WIN32
if (G_WIN32_HAVE_WIDECHAR_API ())
{
_wrewinddir (dir->u.wdirp);
return;
}
#endif
rewinddir (dir->u.dirp);
}
/**
@ -148,6 +331,15 @@ g_dir_close (GDir *dir)
{
g_return_if_fail (dir != NULL);
closedir (dir->dir);
#ifdef G_OS_WIN32
if (G_WIN32_HAVE_WIDECHAR_API ())
{
_wclosedir (dir->u.wdirp);
g_free (dir);
return;
}
#endif
closedir (dir->u.dirp);
g_free (dir);
}

View File

@ -29,12 +29,18 @@ G_BEGIN_DECLS
typedef struct _GDir GDir;
GDir * g_dir_open (const gchar *path,
guint flags,
GError **error);
G_CONST_RETURN gchar *g_dir_read_name (GDir *dir);
void g_dir_rewind (GDir *dir);
void g_dir_close (GDir *dir);
#ifdef G_OS_WIN32
/* For DLL ABI stability, keep old names for old (non-UTF-8) functionality. */
#define g_dir_open g_dir_open_utf8
#define g_dir_read_name g_dir_read_name_utf8
#endif
GDir * g_dir_open (const gchar *path,
guint flags,
GError **error);
G_CONST_RETURN gchar *g_dir_read_name (GDir *dir);
void g_dir_rewind (GDir *dir);
void g_dir_close (GDir *dir);
G_END_DECLS

View File

@ -63,6 +63,7 @@
#define O_BINARY 0
#endif
#include "gstdio.h"
#include "glibintl.h"
/**
@ -94,7 +95,7 @@
* <informalexample><programlisting>
* /&ast; DON'T DO THIS &ast;/
* if (!g_file_test (filename, G_FILE_TEST_IS_SYMLINK)) {
* fd = open (filename, O_WRONLY);
* fd = g_open (filename, O_WRONLY);
* /&ast; write to fd &ast;/
* }
* </programlisting></informalexample>
@ -112,10 +113,103 @@ gboolean
g_file_test (const gchar *filename,
GFileTest test)
{
#ifdef G_OS_WIN32
if (G_WIN32_HAVE_WIDECHAR_API ())
{
wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
if (wfilename == NULL)
return FALSE;
if ((test & G_FILE_TEST_EXISTS) && (_waccess (wfilename, F_OK) == 0))
{
g_free (wfilename);
return TRUE;
}
if (test & (G_FILE_TEST_IS_REGULAR |
G_FILE_TEST_IS_DIR |
G_FILE_TEST_IS_EXECUTABLE))
{
struct _stat s;
if (_wstat (wfilename, &s) == 0)
{
if ((test & G_FILE_TEST_IS_REGULAR) && S_ISREG (s.st_mode))
{
g_free (wfilename);
return TRUE;
}
if ((test & G_FILE_TEST_IS_DIR) && S_ISDIR (s.st_mode))
{
g_free (wfilename);
return TRUE;
}
if ((test & G_FILE_TEST_IS_EXECUTABLE) &&
(s.st_mode & _S_IEXEC))
{
g_free (wfilename);
return TRUE;
}
}
}
g_free (wfilename);
return FALSE;
}
else
{
gchar *cp_filename = g_locale_from_utf8 (filename, -1, NULL, NULL, NULL);
if (cp_filename == NULL)
return FALSE;
if ((test & G_FILE_TEST_EXISTS) && (access (cp_filename, F_OK) == 0))
{
g_free (cp_filename);
return TRUE;
}
if (test & (G_FILE_TEST_IS_REGULAR |
G_FILE_TEST_IS_DIR |
G_FILE_TEST_IS_EXECUTABLE))
{
struct stat s;
if (stat (cp_filename, &s) == 0)
{
if ((test & G_FILE_TEST_IS_REGULAR) && S_ISREG (s.st_mode))
{
g_free (cp_filename);
return TRUE;
}
if ((test & G_FILE_TEST_IS_DIR) && S_ISDIR (s.st_mode))
{
g_free (cp_filename);
return TRUE;
}
if ((test & G_FILE_TEST_IS_EXECUTABLE) &&
(s.st_mode & _S_IEXEC))
{
g_free (cp_filename);
return TRUE;
}
}
}
g_free (cp_filename);
return FALSE;
}
#else
if ((test & G_FILE_TEST_EXISTS) && (access (filename, F_OK) == 0))
return TRUE;
#ifndef G_OS_WIN32
if ((test & G_FILE_TEST_IS_EXECUTABLE) && (access (filename, X_OK) == 0))
{
if (getuid () != 0)
@ -128,18 +222,13 @@ g_file_test (const gchar *filename,
}
else
test &= ~G_FILE_TEST_IS_EXECUTABLE;
#endif
if (test & G_FILE_TEST_IS_SYMLINK)
{
#ifdef G_OS_WIN32
/* no sym links on win32, no lstat in msvcrt */
#else
struct stat s;
if ((lstat (filename, &s) == 0) && S_ISLNK (s.st_mode))
return TRUE;
#endif
}
if (test & (G_FILE_TEST_IS_REGULAR |
@ -156,26 +245,45 @@ g_file_test (const gchar *filename,
if ((test & G_FILE_TEST_IS_DIR) && S_ISDIR (s.st_mode))
return TRUE;
#ifndef G_OS_WIN32
/* The extra test for root when access (file, X_OK) succeeds.
* Probably only makes sense on Unix.
*/
if ((test & G_FILE_TEST_IS_EXECUTABLE) &&
((s.st_mode & S_IXOTH) ||
(s.st_mode & S_IXUSR) ||
(s.st_mode & S_IXGRP)))
return TRUE;
#else
if ((test & G_FILE_TEST_IS_EXECUTABLE) &&
(s.st_mode & _S_IEXEC))
return TRUE;
#endif
}
}
return FALSE;
#endif
}
#ifdef G_OS_WIN32
#undef g_file_test
/* Binary compatibility version. Not for newly compiled code. */
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;
}
#endif
GQuark
g_file_error_quark (void)
{
@ -357,7 +465,7 @@ g_file_error_from_errno (gint err_no)
}
static gboolean
get_contents_stdio (const gchar *filename,
get_contents_stdio (const gchar *utf8_filename,
FILE *f,
gchar **contents,
gsize *length,
@ -388,15 +496,12 @@ get_contents_stdio (const gchar *filename,
if (str == NULL)
{
gchar *utf8_filename = g_filename_to_utf8 (filename, -1,
NULL, NULL, NULL);
g_set_error (error,
G_FILE_ERROR,
G_FILE_ERROR_NOMEM,
_("Could not allocate %lu bytes to read file \"%s\""),
(gulong) total_allocated,
utf8_filename ? utf8_filename : "???");
g_free (utf8_filename);
goto error;
}
@ -404,15 +509,12 @@ get_contents_stdio (const gchar *filename,
if (ferror (f))
{
gchar *utf8_filename = g_filename_to_utf8 (filename, -1,
NULL, NULL, NULL);
g_set_error (error,
G_FILE_ERROR,
g_file_error_from_errno (errno),
_("Error reading file '%s': %s"),
utf8_filename ? utf8_filename : "???",
g_strerror (errno));
g_free (utf8_filename);
goto error;
}
@ -443,7 +545,7 @@ get_contents_stdio (const gchar *filename,
#ifndef G_OS_WIN32
static gboolean
get_contents_regfile (const gchar *filename,
get_contents_regfile (const gchar *utf8_filename,
struct stat *stat_buf,
gint fd,
gchar **contents,
@ -462,15 +564,12 @@ get_contents_regfile (const gchar *filename,
if (buf == NULL)
{
gchar *utf8_filename = g_filename_to_utf8 (filename, -1,
NULL, NULL, NULL);
g_set_error (error,
G_FILE_ERROR,
G_FILE_ERROR_NOMEM,
_("Could not allocate %lu bytes to read file \"%s\""),
(gulong) alloc_size,
utf8_filename ? utf8_filename : "???");
g_free (utf8_filename);
goto error;
}
@ -486,8 +585,6 @@ get_contents_regfile (const gchar *filename,
{
if (errno != EINTR)
{
gchar *utf8_filename = g_filename_to_utf8 (filename, -1,
NULL, NULL, NULL);
g_free (buf);
g_set_error (error,
G_FILE_ERROR,
@ -495,7 +592,6 @@ get_contents_regfile (const gchar *filename,
_("Failed to read from file '%s': %s"),
utf8_filename ? utf8_filename : "???",
g_strerror (errno));
g_free (utf8_filename);
goto error;
}
@ -532,14 +628,13 @@ get_contents_posix (const gchar *filename,
{
struct stat stat_buf;
gint fd;
gchar *utf8_filename = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
/* O_BINARY useful on Cygwin */
fd = open (filename, O_RDONLY|O_BINARY);
if (fd < 0)
{
gchar *utf8_filename = g_filename_to_utf8 (filename, -1,
NULL, NULL, NULL);
g_set_error (error,
G_FILE_ERROR,
g_file_error_from_errno (errno),
@ -554,8 +649,6 @@ get_contents_posix (const gchar *filename,
/* I don't think this will ever fail, aside from ENOMEM, but. */
if (fstat (fd, &stat_buf) < 0)
{
gchar *utf8_filename = g_filename_to_utf8 (filename, -1,
NULL, NULL, NULL);
close (fd);
g_set_error (error,
G_FILE_ERROR,
@ -570,24 +663,25 @@ get_contents_posix (const gchar *filename,
if (stat_buf.st_size > 0 && S_ISREG (stat_buf.st_mode))
{
return get_contents_regfile (filename,
&stat_buf,
fd,
contents,
length,
error);
gboolean retval = get_contents_regfile (utf8_filename,
&stat_buf,
fd,
contents,
length,
error);
g_free (utf8_filename);
return retval;
}
else
{
FILE *f;
gboolean retval;
f = fdopen (fd, "r");
if (f == NULL)
{
gchar *utf8_filename = g_filename_to_utf8 (filename, -1,
NULL, NULL, NULL);
g_set_error (error,
G_FILE_ERROR,
g_file_error_from_errno (errno),
@ -599,7 +693,10 @@ get_contents_posix (const gchar *filename,
return FALSE;
}
return get_contents_stdio (filename, f, contents, length, error);
retval = get_contents_stdio (utf8_filename, f, contents, length, error);
g_free (utf8_filename);
return retval;
}
}
@ -607,14 +704,16 @@ get_contents_posix (const gchar *filename,
static gboolean
get_contents_win32 (const gchar *filename,
gchar **contents,
gsize *length,
GError **error)
gchar **contents,
gsize *length,
GError **error)
{
FILE *f;
/* I guess you want binary mode; maybe you want text sometimes? */
f = fopen (filename, "rb");
gboolean retval;
wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
f = _wfopen (wfilename, L"rb");
g_free (wfilename);
if (f == NULL)
{
@ -632,14 +731,16 @@ get_contents_win32 (const gchar *filename,
return FALSE;
}
return get_contents_stdio (filename, f, contents, length, error);
retval = get_contents_stdio (filename, f, contents, length, error);
return retval;
}
#endif
/**
* g_file_get_contents:
* @filename: a file to read contents from
* @filename: name of a file to read contents from, in the encoding used for filenames
* @contents: location to store an allocated string
* @length: location to store length in bytes of the contents
* @error: return location for a #GError
@ -674,6 +775,33 @@ g_file_get_contents (const gchar *filename,
#endif
}
#ifdef G_OS_WIN32
#undef g_file_get_contents
/* Binary compatibility version. Not for newly compiled code. */
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_filename, contents, length, error);
g_free (utf8_filename);
return retval;
}
#endif
/*
* mkstemp() implementation is from the GNU C library.
* Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc.
@ -740,7 +868,8 @@ g_mkstemp (gchar *tmpl)
v /= NLETTERS;
XXXXXX[5] = letters[v % NLETTERS];
fd = open (tmpl, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0600);
/* tmpl is in UTF-8 on Windows, thus use g_open() */
fd = g_open (tmpl, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0600);
if (fd >= 0)
return fd;
@ -756,6 +885,73 @@ g_mkstemp (gchar *tmpl)
#endif
}
#ifdef G_OS_WIN32
#undef g_mkstemp
/* Binary compatibility version. Not for newly compiled code. */
gint
g_mkstemp (gchar *tmpl)
{
int len;
char *XXXXXX;
int count, fd;
static const char letters[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
static const int NLETTERS = sizeof (letters) - 1;
glong value;
GTimeVal tv;
static int counter = 0;
len = strlen (tmpl);
if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX"))
return -1;
/* This is where the Xs start. */
XXXXXX = &tmpl[len - 6];
/* Get some more or less random data. */
g_get_current_time (&tv);
value = (tv.tv_usec ^ tv.tv_sec) + counter++;
for (count = 0; count < 100; value += 7777, ++count)
{
glong v = value;
/* Fill in the random bits. */
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];
/* This is the backward compatibility system codepage version,
* thus use normal open().
*/
fd = open (tmpl, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0600);
if (fd >= 0)
return fd;
else if (errno != EEXIST)
/* 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;
}
/* We got out of the loop because we ran out of combinations to try. */
return -1;
}
#endif
/**
* g_file_open_tmp:
* @tmpl: Template for file name, as in g_mkstemp(), basename only
@ -857,6 +1053,39 @@ g_file_open_tmp (const gchar *tmpl,
return retval;
}
#ifdef G_OS_WIN32
#undef g_file_open_tmp
/* Binary compatibility version. Not for newly compiled code. */
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;
}
#endif
static gchar *
g_build_pathv (const gchar *separator,
const gchar *first_element,

View File

@ -73,6 +73,13 @@ GQuark g_file_error_quark (void);
/* So other code can generate a GFileError */
GFileError g_file_error_from_errno (gint err_no);
#ifdef G_OS_WIN32
#define g_file_test g_file_test_utf8
#define g_file_get_contents g_file_get_contents_utf8
#define g_mkstemp g_mkstemp_utf8
#define g_file_open_tmp g_file_open_tmp_utf8
#endif
gboolean g_file_test (const gchar *filename,
GFileTest test);
gboolean g_file_get_contents (const gchar *filename,
@ -99,5 +106,3 @@ gchar *g_build_filename (const gchar *first_element,
G_END_DECLS
#endif /* __G_FILEUTILS_H__ */

View File

@ -46,6 +46,7 @@
#include <errno.h>
#include <sys/stat.h>
#include "gstdio.h"
#include "glibintl.h"
typedef struct _GIOWin32Channel GIOWin32Channel;
@ -1336,7 +1337,7 @@ g_io_channel_new_file (const gchar *filename,
}
/* always open 'untranslated' */
fid = open (filename, flags | _O_BINARY, pmode);
fid = g_open (filename, flags | _O_BINARY, pmode);
if (g_io_win32_get_debug_flag ())
{
@ -1383,6 +1384,32 @@ g_io_channel_new_file (const gchar *filename,
return channel;
}
#ifdef G_OS_WIN32
#undef g_io_channel_new_file
/* Binary compatibility version. Not for newly compiled code. */
GIOChannel *
g_io_channel_new_file (const gchar *filename,
const gchar *mode,
GError **error)
{
gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, error);
GIOChannel *retval;
if (utf8_filename == NULL)
return NULL;
retval = g_io_channel_new_file_utf8 (utf8_filename, mode, error);
g_free (utf8_filename);
return retval;
}
#endif
static GIOStatus
g_io_win32_set_flags (GIOChannel *channel,
GIOFlags flags,

View File

@ -148,8 +148,14 @@ g_date_valid_year
g_dir_close
g_direct_equal
g_direct_hash
g_dir_open
g_dir_read_name
g_dir_open PRIVATE
#ifdef G_OS_WIN32
g_dir_open_utf8
#endif
g_dir_read_name PRIVATE
#ifdef G_OS_WIN32
g_dir_read_name_utf8
#endif
g_dir_rewind
g_error_copy
g_error_free
@ -158,29 +164,55 @@ g_error_new
g_error_new_literal
g_file_error_from_errno
g_file_error_quark
g_file_get_contents
g_file_get_contents PRIVATE
#ifdef G_OS_WIN32
g_file_get_contents_utf8
#endif
g_filename_from_uri
g_filename_from_utf8
g_filename_from_utf8 PRIVATE
#ifdef G_OS_WIN32
g_filename_from_utf8_utf8
#endif
g_filename_to_uri
g_filename_to_utf8
g_file_open_tmp
g_filename_to_utf8 PRIVATE
#ifdef G_OS_WIN32
g_filename_to_utf8_utf8
#endif
g_file_open_tmp PRIVATE
#ifdef G_OS_WIN32
g_file_open_tmp_utf8
#endif
g_file_read_link
g_file_test
g_file_test PRIVATE
#ifdef G_OS_WIN32
g_file_test_utf8
#endif
g_find_program_in_path
g_fopen
g_fprintf
g_free
g_freopen
g_get_application_name
g_get_charset
g_get_current_dir
g_get_current_dir PRIVATE
#ifdef G_OS_WIN32
g_get_current_dir_utf8
#endif
g_get_current_time
g_getenv
g_get_home_dir
g_get_home_dir PRIVATE
#ifdef G_OS_WIN32
g_get_home_dir_utf8
#endif
g_get_language_names
g_get_prgname
g_get_real_name
g_get_system_config_dirs
g_get_system_data_dirs
g_get_tmp_dir
g_get_tmp_dir PRIVATE
#ifdef G_OS_WIN32
g_get_tmp_dir_utf8
#endif
g_get_user_cache_dir
g_get_user_config_dir
g_get_user_data_dir
@ -245,7 +277,10 @@ g_io_channel_get_encoding
g_io_channel_get_flags
g_io_channel_get_line_term
g_io_channel_init
g_io_channel_new_file
g_io_channel_new_file PRIVATE
#ifdef G_OS_WIN32
g_io_channel_new_file_utf8
#endif
g_io_channel_read
g_io_channel_read_chars
g_io_channel_read_line
@ -410,7 +445,11 @@ g_memdup
g_mem_is_system_malloc
g_mem_profile
g_mem_set_vtable
g_mkstemp
g_mkdir
g_mkstemp PRIVATE
#ifdef G_OS_WIN32
g_mkstemp_utf8
#endif
g_node_child_index
g_node_child_position
g_node_children_foreach
@ -443,6 +482,7 @@ g_nullify_pointer
g_once_impl
g_on_error_query
g_on_error_stack_trace
g_open
g_option_context_add_group
g_option_context_add_main_entries
g_option_error_quark
@ -559,6 +599,8 @@ g_relation_insert
g_relation_new
g_relation_print
g_relation_select
g_remove
g_rename
g_return_if_fail_warning
g_scanner_cur_line
g_scanner_cur_position
@ -648,6 +690,7 @@ g_spawn_command_line_sync
g_spawn_error_quark
g_spawn_sync
g_sprintf
g_stat
g_static_mutex_free
g_static_mutex_get_mutex_impl
g_static_mutex_init
@ -815,6 +858,7 @@ g_unichar_validate
g_unichar_xdigit_value
g_unicode_canonical_decomposition
g_unicode_canonical_ordering
g_unlink
g_unsetenv
g_uri_list_extract_uris
g_usleep

446
glib/gstdio.c Normal file
View File

@ -0,0 +1,446 @@
/* gstdio.c - wrappers for C library functions
*
* Copyright 2004 Tor Lillqvist
*
* 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,
* write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef G_OS_WIN32
#include <wchar.h>
#include <io.h>
#endif
#include "galias.h"
#include "glib.h"
#include "gstdio.h"
#if !defined (G_OS_UNIX) && !defined (G_OS_WIN32)
#error Please port this to your operating system
#endif
/**
* g_open:
* @filename: a pathname in the GLib file name encoding
* @flags: as in open()
* @mode: as in open()
*
* A wrapper for the POSIX open() function. The open() function is used
* to convert a pathname into a file descriptor.
*
* See the C library manual for more details about open().
*
* 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 to
* the locale settings of the process (or the
* <envar>G_FILENAME_ENCODING</envar> environment variable), or not.
*
* 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.
*
* Returns: a new file descriptor, or -1 if an error occurred
*
* Since: 2.6
*/
int
g_open (const gchar *filename,
int flags,
int mode)
{
#ifdef G_OS_WIN32
if (G_WIN32_HAVE_WIDECHAR_API ())
{
wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
int retval = _wopen (wfilename, flags, mode);
int save_errno = errno;
g_free (wfilename);
errno = save_errno;
return retval;
}
else
{
gchar *cp_filename = g_locale_from_utf8 (filename, -1, NULL, NULL, NULL);
int retval = open (cp_filename, flags, mode);
int save_errno = errno;
g_free (cp_filename);
errno = save_errno;
return retval;
}
#else
return open (filename, flags, mode);
#endif
}
/**
* g_rename:
* @oldfilename: a pathname in the GLib file name encoding
* @newfilename: a pathname in the GLib file name encoding
*
* A wrapper for the POSIX rename() function. The rename() function
* renames a file, moving it between directories if required.
*
* See the C library manual for more details about rename().
*
* Returns: 0 if the renaming succeeded, -1 if an error occurred
*
* Since: 2.6
*/
int
g_rename (const gchar *oldfilename,
const gchar *newfilename)
{
#ifdef G_OS_WIN32
if (G_WIN32_HAVE_WIDECHAR_API ())
{
wchar_t *woldfilename = g_utf8_to_utf16 (oldfilename, -1, NULL, NULL, NULL);
wchar_t *wnewfilename = g_utf8_to_utf16 (newfilename, -1, NULL, NULL, NULL);
int retval = _wrename (woldfilename, wnewfilename);
int save_errno = errno;
g_free (woldfilename);
g_free (wnewfilename);
errno = save_errno;
return retval;
}
else
{
gchar *cp_oldfilename = g_locale_from_utf8 (oldfilename, -1, NULL, NULL, NULL);
gchar *cp_newfilename = g_locale_from_utf8 (newfilename, -1, NULL, NULL, NULL);
int retval = rename (cp_oldfilename, cp_newfilename);
int save_errno = errno;
g_free (cp_oldfilename);
g_free (cp_newfilename);
errno = save_errno;
return retval;
}
#else
return rename (oldfilename, newfilename);
#endif
}
/**
* g_mkdir:
* @filename: a pathname in the GLib file name encoding
* @mode: permissions to use for the newly created directory
*
* A wrapper for the POSIX mkdir() function. The mkdir() function
* attempts to create a directory with the given name and permissions.
*
* See the C library manual for more details about mkdir().
*
* Returns: 0 if the directory was successfully created, -1 if an error
* occurred
*
* Since: 2.6
*/
int
g_mkdir (const gchar *filename,
int mode)
{
#ifdef G_OS_WIN32
if (G_WIN32_HAVE_WIDECHAR_API ())
{
wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
int retval = _wmkdir (wfilename);
int save_errno = errno;
g_free (wfilename);
errno = save_errno;
return retval;
}
else
{
gchar *cp_filename = g_locale_from_utf8 (filename, -1, NULL, NULL, NULL);
int retval = mkdir (cp_filename);
int save_errno = errno;
g_free (cp_filename);
errno = save_errno;
return retval;
}
#else
return mkdir (filename, mode);
#endif
}
/**
* g_stat:
* @filename: a pathname in the GLib file name encoding
* @buf: a pointer to a <structname>stat</structname> struct, which
* will be filled with the file information
*
* A wrapper for the POSIX stat() function. The stat() function
* returns information about a file.
*
* See the C library manual for more details about stat().
*
* Returns: 0 if the directory was successfully created, -1 if an error
* occurred
*
* Since: 2.6
*/
int
g_stat (const gchar *filename,
struct stat *buf)
{
#ifdef G_OS_WIN32
if (G_WIN32_HAVE_WIDECHAR_API ())
{
wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
int retval = _wstat (wfilename, (struct _stat *) buf);
int save_errno = errno;
g_free (wfilename);
errno = save_errno;
return retval;
}
else
{
gchar *cp_filename = g_locale_from_utf8 (filename, -1, NULL, NULL, NULL);
int retval = stat (cp_filename, buf);
int save_errno = errno;
g_free (cp_filename);
errno = save_errno;
return retval;
}
#else
return stat (filename, buf);
#endif
}
/**
* g_unlink:
* @filename: a pathname in the GLib file name encoding
*
* A wrapper for the POSIX unlink() function. The unlink() function
* deletes a name from the filesystem. If this was the last link to the
* file and no processes have it opened, the diskspace occupied by the
* file is freed.
*
* See the C library manual for more details about unlink().
*
* Returns: 0 if the directory was successfully created, -1 if an error
* occurred
*
* Since: 2.6
*/
int
g_unlink (const gchar *filename)
{
#ifdef G_OS_WIN32
if (G_WIN32_HAVE_WIDECHAR_API ())
{
wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
int retval = _wunlink (wfilename);
int save_errno = errno;
g_free (wfilename);
errno = save_errno;
return retval;
}
else
{
gchar *cp_filename = g_locale_from_utf8 (filename, -1, NULL, NULL, NULL);
int retval = unlink (cp_filename);
int save_errno = errno;
g_free (cp_filename);
errno = save_errno;
return retval;
}
#else
return unlink (filename);
#endif
}
/**
* g_remove:
* @filename: a pathname in the GLib file name encoding
*
* A wrapper for the POSIX remove() function. The remove() function
* deletes a name from the filesystem. It calls unlink() for files
* and rmdir() for directories.
*
* See the C library manual for more details about remove().
*
* Returns: 0 if the directory was successfully created, -1 if an error
* occurred
*
* Since: 2.6
*/
int
g_remove (const gchar *filename)
{
#ifdef G_OS_WIN32
if (G_WIN32_HAVE_WIDECHAR_API ())
{
wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
int retval = _wremove (wfilename);
int save_errno = errno;
g_free (wfilename);
errno = save_errno;
return retval;
}
else
{
gchar *cp_filename = g_locale_from_utf8 (filename, -1, NULL, NULL, NULL);
int retval = remove (cp_filename);
int save_errno = errno;
g_free (cp_filename);
errno = save_errno;
return retval;
}
#else
return remove (filename);
#endif
}
/**
* g_fopen:
* @filename: a pathname in the GLib file name encoding
* @mode: a string describing the mode in which the file should be
* opened
*
* A wrapper for the POSIX fopen() function. The fopen() function opens
* a file and associates a new stream with it.
*
* See the C library manual for more details about fopen().
*
* Returns: A <typename>FILE</typename> pointer if the file was successfully
* opened, or %NULL if an error occurred
*
* Since: 2.6
*/
FILE *
g_fopen (const gchar *filename,
const gchar *mode)
{
#ifdef G_OS_WIN32
if (G_WIN32_HAVE_WIDECHAR_API ())
{
wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
wchar_t *wmode = g_utf8_to_utf16 (mode, -1, NULL, NULL, NULL);
FILE *retval = _wfopen (wfilename, wmode);
int save_errno = errno;
g_free (wfilename);
g_free (wmode);
errno = save_errno;
return retval;
}
else
{
gchar *cp_filename = g_locale_from_utf8 (filename, -1, NULL, NULL, NULL);
FILE *retval = fopen (cp_filename, mode);
int save_errno = errno;
g_free (cp_filename);
errno = save_errno;
return retval;
}
#else
return fopen (filename, mode);
#endif
}
/**
* g_freopen:
* @filename: a pathname in the GLib file name encoding
* @mode: a string describing the mode in which the file should be
* opened
* @stream: an existing stream which will be reused, or %NULL
*
* A wrapper for the POSIX freopen() function. The freopen() function
* opens a file and associates it with an existing stream.
*
* See the C library manual for more details about freopen().
*
* Returns: A <typename>FILE</typename> pointer if the file was successfully
* opened, or %NULL if an error occurred.
*
* Since: 2.6
*/
FILE *
g_freopen (const gchar *filename,
const gchar *mode,
FILE *stream)
{
#ifdef G_OS_WIN32
if (G_WIN32_HAVE_WIDECHAR_API ())
{
wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
wchar_t *wmode = g_utf8_to_utf16 (mode, -1, NULL, NULL, NULL);
FILE *retval = _wfreopen (wfilename, wmode, stream);
int save_errno = errno;
g_free (wfilename);
g_free (wmode);
errno = save_errno;
return retval;
}
else
{
gchar *cp_filename = g_locale_from_utf8 (filename, -1, NULL, NULL, NULL);
FILE *retval = freopen (cp_filename, mode, stream);
int save_errno = errno;
g_free (cp_filename);
errno = save_errno;
return retval;
}
#else
return freopen (filename, mode, stream);
#endif
}

61
glib/gstdio.h Normal file
View File

@ -0,0 +1,61 @@
/* gstdio.h - GFilename wrappers for C library functions
*
* Copyright 2004 Tor Lillqvist
*
* 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,
* write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __G_STDIO_H__
#define __G_STDIO_H__
#include <glib/gprintf.h>
#include <sys/stat.h>
/* Wrappers for C library functions that take pathname arguments. On
* Unix, the pathname is a file name as it literally is in the file
* system. On well-maintained systems with consistent users who know
* what they are doing and no exchange of files with others this would
* be a well-defined encoding, preferrably UTF-8. On Windows, the
* pathname is always in UTF-8, even if that is not the on-disk
* encoding or the encoding used by the Win32 API.
*/
int g_open (const gchar *filename,
int flags,
int mode);
int g_rename (const gchar *oldfilename,
const gchar *newfilename);
int g_mkdir (const gchar *filename,
int mode);
int g_stat (const gchar *filename,
struct stat *buf);
int g_unlink (const gchar *filename);
int g_remove (const gchar *filename);
FILE *g_fopen (const gchar *filename,
const gchar *mode);
FILE *g_freopen (const gchar *filename,
const gchar *mode,
FILE *stream);
#endif /* __G_STDIO_H__ */

View File

@ -702,12 +702,33 @@ g_get_current_dir (void)
buffer[1] = 0;
}
#ifdef G_OS_WIN32
dir = g_locale_to_utf8 (buffer, -1, NULL, NULL, NULL);
#else
dir = g_strdup (buffer);
#endif
g_free (buffer);
return dir;
}
#ifdef G_OS_WIN32
#undef g_get_current_dir
/* Binary compatibility version. Not for newly compiled code. */
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;
}
#endif
/**
* g_getenv:
* @variable: the environment variable to get.
@ -1167,6 +1188,27 @@ g_get_home_dir (void)
return g_home_dir;
}
#ifdef G_OS_WIN32
#undef g_get_home_dir
G_CONST_RETURN gchar*
g_get_home_dir (void)
{
static gchar *home_dir = NULL;
G_LOCK (g_utils_global);
if (!g_tmp_dir)
g_get_any_init ();
if (!home_dir && g_home_dir)
home_dir = g_locale_from_utf8 (g_home_dir, -1, NULL, NULL, NULL);
G_UNLOCK (g_utils_global);
return home_dir;
}
#endif
/* Return a directory to be used to store temporary files. This is the
* value of the TMPDIR, TMP or TEMP environment variables (they are
* checked in that order). If none of those exist, use P_tmpdir from
@ -1185,6 +1227,30 @@ g_get_tmp_dir (void)
return g_tmp_dir;
}
#ifdef G_OS_WIN32
#undef g_get_tmp_dir
G_CONST_RETURN gchar*
g_get_tmp_dir (void)
{
static gchar *tmp_dir = NULL;
G_LOCK (g_utils_global);
if (!g_tmp_dir)
g_get_any_init ();
if (!tmp_dir)
tmp_dir = g_locale_from_utf8 (g_tmp_dir, -1, NULL, NULL, NULL);
if (tmp_dir == NULL)
tmp_dir = "C:\\";
G_UNLOCK (g_utils_global);
return tmp_dir;
}
#endif
G_LOCK_DEFINE_STATIC (g_prgname);
static gchar *g_prgname = NULL;

View File

@ -115,6 +115,10 @@ G_BEGIN_DECLS
/* Retrive static string info
*/
#ifdef G_OS_WIN32
#define g_get_home_dir g_get_home_dir_utf8
#define g_get_tmp_dir g_get_tmp_dir_utf8
#endif
G_CONST_RETURN gchar* g_get_user_name (void);
G_CONST_RETURN gchar* g_get_real_name (void);
G_CONST_RETURN gchar* g_get_home_dir (void);
@ -171,6 +175,10 @@ G_CONST_RETURN gchar* g_basename (const gchar *file_name);
#endif /* G_DISABLE_DEPRECATED */
#ifdef G_OS_WIN32
#define g_get_current_dir g_get_current_dir_utf8
#endif
/* The returned strings are newly allocated with g_malloc() */
gchar* g_get_current_dir (void);
gchar* g_path_get_basename (const gchar *file_name);

View File

@ -16,7 +16,7 @@ print <<EOF;
#include "glib.h"
#include "gprintf.h"
#include "gstdio.h"
#ifdef G_OS_WIN32
#include "gwin32.h"
#endif
@ -77,8 +77,9 @@ while (<>) {
next;
}
my $str = $_;
# Drop any Win32 specific .def file syntax
$str = (split (/ /, $str))[0];
chomp($str);
my $alias = "IA__".$str;