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