1 /* GLIB - Library of useful routines for C programming 2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald 3 * 4 * gdir.c: Simplified wrapper around the DIRENT functions. 5 * 6 * Copyright 2001 Hans Breuer 7 * Copyright 2004 Tor Lillqvist 8 * 9 * This library is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU Lesser General Public 11 * License as published by the Free Software Foundation; either 12 * version 2 of the License, or (at your option) any later version. 13 * 14 * This library is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * Lesser General Public License for more details. 18 * 19 * You should have received a copy of the GNU Lesser General Public 20 * License along with this library; if not, write to the 21 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 22 * Boston, MA 02111-1307, USA. 23 */ 24 25 #include "config.h" 26 27 #include <errno.h> 28 #include <string.h> 29 #include <stdio.h> 30 #include <sys/stat.h> 31 32 #ifdef HAVE_DIRENT_H 33 #include <sys/types.h> 34 #include <dirent.h> 35 #endif 36 37 #include "glib.h" 38 #include "gdir.h" 39 40 #include "glibintl.h" 41 42 #include "galias.h" 43 44 #if defined (_MSC_VER) && !defined (HAVE_DIRENT_H) 45 #include "../build/win32/dirent/dirent.h" 46 #include "../build/win32/dirent/wdirent.c" 47 #endif 48 49 struct _GDir 50 { 51 #ifdef G_OS_WIN32 52 _WDIR *wdirp; 53 #else 54 DIR *dirp; 55 #endif 56 #ifdef G_OS_WIN32 57 gchar utf8_buf[FILENAME_MAX*4]; 58 #endif 59 }; 60 61 /** 62 * g_dir_open: 63 * @path: the path to the directory you are interested in. On Unix 64 * in the on-disk encoding. On Windows in UTF-8 65 * @flags: Currently must be set to 0. Reserved for future use. 66 * @error: return location for a #GError, or %NULL. 67 * If non-%NULL, an error will be set if and only if 68 * g_dir_open() fails. 69 * 70 * Opens a directory for reading. The names of the files in the 71 * directory can then be retrieved using g_dir_read_name(). 72 * 73 * Return value: a newly allocated #GDir on success, %NULL on failure. 74 * If non-%NULL, you must free the result with g_dir_close() 75 * when you are finished with it. 76 **/ 77 GDir * 78 g_dir_open (const gchar *path, 79 guint flags, 80 GError **error) 81 { 82 GDir *dir; 83 #ifdef G_OS_WIN32 84 wchar_t *wpath; 85 #else 86 gchar *utf8_path; 87 #endif 88 89 g_return_val_if_fail (path != NULL, NULL); 90 91 #ifdef G_OS_WIN32 92 wpath = g_utf8_to_utf16 (path, -1, NULL, NULL, error); 93 94 if (wpath == NULL) 95 return NULL; 96 97 dir = g_new (GDir, 1); 98 99 dir->wdirp = _wopendir (wpath); 100 g_free (wpath); 101 102 if (dir->wdirp) 103 return dir; 104 105 /* error case */ 106 107 g_set_error (error, 108 G_FILE_ERROR, 109 g_file_error_from_errno (errno), 110 _("Error opening directory '%s': %s"), 111 path, g_strerror (errno)); 112 113 g_free (dir); 114 115 return NULL; 116 #else 117 dir = g_new (GDir, 1); 118 119 dir->dirp = opendir (path); 120 121 if (dir->dirp) 122 return dir; 123 124 /* error case */ 125 utf8_path = g_filename_to_utf8 (path, -1, 126 NULL, NULL, NULL); 127 g_set_error (error, 128 G_FILE_ERROR, 129 g_file_error_from_errno (errno), 130 _("Error opening directory '%s': %s"), 131 utf8_path, g_strerror (errno)); 132 133 g_free (utf8_path); 134 g_free (dir); 135 136 return NULL; 137 #endif 138 } 139 140 #if defined (G_OS_WIN32) && !defined (_WIN64) 141 142 /* The above function actually is called g_dir_open_utf8, and it's 143 * that what applications compiled with this GLib version will 144 * use. 145 */ 146 147 #undef g_dir_open 148 149 /* Binary compatibility version. Not for newly compiled code. */ 150 151 GDir * 152 g_dir_open (const gchar *path, 153 guint flags, 154 GError **error) 155 { 156 gchar *utf8_path = g_locale_to_utf8 (path, -1, NULL, NULL, error); 157 GDir *retval; 158 159 if (utf8_path == NULL) 160 return NULL; 161 162 retval = g_dir_open_utf8 (utf8_path, flags, error); 163 164 g_free (utf8_path); 165 166 return retval; 167 } 168 #endif 169 170 /** 171 * g_dir_read_name: 172 * @dir: a #GDir* created by g_dir_open() 173 * 174 * Retrieves the name of the next entry in the directory. The '.' and 175 * '..' entries are omitted. On Windows, the returned name is in 176 * UTF-8. On Unix, it is in the on-disk encoding. 177 * 178 * Return value: The entry's name or %NULL if there are no 179 * more entries. The return value is owned by GLib and 180 * must not be modified or freed. 181 **/ 182 G_CONST_RETURN gchar* 183 g_dir_read_name (GDir *dir) 184 { 185 #ifdef G_OS_WIN32 186 gchar *utf8_name; 187 struct _wdirent *wentry; 188 #else 189 struct dirent *entry; 190 #endif 191 192 g_return_val_if_fail (dir != NULL, NULL); 193 194 #ifdef G_OS_WIN32 195 while (1) 196 { 197 wentry = _wreaddir (dir->wdirp); 198 while (wentry 199 && (0 == wcscmp (wentry->d_name, L".") || 200 0 == wcscmp (wentry->d_name, L".."))) 201 wentry = _wreaddir (dir->wdirp); 202 203 if (wentry == NULL) 204 return NULL; 205 206 utf8_name = g_utf16_to_utf8 (wentry->d_name, -1, NULL, NULL, NULL); 207 208 if (utf8_name == NULL) 209 continue; /* Huh, impossible? Skip it anyway */ 210 211 strcpy (dir->utf8_buf, utf8_name); 212 g_free (utf8_name); 213 214 return dir->utf8_buf; 215 } 216 #else 217 entry = readdir (dir->dirp); 218 while (entry 219 && (0 == strcmp (entry->d_name, ".") || 220 0 == strcmp (entry->d_name, ".."))) 221 entry = readdir (dir->dirp); 222 223 if (entry) 224 return entry->d_name; 225 else 226 return NULL; 227 #endif 228 } 229 230 #if defined (G_OS_WIN32) && !defined (_WIN64) 231 232 /* Ditto for g_dir_read_name */ 233 234 #undef g_dir_read_name 235 236 /* Binary compatibility version. Not for newly compiled code. */ 237 238 G_CONST_RETURN gchar* 239 g_dir_read_name (GDir *dir) 240 { 241 while (1) 242 { 243 const gchar *utf8_name = g_dir_read_name_utf8 (dir); 244 gchar *retval; 245 246 if (utf8_name == NULL) 247 return NULL; 248 249 retval = g_locale_from_utf8 (utf8_name, -1, NULL, NULL, NULL); 250 251 if (retval != NULL) 252 { 253 strcpy (dir->utf8_buf, retval); 254 g_free (retval); 255 256 return dir->utf8_buf; 257 } 258 } 259 } 260 261 #endif 262 263 /** 264 * g_dir_rewind: 265 * @dir: a #GDir* created by g_dir_open() 266 * 267 * Resets the given directory. The next call to g_dir_read_name() 268 * will return the first entry again. 269 **/ 270 void 271 g_dir_rewind (GDir *dir) 272 { 273 g_return_if_fail (dir != NULL); 274 275 #ifdef G_OS_WIN32 276 _wrewinddir (dir->wdirp); 277 #else 278 rewinddir (dir->dirp); 279 #endif 280 } 281 282 /** 283 * g_dir_close: 284 * @dir: a #GDir* created by g_dir_open() 285 * 286 * Closes the directory and deallocates all related resources. 287 **/ 288 void 289 g_dir_close (GDir *dir) 290 { 291 g_return_if_fail (dir != NULL); 292 293 #ifdef G_OS_WIN32 294 _wclosedir (dir->wdirp); 295 #else 296 closedir (dir->dirp); 297 #endif 298 g_free (dir); 299 } 300 301 #define __G_DIR_C__ 302 #include "galiasdef.c" 303