diff -r 000000000000 -r e4d67989cc36 glib/libglib/src/gdir.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/glib/libglib/src/gdir.c Tue Feb 02 02:01:42 2010 +0200 @@ -0,0 +1,348 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * gdir.c: Simplified wrapper around the DIRENT functions. + * + * Copyright 2001 Hans Breuer + * Copyright 2004 Tor Lillqvist + * Portions copyright (c) 2006 Nokia Corporation. All rights reserved. + * + * This library 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. + * + * This library 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 this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include +#include /* strcmp */ + +#ifdef HAVE_DIRENT_H +#include +#include +#endif + +#include "glib.h" +#include "gdir.h" + +#include "glibintl.h" + +#include "galias.h" + +struct _GDir +{ + 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. 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(). + * + * Return value: a newly allocated #GDir on success, %NULL on failure. + * If non-%NULL, you must free the result with g_dir_close() + * when you are finished with it. + **/ +EXPORT_C GDir * +g_dir_open (const gchar *path, + guint flags, + 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->u.dirp = opendir (path); + + if (dir->u.dirp) + return dir; + + /* error case */ + utf8_path = g_filename_to_utf8 (path, -1, + NULL, NULL, NULL); + g_set_error (error, + G_FILE_ERROR, + g_file_error_from_errno (errno), + _("Error opening directory '%s': %s"), + utf8_path, g_strerror (errno)); + + g_free (utf8_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. On Windows, the returned name is in + * UTF-8. On Unix, it is in the on-disk encoding. + * + * 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. + **/ +EXPORT_C G_CONST_RETURN gchar* +g_dir_read_name (GDir *dir) +{ + struct dirent *entry; + + g_return_val_if_fail (dir != NULL, NULL); + +#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->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() + * + * Resets the given directory. The next call to g_dir_read_name() + * will return the first entry again. + **/ +EXPORT_C void +g_dir_rewind (GDir *dir) +{ + g_return_if_fail (dir != NULL); + +#ifdef G_OS_WIN32 + if (G_WIN32_HAVE_WIDECHAR_API ()) + { + _wrewinddir (dir->u.wdirp); + return; + } +#endif + + rewinddir (dir->u.dirp); +} + +/** + * g_dir_close: + * @dir: a #GDir* created by g_dir_open() + * + * Closes the directory and deallocates all related resources. + **/ +EXPORT_C void +g_dir_close (GDir *dir) +{ + g_return_if_fail (dir != NULL); + +#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); +} + +#define __G_DIR_C__ +#include "galiasdef.c"