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