diff --git a/glib/gdir.c b/glib/gdir.c index 0c304f6be..4f1798158 100644 --- a/glib/gdir.c +++ b/glib/gdir.c @@ -47,6 +47,8 @@ #include "../build/win32/dirent/wdirent.c" #endif +#include "glib-private.h" /* g_dir_open_with_errno, g_dir_new_from_dirp */ + /** * GDir: * @@ -65,6 +67,57 @@ struct _GDir #endif }; +/*< private > + * g_dir_open_with_errno: + * @path: the path to the directory you are interested in. + * @flags: Currently must be set to 0. Reserved for future use. + * + * Opens a directory for reading. + * + * This function is equivalent to g_dir_open() except in the error case, + * errno will be set accordingly. + * + * This is useful if you want to construct your own error message. + * + * Returns: a newly allocated #GDir on success, or %NULL on failure, + * with errno set accordingly. + * + * Since: 2.38 + */ +GDir * +g_dir_open_with_errno (const gchar *path, + guint flags) +{ + GDir dir; +#ifdef G_OS_WIN32 + gint saved_errno; + wchar_t *wpath; +#endif + + g_return_val_if_fail (path != NULL, NULL); + +#ifdef G_OS_WIN32 + wpath = g_utf8_to_utf16 (path, -1, NULL, NULL, NULL); + + g_return_val_if_fail (wpath != NULL, NULL); + + dir.wdirp = _wopendir (wpath); + saved_errno = errno; + g_free (wpath); + errno = saved_errno; + + if (dir.wdirp == NULL) + return NULL; +#else + dir.dirp = opendir (path); + + if (dir.dirp == NULL) + return NULL; +#endif + + return g_memdup (&dir, sizeof dir); +} + /** * g_dir_open: * @path: the path to the directory you are interested in. On Unix @@ -87,67 +140,25 @@ g_dir_open (const gchar *path, guint flags, GError **error) { + gint saved_errno; GDir *dir; - int errsv; -#ifdef G_OS_WIN32 - wchar_t *wpath; -#else - gchar *utf8_path; -#endif - g_return_val_if_fail (path != NULL, NULL); + dir = g_dir_open_with_errno (path, flags); -#ifdef G_OS_WIN32 - wpath = g_utf8_to_utf16 (path, -1, NULL, NULL, error); + if (dir == NULL) + { + gchar *utf8_path; - if (wpath == NULL) - return NULL; + saved_errno = errno; - dir = g_new (GDir, 1); + utf8_path = g_filename_to_utf8 (path, -1, NULL, NULL, NULL); - dir->wdirp = _wopendir (wpath); - g_free (wpath); + g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (saved_errno), + _("Error opening directory '%s': %s"), utf8_path, g_strerror (saved_errno)); + g_free (utf8_path); + } - if (dir->wdirp) - return dir; - - /* error case */ - errsv = errno; - - g_set_error (error, - G_FILE_ERROR, - g_file_error_from_errno (errsv), - _("Error opening directory '%s': %s"), - path, g_strerror (errsv)); - - g_free (dir); - - return NULL; -#else - dir = g_new (GDir, 1); - - dir->dirp = opendir (path); - - if (dir->dirp) - return dir; - - /* error case */ - errsv = errno; - - utf8_path = g_filename_to_utf8 (path, -1, - NULL, NULL, NULL); - - g_set_error (error, - G_FILE_ERROR, - g_file_error_from_errno (errsv), - _("Error opening directory '%s': %s"), - utf8_path, g_strerror (errsv)); - - g_free (utf8_path); - g_free (dir); - - return NULL; -#endif + return dir; } #if defined (G_OS_WIN32) && !defined (_WIN64) @@ -180,6 +191,40 @@ g_dir_open (const gchar *path, } #endif +/*< private > + * g_dir_new_from_dirp: + * @dirp: a #DIR* created by opendir() or fdopendir() + * + * Creates a #GDir object from the DIR object that is created using + * opendir() or fdopendir(). The created #GDir assumes ownership of the + * passed-in #DIR pointer. + * + * @dirp must not be %NULL. + * + * This function never fails. + * + * Returns: a newly allocated #GDir, which should be closed using + * g_dir_close(). + * + * Since: 2.38 + **/ +GDir * +g_dir_new_from_dirp (gpointer dirp) +{ +#ifdef G_OS_UNIX + GDir *dir; + + g_return_val_if_fail (dirp != NULL, NULL); + + dir = g_new (GDir, 1); + dir->dirp = dirp; + + return dir; +#else + g_assert_not_reached (); +#endif +} + /** * g_dir_read_name: * @dir: a #GDir* created by g_dir_open() diff --git a/glib/gdir.h b/glib/gdir.h index 0b7c4afce..7b6ec1b51 100644 --- a/glib/gdir.h +++ b/glib/gdir.h @@ -30,6 +30,10 @@ #include +#ifdef G_OS_UNIX +#include +#endif + G_BEGIN_DECLS typedef struct _GDir GDir; diff --git a/glib/glib-private.c b/glib/glib-private.c index d2da2cd47..c357502b2 100644 --- a/glib/glib-private.c +++ b/glib/glib-private.c @@ -43,7 +43,10 @@ glib__private__ (void) g_get_worker_context, g_check_setuid, - g_main_context_new_with_next_id + g_main_context_new_with_next_id, + + g_dir_open_with_errno, + g_dir_new_from_dirp }; return &table; diff --git a/glib/glib-private.h b/glib/glib-private.h index 7e2e61efc..44cbf3d94 100644 --- a/glib/glib-private.h +++ b/glib/glib-private.h @@ -33,6 +33,9 @@ GLIB_AVAILABLE_IN_ALL gchar *_glib_get_locale_dir (void); #endif +GDir * g_dir_open_with_errno (const gchar *path, guint flags); +GDir * g_dir_new_from_dirp (gpointer dirp); + #define GLIB_PRIVATE_CALL(symbol) (glib__private__()->symbol) typedef struct { @@ -49,6 +52,11 @@ typedef struct { gboolean (* g_check_setuid) (void); GMainContext * (* g_main_context_new_with_next_id) (guint next_id); + + GDir * (* g_dir_open_with_errno) (const gchar *path, + guint flags); + GDir * (* g_dir_new_from_dirp) (gpointer dirp); + /* Add other private functions here, initialize them in glib-private.c */ } GLibPrivateVTable;