blah. use G_WITH_CYGWIN instead of G_HAVE_CYGWIN
[platform/upstream/glib.git] / gutils.c
1 /* GLIB - Library of useful routines for C programming
2  * Copyright (C) 1995-1998  Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GLib Team and others 1997-1999.  See the AUTHORS
22  * file for a list of people on the GLib Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GLib at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 /* 
28  * MT safe for the unix part, FIXME: make the win32 part MT safe as well.
29  */
30
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
34
35 #include "glibconfig.h"
36
37 #ifdef HAVE_UNISTD_H
38 #include <unistd.h>
39 #endif
40 #include <stdarg.h>
41 #include <stdlib.h>
42 #include <stdio.h>
43 #include <string.h>
44 #include <errno.h>
45 #ifdef HAVE_PWD_H
46 #include <pwd.h>
47 #endif
48 #include <sys/types.h>
49 #ifdef HAVE_SYS_PARAM_H
50 #include <sys/param.h>
51 #endif
52
53 #ifdef G_OS_WIN32
54 #  define STRICT                        /* Strict typing, please */
55 #  include <windows.h>
56 #  include <direct.h>
57 #  include <errno.h>
58 #  include <ctype.h>
59 #  ifdef _MSC_VER
60 #    include <io.h>
61 #  endif /* _MSC_VER */
62 #endif /* G_OS_WIN32 */
63
64 /* implement Glib's inline functions
65  */
66 #define G_INLINE_FUNC extern
67 #define G_CAN_INLINE 1
68 #include "glib.h"
69
70 #ifdef  MAXPATHLEN
71 #define G_PATH_LENGTH   (MAXPATHLEN + 1)
72 #elif   defined (PATH_MAX)
73 #define G_PATH_LENGTH   (PATH_MAX + 1)
74 #else   /* !MAXPATHLEN */
75 #define G_PATH_LENGTH   (2048 + 1)
76 #endif  /* !MAXPATHLEN && !PATH_MAX */
77
78 const guint glib_major_version = GLIB_MAJOR_VERSION;
79 const guint glib_minor_version = GLIB_MINOR_VERSION;
80 const guint glib_micro_version = GLIB_MICRO_VERSION;
81 const guint glib_interface_age = GLIB_INTERFACE_AGE;
82 const guint glib_binary_age = GLIB_BINARY_AGE;
83
84 #if !defined (HAVE_MEMMOVE) && !defined (HAVE_WORKING_BCOPY)
85 void 
86 g_memmove (gpointer dest, gconstpointer src, gulong len)
87 {
88   gchar* destptr = dest;
89   const gchar* srcptr = src;
90   if (src + len < dest || dest + len < src)
91     {
92       bcopy (src, dest, len);
93       return;
94     }
95   else if (dest <= src)
96     {
97       while (len--)
98         *(destptr++) = *(srcptr++);
99     }
100   else
101     {
102       destptr += len;
103       srcptr += len;
104       while (len--)
105         *(--destptr) = *(--srcptr);
106     }
107 }
108 #endif /* !HAVE_MEMMOVE && !HAVE_WORKING_BCOPY */
109
110 void
111 g_atexit (GVoidFunc func)
112 {
113   gint result;
114   gchar *error = NULL;
115
116   /* keep this in sync with glib.h */
117
118 #ifdef  G_NATIVE_ATEXIT
119   result = ATEXIT (func);
120   if (result)
121     error = g_strerror (errno);
122 #elif defined (HAVE_ATEXIT)
123 #  ifdef NeXT /* @#%@! NeXTStep */
124   result = !atexit ((void (*)(void)) func);
125   if (result)
126     error = g_strerror (errno);
127 #  else
128   result = atexit ((void (*)(void)) func);
129   if (result)
130     error = g_strerror (errno);
131 #  endif /* NeXT */
132 #elif defined (HAVE_ON_EXIT)
133   result = on_exit ((void (*)(int, void *)) func, NULL);
134   if (result)
135     error = g_strerror (errno);
136 #else
137   result = 0;
138   error = "no implementation";
139 #endif /* G_NATIVE_ATEXIT */
140
141   if (error)
142     g_error ("Could not register atexit() function: %s", error);
143 }
144
145 gint
146 g_snprintf (gchar       *str,
147             gulong       n,
148             gchar const *fmt,
149             ...)
150 {
151 #ifdef  HAVE_VSNPRINTF
152   va_list args;
153   gint retval;
154   
155   va_start (args, fmt);
156   retval = vsnprintf (str, n, fmt, args);
157   va_end (args);
158
159   if (retval < 0)
160     {
161       str[n-1] = '\0';
162       retval = strlen (str);
163     }
164
165   return retval;
166 #else   /* !HAVE_VSNPRINTF */
167   gchar *printed;
168   va_list args;
169   
170   va_start (args, fmt);
171   printed = g_strdup_vprintf (fmt, args);
172   va_end (args);
173   
174   strncpy (str, printed, n);
175   str[n-1] = '\0';
176
177   g_free (printed);
178   
179   return strlen (str);
180 #endif  /* !HAVE_VSNPRINTF */
181 }
182
183 gint
184 g_vsnprintf (gchar       *str,
185              gulong       n,
186              gchar const *fmt,
187              va_list      args)
188 {
189 #ifdef  HAVE_VSNPRINTF
190   gint retval;
191   
192   retval = vsnprintf (str, n, fmt, args);
193   
194   if (retval < 0)
195     {
196       str[n-1] = '\0';
197       retval = strlen (str);
198     }
199
200   return retval;
201 #else   /* !HAVE_VSNPRINTF */
202   gchar *printed;
203   
204   printed = g_strdup_vprintf (fmt, args);
205   strncpy (str, printed, n);
206   str[n-1] = '\0';
207
208   g_free (printed);
209   
210   return strlen (str);
211 #endif /* !HAVE_VSNPRINTF */
212 }
213
214 guint        
215 g_parse_debug_string  (const gchar *string, 
216                        GDebugKey   *keys, 
217                        guint        nkeys)
218 {
219   guint i;
220   guint result = 0;
221   
222   g_return_val_if_fail (string != NULL, 0);
223   
224   if (!g_strcasecmp (string, "all"))
225     {
226       for (i=0; i<nkeys; i++)
227         result |= keys[i].value;
228     }
229   else
230     {
231       gchar *str = g_strdup (string);
232       gchar *p = str;
233       gchar *q;
234       gboolean done = FALSE;
235       
236       while (*p && !done)
237         {
238           q = strchr (p, ':');
239           if (!q)
240             {
241               q = p + strlen(p);
242               done = TRUE;
243             }
244           
245           *q = 0;
246           
247           for (i=0; i<nkeys; i++)
248             if (!g_strcasecmp(keys[i].key, p))
249               result |= keys[i].value;
250           
251           p = q+1;
252         }
253       
254       g_free (str);
255     }
256   
257   return result;
258 }
259
260 gchar*
261 g_basename (const gchar    *file_name)
262 {
263   register gchar *base;
264   
265   g_return_val_if_fail (file_name != NULL, NULL);
266   
267   base = strrchr (file_name, G_DIR_SEPARATOR);
268   if (base)
269     return base + 1;
270
271 #ifdef G_OS_WIN32
272   if (isalpha (file_name[0]) && file_name[1] == ':')
273     return (gchar*) file_name + 2;
274 #endif /* G_OS_WIN32 */
275   
276   return (gchar*) file_name;
277 }
278
279 gboolean
280 g_path_is_absolute (const gchar *file_name)
281 {
282   g_return_val_if_fail (file_name != NULL, FALSE);
283   
284   if (file_name[0] == G_DIR_SEPARATOR)
285     return TRUE;
286
287 #ifdef G_OS_WIN32
288   if (isalpha (file_name[0]) && file_name[1] == ':' && file_name[2] == G_DIR_SEPARATOR)
289     return TRUE;
290 #endif
291
292   return FALSE;
293 }
294
295 gchar*
296 g_path_skip_root (gchar *file_name)
297 {
298   g_return_val_if_fail (file_name != NULL, NULL);
299   
300   if (file_name[0] == G_DIR_SEPARATOR)
301     return file_name + 1;
302
303 #ifdef G_OS_WIN32
304   if (isalpha (file_name[0]) && file_name[1] == ':' && file_name[2] == G_DIR_SEPARATOR)
305     return file_name + 3;
306 #endif
307
308   return NULL;
309 }
310
311 gchar*
312 g_dirname (const gchar     *file_name)
313 {
314   register gchar *base;
315   register guint len;
316   
317   g_return_val_if_fail (file_name != NULL, NULL);
318   
319   base = strrchr (file_name, G_DIR_SEPARATOR);
320   if (!base)
321     return g_strdup (".");
322   while (base > file_name && *base == G_DIR_SEPARATOR)
323     base--;
324   len = (guint) 1 + base - file_name;
325   
326   base = g_new (gchar, len + 1);
327   g_memmove (base, file_name, len);
328   base[len] = 0;
329   
330   return base;
331 }
332
333 gchar*
334 g_get_current_dir (void)
335 {
336   gchar *buffer;
337   gchar *dir;
338
339   buffer = g_new (gchar, G_PATH_LENGTH);
340   *buffer = 0;
341   
342   /* We don't use getcwd(3) on SUNOS, because, it does a popen("pwd")
343    * and, if that wasn't bad enough, hangs in doing so.
344    */
345 #if     defined (sun) && !defined (__SVR4)
346   dir = getwd (buffer);
347 #else   /* !sun */
348   dir = getcwd (buffer, G_PATH_LENGTH - 1);
349 #endif  /* !sun */
350   
351   if (!dir || !*buffer)
352     {
353       /* hm, should we g_error() out here?
354        * this can happen if e.g. "./" has mode \0000
355        */
356       buffer[0] = G_DIR_SEPARATOR;
357       buffer[1] = 0;
358     }
359
360   dir = g_strdup (buffer);
361   g_free (buffer);
362   
363   return dir;
364 }
365
366 gchar*
367 g_getenv (const gchar *variable)
368 {
369 #ifndef G_OS_WIN32
370   g_return_val_if_fail (variable != NULL, NULL);
371
372   return getenv (variable);
373 #else
374   gchar *v;
375   guint k;
376   static gchar *p = NULL;
377   static gint l;
378   gchar dummy[2];
379
380   g_return_val_if_fail (variable != NULL, NULL);
381   
382   v = getenv (variable);
383   if (!v)
384     return NULL;
385   
386   /* On Windows NT, it is relatively typical that environment variables
387    * contain references to other environment variables. Handle that by
388    * calling ExpandEnvironmentStrings.
389    */
390
391   /* First check how much space we need */
392   k = ExpandEnvironmentStrings (v, dummy, 2);
393   /* Then allocate that much, and actualy do the expansion */
394   if (p == NULL)
395     {
396       p = g_malloc (k);
397       l = k;
398     }
399   else if (k > l)
400     {
401       p = g_realloc (p, k);
402       l = k;
403     }
404   ExpandEnvironmentStrings (v, p, k);
405   return p;
406 #endif
407 }
408
409
410 G_LOCK_DEFINE_STATIC (g_utils_global);
411
412 static  gchar   *g_tmp_dir = NULL;
413 static  gchar   *g_user_name = NULL;
414 static  gchar   *g_real_name = NULL;
415 static  gchar   *g_home_dir = NULL;
416
417 /* HOLDS: g_utils_global_lock */
418 static void
419 g_get_any_init (void)
420 {
421   if (!g_tmp_dir)
422     {
423       g_tmp_dir = g_strdup (g_getenv ("TMPDIR"));
424       if (!g_tmp_dir)
425         g_tmp_dir = g_strdup (g_getenv ("TMP"));
426       if (!g_tmp_dir)
427         g_tmp_dir = g_strdup (g_getenv ("TEMP"));
428       
429 #ifdef P_tmpdir
430       if (!g_tmp_dir)
431         {
432           int k;
433           g_tmp_dir = g_strdup (P_tmpdir);
434           k = strlen (g_tmp_dir);
435           if (g_tmp_dir[k-1] == G_DIR_SEPARATOR)
436             g_tmp_dir[k-1] = '\0';
437         }
438 #endif
439       
440       if (!g_tmp_dir)
441         {
442 #ifndef G_OS_WIN32
443           g_tmp_dir = g_strdup ("/tmp");
444 #else /* G_OS_WIN32 */
445           g_tmp_dir = g_strdup ("C:\\");
446 #endif /* G_OS_WIN32 */
447         }
448       
449       if (!g_home_dir)
450         g_home_dir = g_strdup (g_getenv ("HOME"));
451       
452 #ifdef G_OS_WIN32
453       if (!g_home_dir)
454         {
455           /* The official way to specify a home directory on NT is
456            * the HOMEDRIVE and HOMEPATH environment variables.
457            *
458            * This is inside #ifdef G_OS_WIN32 because with the cygwin dll,
459            * HOME should be a POSIX style pathname.
460            */
461           
462           if (getenv ("HOMEDRIVE") != NULL && getenv ("HOMEPATH") != NULL)
463             {
464               gchar *homedrive, *homepath;
465               
466               homedrive = g_strdup (g_getenv ("HOMEDRIVE"));
467               homepath = g_strdup (g_getenv ("HOMEPATH"));
468               
469               g_home_dir = g_strconcat (homedrive, homepath, NULL);
470               g_free (homedrive);
471               g_free (homepath);
472             }
473         }
474 #endif /* !G_OS_WIN32 */
475       
476 #ifdef HAVE_PWD_H
477       {
478         struct passwd *pw = NULL;
479         gpointer buffer = NULL;
480         
481 #  ifdef HAVE_GETPWUID_R
482         struct passwd pwd;
483 #    ifdef _SC_GETPW_R_SIZE_MAX  
484         /* This reurns the maximum length */
485         guint bufsize = sysconf (_SC_GETPW_R_SIZE_MAX);
486 #    else /* _SC_GETPW_R_SIZE_MAX */
487         guint bufsize = 64;
488 #    endif /* _SC_GETPW_R_SIZE_MAX */
489         gint error;
490         
491         do
492           {
493             g_free (buffer);
494             buffer = g_malloc (bufsize);
495             errno = 0;
496             
497 #    ifdef HAVE_GETPWUID_R_POSIX
498             error = getpwuid_r (getuid (), &pwd, buffer, bufsize, &pw);
499             error = error < 0 ? errno : error;
500 #    else /* !HAVE_GETPWUID_R_POSIX */
501 #      ifdef _AIX
502             error = getpwuid_r (getuid (), &pwd, buffer, bufsize);
503             pw = error == 0 ? &pwd : NULL;
504 #      else /* !_AIX */
505             pw = getpwuid_r (getuid (), &pwd, buffer, bufsize);
506             error = pw ? 0 : errno;
507 #      endif /* !_AIX */            
508 #    endif /* !HAVE_GETPWUID_R_POSIX */
509             
510             if (!pw)
511               {
512                 /* we bail out prematurely if the user id can't be found
513                  * (should be pretty rare case actually), or if the buffer
514                  * should be sufficiently big and lookups are still not
515                  * successfull.
516                  */
517                 if (error == 0 || error == ENOENT)
518                   {
519                     g_warning ("getpwuid_r(): failed due to: " 
520                                "No such user: %lu.", (unsigned long)getuid ());
521                     break;
522                   }
523                 if (bufsize > 32 * 1024)
524                   {
525                     g_warning ("getpwuid_r(): failed due to: %s.",
526                                g_strerror (error));
527                     break;
528                   }
529                 
530                 bufsize *= 2;
531               }
532           }
533         while (!pw);
534 #  endif /* !HAVE_GETPWUID_R */
535         
536         if (!pw)
537           {
538             setpwent ();
539             pw = getpwuid (getuid ());
540             endpwent ();
541           }
542         if (pw)
543           {
544             g_user_name = g_strdup (pw->pw_name);
545 #ifdef HAVE_PW_GECOS
546             g_real_name = g_strdup (pw->pw_gecos);
547 #else
548             g_real_name = g_strdup (g_user_name);
549 #endif
550             if (!g_home_dir)
551               g_home_dir = g_strdup (pw->pw_dir);
552           }
553         g_free (buffer);
554       }
555       
556 #else /* !HAVE_PWD_H */
557       
558 #  ifdef G_OS_WIN32
559       {
560         guint len = 17;
561         gchar buffer[17];
562         
563         if (GetUserName (buffer, &len))
564           {
565             g_user_name = g_strdup (buffer);
566             g_real_name = g_strdup (buffer);
567           }
568       }
569 #  endif /* G_OS_WIN32 */
570       
571 #endif /* !HAVE_PWD_H */
572       
573 #ifdef __EMX__
574       /* change '\\' in %HOME% to '/' */
575       g_strdelimit (g_home_dir, "\\",'/');
576 #endif
577       if (!g_user_name)
578         g_user_name = g_strdup ("somebody");
579       if (!g_real_name)
580         g_real_name = g_strdup ("Unknown");
581       else
582         {
583           gchar *p;
584
585           for (p = g_real_name; *p; p++)
586             if (*p == ',')
587               {
588                 *p = 0;
589                 p = g_strdup (g_real_name);
590                 g_free (g_real_name);
591                 g_real_name = p;
592                 break;
593               }
594         }
595     }
596 }
597
598 gchar*
599 g_get_user_name (void)
600 {
601   G_LOCK (g_utils_global);
602   if (!g_tmp_dir)
603     g_get_any_init ();
604   G_UNLOCK (g_utils_global);
605   
606   return g_user_name;
607 }
608
609 gchar*
610 g_get_real_name (void)
611 {
612   G_LOCK (g_utils_global);
613   if (!g_tmp_dir)
614     g_get_any_init ();
615   G_UNLOCK (g_utils_global);
616  
617   return g_real_name;
618 }
619
620 /* Return the home directory of the user. If there is a HOME
621  * environment variable, its value is returned, otherwise use some
622  * system-dependent way of finding it out. If no home directory can be
623  * deduced, return NULL.
624  */
625
626 gchar*
627 g_get_home_dir (void)
628 {
629   G_LOCK (g_utils_global);
630   if (!g_tmp_dir)
631     g_get_any_init ();
632   G_UNLOCK (g_utils_global);
633   
634   return g_home_dir;
635 }
636
637 /* Return a directory to be used to store temporary files. This is the
638  * value of the TMPDIR, TMP or TEMP environment variables (they are
639  * checked in that order). If none of those exist, use P_tmpdir from
640  * stdio.h.  If that isn't defined, return "/tmp" on POSIXly systems,
641  * and C:\ on Windows.
642  */
643
644 gchar*
645 g_get_tmp_dir (void)
646 {
647   G_LOCK (g_utils_global);
648   if (!g_tmp_dir)
649     g_get_any_init ();
650   G_UNLOCK (g_utils_global);
651   
652   return g_tmp_dir;
653 }
654
655 static gchar *g_prgname = NULL;
656
657 gchar*
658 g_get_prgname (void)
659 {
660   gchar* retval;
661
662   G_LOCK (g_utils_global);
663   retval = g_prgname;
664   G_UNLOCK (g_utils_global);
665
666   return retval;
667 }
668
669 void
670 g_set_prgname (const gchar *prgname)
671 {
672   gchar *c;
673     
674   G_LOCK (g_utils_global);
675   c = g_prgname;
676   g_prgname = g_strdup (prgname);
677   g_free (c);
678   G_UNLOCK (g_utils_global);
679 }
680
681 guint
682 g_direct_hash (gconstpointer v)
683 {
684   return GPOINTER_TO_UINT (v);
685 }
686
687 gint
688 g_direct_equal (gconstpointer v1,
689                 gconstpointer v2)
690 {
691   return v1 == v2;
692 }
693
694 gint
695 g_int_equal (gconstpointer v1,
696              gconstpointer v2)
697 {
698   return *((const gint*) v1) == *((const gint*) v2);
699 }
700
701 guint
702 g_int_hash (gconstpointer v)
703 {
704   return *(const gint*) v;
705 }
706
707 #ifdef G_OS_WIN32
708
709 int
710 gwin_ftruncate (gint  fd,
711                 guint size)
712 {
713   HANDLE hfile;
714   guint curpos;
715
716   g_return_val_if_fail (fd >= 0, -1);
717   
718   hfile = (HANDLE) _get_osfhandle (fd);
719   curpos = SetFilePointer (hfile, 0, NULL, FILE_CURRENT);
720   if (curpos == 0xFFFFFFFF
721       || SetFilePointer (hfile, size, NULL, FILE_BEGIN) == 0xFFFFFFFF
722       || !SetEndOfFile (hfile))
723     {
724       gint error = GetLastError ();
725
726       switch (error)
727         {
728         case ERROR_INVALID_HANDLE:
729           errno = EBADF;
730           break;
731         default:
732           errno = EIO;
733           break;
734         }
735
736       return -1;
737     }
738
739   return 0;
740 }
741
742 DIR*
743 gwin_opendir (const char *dirname)
744 {
745   DIR *result;
746   gchar *mask;
747   guint k;
748
749   g_return_val_if_fail (dirname != NULL, NULL);
750
751   result = g_new0 (DIR, 1);
752   result->find_file_data = g_new0 (WIN32_FIND_DATA, 1);
753   result->dir_name = g_strdup (dirname);
754   
755   k = strlen (result->dir_name);
756   if (k && result->dir_name[k - 1] == '\\')
757     {
758       result->dir_name[k - 1] = '\0';
759       k--;
760     }
761   mask = g_strdup_printf ("%s\\*", result->dir_name);
762
763   result->find_file_handle = (guint) FindFirstFile (mask,
764                                              (LPWIN32_FIND_DATA) result->find_file_data);
765   g_free (mask);
766
767   if (result->find_file_handle == (guint) INVALID_HANDLE_VALUE)
768     {
769       int error = GetLastError ();
770
771       g_free (result->dir_name);
772       g_free (result->find_file_data);
773       g_free (result);
774       switch (error)
775         {
776         default:
777           errno = EIO;
778           return NULL;
779         }
780     }
781   result->just_opened = TRUE;
782
783   return result;
784 }
785
786 struct dirent*
787 gwin_readdir (DIR *dir)
788 {
789   static struct dirent result;
790
791   g_return_val_if_fail (dir != NULL, NULL);
792
793   if (dir->just_opened)
794     dir->just_opened = FALSE;
795   else
796     {
797       if (!FindNextFile ((HANDLE) dir->find_file_handle,
798                          (LPWIN32_FIND_DATA) dir->find_file_data))
799         {
800           int error = GetLastError ();
801
802           switch (error)
803             {
804             case ERROR_NO_MORE_FILES:
805               return NULL;
806             default:
807               errno = EIO;
808               return NULL;
809             }
810         }
811     }
812   strcpy (result.d_name, g_basename (((LPWIN32_FIND_DATA) dir->find_file_data)->cFileName));
813       
814   return &result;
815 }
816
817 void
818 gwin_rewinddir (DIR *dir)
819 {
820   gchar *mask;
821
822   g_return_if_fail (dir != NULL);
823
824   if (!FindClose ((HANDLE) dir->find_file_handle))
825     g_warning ("gwin_rewinddir(): FindClose() failed\n");
826
827   mask = g_strdup_printf ("%s\\*", dir->dir_name);
828   dir->find_file_handle = (guint) FindFirstFile (mask,
829                                           (LPWIN32_FIND_DATA) dir->find_file_data);
830   g_free (mask);
831
832   if (dir->find_file_handle == (guint) INVALID_HANDLE_VALUE)
833     {
834       int error = GetLastError ();
835
836       switch (error)
837         {
838         default:
839           errno = EIO;
840           return;
841         }
842     }
843   dir->just_opened = TRUE;
844 }  
845
846 gint
847 gwin_closedir (DIR *dir)
848 {
849   g_return_val_if_fail (dir != NULL, -1);
850
851   if (!FindClose ((HANDLE) dir->find_file_handle))
852     {
853       int error = GetLastError ();
854
855       switch (error)
856         {
857         default:
858           errno = EIO; return -1;
859         }
860     }
861
862   g_free (dir->dir_name);
863   g_free (dir->find_file_data);
864   g_free (dir);
865
866   return 0;
867 }
868
869 #endif /* G_OS_WIN32 */