b3c1565a2fdd964bbdbc04a370f8af9c270b2343
[platform/upstream/glib.git] / glib / gfileutils.c
1 /* gfileutils.c - File utility functions
2  *
3  *  Copyright 2000 Red Hat, Inc.
4  *
5  * GLib is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU Lesser General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * GLib is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with GLib; see the file COPYING.LIB.  If not,
17  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  *   Boston, MA 02111-1307, USA.
19  */
20
21 #include "config.h"
22
23 #include "glib.h"
24
25 #include <sys/stat.h>
26 #ifdef HAVE_UNISTD_H
27 #include <unistd.h>
28 #endif
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <stdarg.h>
32 #include <string.h>
33 #include <errno.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <sys/wait.h>
37 #include <fcntl.h>
38 #include <stdlib.h>
39
40 #ifdef G_OS_WIN32
41 #include <windows.h>
42 #include <io.h>
43 #endif /* G_OS_WIN32 */
44
45 #ifndef S_ISLNK
46 #define S_ISLNK(x) 0
47 #endif
48
49 #ifndef O_BINARY
50 #define O_BINARY 0
51 #endif
52
53 #include "gstdio.h"
54 #include "glibintl.h"
55
56 #include "galias.h"
57
58 /**
59  * g_file_test:
60  * @filename: a filename to test in the GLib file name encoding
61  * @test: bitfield of #GFileTest flags
62  * 
63  * Returns %TRUE if any of the tests in the bitfield @test are
64  * %TRUE. For example, <literal>(G_FILE_TEST_EXISTS | 
65  * G_FILE_TEST_IS_DIR)</literal> will return %TRUE if the file exists; 
66  * the check whether it's a directory doesn't matter since the existence 
67  * test is %TRUE. With the current set of available tests, there's no point
68  * passing in more than one test at a time.
69  * 
70  * Apart from %G_FILE_TEST_IS_SYMLINK all tests follow symbolic links,
71  * so for a symbolic link to a regular file g_file_test() will return
72  * %TRUE for both %G_FILE_TEST_IS_SYMLINK and %G_FILE_TEST_IS_REGULAR.
73  *
74  * Note, that for a dangling symbolic link g_file_test() will return
75  * %TRUE for %G_FILE_TEST_IS_SYMLINK and %FALSE for all other flags.
76  *
77  * You should never use g_file_test() to test whether it is safe
78  * to perform an operation, because there is always the possibility
79  * of the condition changing before you actually perform the operation.
80  * For example, you might think you could use %G_FILE_TEST_IS_SYMLINK
81  * to know whether it is is safe to write to a file without being
82  * tricked into writing into a different location. It doesn't work!
83  *
84  * <informalexample><programlisting>
85  * /&ast; DON'T DO THIS &ast;/
86  *  if (!g_file_test (filename, G_FILE_TEST_IS_SYMLINK)) {
87  *    fd = g_open (filename, O_WRONLY);
88  *    /&ast; write to fd &ast;/
89  *  }
90  * </programlisting></informalexample>
91  *
92  * Another thing to note is that %G_FILE_TEST_EXISTS and
93  * %G_FILE_TEST_IS_EXECUTABLE are implemented using the access()
94  * system call. This usually doesn't matter, but if your program
95  * is setuid or setgid it means that these tests will give you
96  * the answer for the real user ID and group ID, rather than the
97  * effective user ID and group ID.
98  *
99  * On Windows, there are no symlinks, so testing for
100  * %G_FILE_TEST_IS_SYMLINK will always return %FALSE. Testing for
101  * %G_FILE_TEST_IS_EXECUTABLE will just check that the file exists and
102  * its name indicates that it is executable, checking for well-known
103  * extensions and those listed in the %PATHEXT environment variable.
104  *
105  * Return value: whether a test was %TRUE
106  **/
107 gboolean
108 g_file_test (const gchar *filename,
109              GFileTest    test)
110 {
111 #ifdef G_OS_WIN32
112 /* stuff missing in std vc6 api */
113 #  ifndef INVALID_FILE_ATTRIBUTES
114 #    define INVALID_FILE_ATTRIBUTES -1
115 #  endif
116 #  ifndef FILE_ATTRIBUTE_DEVICE
117 #    define FILE_ATTRIBUTE_DEVICE 64
118 #  endif
119   int attributes;
120
121   if (G_WIN32_HAVE_WIDECHAR_API ())
122     {
123       wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
124
125       if (wfilename == NULL)
126         return FALSE;
127
128       attributes = GetFileAttributesW (wfilename);
129
130       g_free (wfilename);
131     }
132   else
133     {
134       gchar *cpfilename = g_locale_from_utf8 (filename, -1, NULL, NULL, NULL);
135
136       if (cpfilename == NULL)
137         return FALSE;
138       
139       attributes = GetFileAttributesA (cpfilename);
140       
141       g_free (cpfilename);
142     }
143
144   if (attributes == INVALID_FILE_ATTRIBUTES)
145     return FALSE;
146
147   if (test & G_FILE_TEST_EXISTS)
148     return TRUE;
149       
150   if (test & G_FILE_TEST_IS_REGULAR)
151     return (attributes & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE)) == 0;
152
153   if (test & G_FILE_TEST_IS_DIR)
154     return (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
155
156   if (test & G_FILE_TEST_IS_EXECUTABLE)
157     {
158       const gchar *lastdot = strrchr (filename, '.');
159       const gchar *pathext = NULL, *p;
160       int extlen;
161
162       if (lastdot == NULL)
163         return FALSE;
164
165       if (stricmp (lastdot, ".exe") == 0 ||
166           stricmp (lastdot, ".cmd") == 0 ||
167           stricmp (lastdot, ".bat") == 0 ||
168           stricmp (lastdot, ".com") == 0)
169         return TRUE;
170
171       /* Check if it is one of the types listed in %PATHEXT% */
172
173       pathext = g_getenv ("PATHEXT");
174       if (pathext == NULL)
175         return FALSE;
176
177       pathext = g_utf8_casefold (pathext, -1);
178
179       lastdot = g_utf8_casefold (lastdot, -1);
180       extlen = strlen (lastdot);
181
182       p = pathext;
183       while (TRUE)
184         {
185           const gchar *q = strchr (p, ';');
186           if (q == NULL)
187             q = p + strlen (p);
188           if (extlen == q - p &&
189               memcmp (lastdot, p, extlen) == 0)
190             {
191               g_free ((gchar *) pathext);
192               g_free ((gchar *) lastdot);
193               return TRUE;
194             }
195           if (*q)
196             p = q + 1;
197           else
198             break;
199         }
200
201       g_free ((gchar *) pathext);
202       g_free ((gchar *) lastdot);
203       return FALSE;
204     }
205
206   return FALSE;
207 #else
208   if ((test & G_FILE_TEST_EXISTS) && (access (filename, F_OK) == 0))
209     return TRUE;
210   
211   if ((test & G_FILE_TEST_IS_EXECUTABLE) && (access (filename, X_OK) == 0))
212     {
213       if (getuid () != 0)
214         return TRUE;
215
216       /* For root, on some POSIX systems, access (filename, X_OK)
217        * will succeed even if no executable bits are set on the
218        * file. We fall through to a stat test to avoid that.
219        */
220     }
221   else
222     test &= ~G_FILE_TEST_IS_EXECUTABLE;
223
224   if (test & G_FILE_TEST_IS_SYMLINK)
225     {
226       struct stat s;
227
228       if ((lstat (filename, &s) == 0) && S_ISLNK (s.st_mode))
229         return TRUE;
230     }
231   
232   if (test & (G_FILE_TEST_IS_REGULAR |
233               G_FILE_TEST_IS_DIR |
234               G_FILE_TEST_IS_EXECUTABLE))
235     {
236       struct stat s;
237       
238       if (stat (filename, &s) == 0)
239         {
240           if ((test & G_FILE_TEST_IS_REGULAR) && S_ISREG (s.st_mode))
241             return TRUE;
242           
243           if ((test & G_FILE_TEST_IS_DIR) && S_ISDIR (s.st_mode))
244             return TRUE;
245
246           /* The extra test for root when access (file, X_OK) succeeds.
247            */
248           if ((test & G_FILE_TEST_IS_EXECUTABLE) &&
249               ((s.st_mode & S_IXOTH) ||
250                (s.st_mode & S_IXUSR) ||
251                (s.st_mode & S_IXGRP)))
252             return TRUE;
253         }
254     }
255
256   return FALSE;
257 #endif
258 }
259
260 #ifdef G_OS_WIN32
261
262 #undef g_file_test
263
264 /* Binary compatibility version. Not for newly compiled code. */
265
266 gboolean
267 g_file_test (const gchar *filename,
268              GFileTest    test)
269 {
270   gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, NULL);
271   gboolean retval;
272
273   if (utf8_filename == NULL)
274     return FALSE;
275
276   retval = g_file_test_utf8 (utf8_filename, test);
277
278   g_free (utf8_filename);
279
280   return retval;
281 }
282
283 #endif
284
285 GQuark
286 g_file_error_quark (void)
287 {
288   static GQuark q = 0;
289   if (q == 0)
290     q = g_quark_from_static_string ("g-file-error-quark");
291
292   return q;
293 }
294
295 /**
296  * g_file_error_from_errno:
297  * @err_no: an "errno" value
298  * 
299  * Gets a #GFileError constant based on the passed-in @errno.
300  * For example, if you pass in %EEXIST this function returns
301  * #G_FILE_ERROR_EXIST. Unlike @errno values, you can portably
302  * assume that all #GFileError values will exist.
303  *
304  * Normally a #GFileError value goes into a #GError returned
305  * from a function that manipulates files. So you would use
306  * g_file_error_from_errno() when constructing a #GError.
307  * 
308  * Return value: #GFileError corresponding to the given @errno
309  **/
310 GFileError
311 g_file_error_from_errno (gint err_no)
312 {
313   switch (err_no)
314     {
315 #ifdef EEXIST
316     case EEXIST:
317       return G_FILE_ERROR_EXIST;
318       break;
319 #endif
320
321 #ifdef EISDIR
322     case EISDIR:
323       return G_FILE_ERROR_ISDIR;
324       break;
325 #endif
326
327 #ifdef EACCES
328     case EACCES:
329       return G_FILE_ERROR_ACCES;
330       break;
331 #endif
332
333 #ifdef ENAMETOOLONG
334     case ENAMETOOLONG:
335       return G_FILE_ERROR_NAMETOOLONG;
336       break;
337 #endif
338
339 #ifdef ENOENT
340     case ENOENT:
341       return G_FILE_ERROR_NOENT;
342       break;
343 #endif
344
345 #ifdef ENOTDIR
346     case ENOTDIR:
347       return G_FILE_ERROR_NOTDIR;
348       break;
349 #endif
350
351 #ifdef ENXIO
352     case ENXIO:
353       return G_FILE_ERROR_NXIO;
354       break;
355 #endif
356
357 #ifdef ENODEV
358     case ENODEV:
359       return G_FILE_ERROR_NODEV;
360       break;
361 #endif
362
363 #ifdef EROFS
364     case EROFS:
365       return G_FILE_ERROR_ROFS;
366       break;
367 #endif
368
369 #ifdef ETXTBSY
370     case ETXTBSY:
371       return G_FILE_ERROR_TXTBSY;
372       break;
373 #endif
374
375 #ifdef EFAULT
376     case EFAULT:
377       return G_FILE_ERROR_FAULT;
378       break;
379 #endif
380
381 #ifdef ELOOP
382     case ELOOP:
383       return G_FILE_ERROR_LOOP;
384       break;
385 #endif
386
387 #ifdef ENOSPC
388     case ENOSPC:
389       return G_FILE_ERROR_NOSPC;
390       break;
391 #endif
392
393 #ifdef ENOMEM
394     case ENOMEM:
395       return G_FILE_ERROR_NOMEM;
396       break;
397 #endif
398
399 #ifdef EMFILE
400     case EMFILE:
401       return G_FILE_ERROR_MFILE;
402       break;
403 #endif
404
405 #ifdef ENFILE
406     case ENFILE:
407       return G_FILE_ERROR_NFILE;
408       break;
409 #endif
410
411 #ifdef EBADF
412     case EBADF:
413       return G_FILE_ERROR_BADF;
414       break;
415 #endif
416
417 #ifdef EINVAL
418     case EINVAL:
419       return G_FILE_ERROR_INVAL;
420       break;
421 #endif
422
423 #ifdef EPIPE
424     case EPIPE:
425       return G_FILE_ERROR_PIPE;
426       break;
427 #endif
428
429 #ifdef EAGAIN
430     case EAGAIN:
431       return G_FILE_ERROR_AGAIN;
432       break;
433 #endif
434
435 #ifdef EINTR
436     case EINTR:
437       return G_FILE_ERROR_INTR;
438       break;
439 #endif
440
441 #ifdef EIO
442     case EIO:
443       return G_FILE_ERROR_IO;
444       break;
445 #endif
446
447 #ifdef EPERM
448     case EPERM:
449       return G_FILE_ERROR_PERM;
450       break;
451 #endif
452
453 #ifdef ENOSYS
454     case ENOSYS:
455       return G_FILE_ERROR_NOSYS;
456       break;
457 #endif
458
459     default:
460       return G_FILE_ERROR_FAILED;
461       break;
462     }
463 }
464
465 static gboolean
466 get_contents_stdio (const gchar *display_filename,
467                     FILE        *f,
468                     gchar      **contents,
469                     gsize       *length,
470                     GError     **error)
471 {
472   gchar buf[4096];
473   size_t bytes;
474   gchar *str = NULL;
475   size_t total_bytes = 0;
476   size_t total_allocated = 0;
477   gchar *tmp;
478
479   g_assert (f != NULL);
480
481   while (!feof (f))
482     {
483       gint save_errno;
484
485       bytes = fread (buf, 1, sizeof (buf), f);
486       save_errno = errno;
487
488       while ((total_bytes + bytes + 1) > total_allocated)
489         {
490           if (str)
491             total_allocated *= 2;
492           else
493             total_allocated = MIN (bytes + 1, sizeof (buf));
494
495           tmp = g_try_realloc (str, total_allocated);
496
497           if (tmp == NULL)
498             {
499               g_set_error (error,
500                            G_FILE_ERROR,
501                            G_FILE_ERROR_NOMEM,
502                            _("Could not allocate %lu bytes to read file \"%s\""),
503                            (gulong) total_allocated,
504                            display_filename);
505
506               goto error;
507             }
508
509           str = tmp;
510         }
511
512       if (ferror (f))
513         {
514           g_set_error (error,
515                        G_FILE_ERROR,
516                        g_file_error_from_errno (save_errno),
517                        _("Error reading file '%s': %s"),
518                        display_filename,
519                        g_strerror (save_errno));
520
521           goto error;
522         }
523
524       memcpy (str + total_bytes, buf, bytes);
525       total_bytes += bytes;
526     }
527
528   fclose (f);
529
530   if (total_allocated == 0)
531     str = g_new (gchar, 1);
532
533   str[total_bytes] = '\0';
534
535   if (length)
536     *length = total_bytes;
537
538   *contents = str;
539
540   return TRUE;
541
542  error:
543
544   g_free (str);
545   fclose (f);
546
547   return FALSE;
548 }
549
550 #ifndef G_OS_WIN32
551
552 static gboolean
553 get_contents_regfile (const gchar *display_filename,
554                       struct stat *stat_buf,
555                       gint         fd,
556                       gchar      **contents,
557                       gsize       *length,
558                       GError     **error)
559 {
560   gchar *buf;
561   size_t bytes_read;
562   size_t size;
563   size_t alloc_size;
564   
565   size = stat_buf->st_size;
566
567   alloc_size = size + 1;
568   buf = g_try_malloc (alloc_size);
569
570   if (buf == NULL)
571     {
572       g_set_error (error,
573                    G_FILE_ERROR,
574                    G_FILE_ERROR_NOMEM,
575                    _("Could not allocate %lu bytes to read file \"%s\""),
576                    (gulong) alloc_size, 
577                    display_filename);
578
579       goto error;
580     }
581   
582   bytes_read = 0;
583   while (bytes_read < size)
584     {
585       gssize rc;
586           
587       rc = read (fd, buf + bytes_read, size - bytes_read);
588
589       if (rc < 0)
590         {
591           if (errno != EINTR) 
592             {
593               int save_errno = errno;
594
595               g_free (buf);
596               g_set_error (error,
597                            G_FILE_ERROR,
598                            g_file_error_from_errno (save_errno),
599                            _("Failed to read from file '%s': %s"),
600                            display_filename, 
601                            g_strerror (save_errno));
602
603               goto error;
604             }
605         }
606       else if (rc == 0)
607         break;
608       else
609         bytes_read += rc;
610     }
611       
612   buf[bytes_read] = '\0';
613
614   if (length)
615     *length = bytes_read;
616   
617   *contents = buf;
618
619   close (fd);
620
621   return TRUE;
622
623  error:
624
625   close (fd);
626   
627   return FALSE;
628 }
629
630 static gboolean
631 get_contents_posix (const gchar *filename,
632                     gchar      **contents,
633                     gsize       *length,
634                     GError     **error)
635 {
636   struct stat stat_buf;
637   gint fd;
638   gchar *display_filename = g_filename_display_name (filename);
639
640   /* O_BINARY useful on Cygwin */
641   fd = open (filename, O_RDONLY|O_BINARY);
642
643   if (fd < 0)
644     {
645       int save_errno = errno;
646
647       g_set_error (error,
648                    G_FILE_ERROR,
649                    g_file_error_from_errno (save_errno),
650                    _("Failed to open file '%s': %s"),
651                    display_filename, 
652                    g_strerror (save_errno));
653       g_free (display_filename);
654
655       return FALSE;
656     }
657
658   /* I don't think this will ever fail, aside from ENOMEM, but. */
659   if (fstat (fd, &stat_buf) < 0)
660     {
661       int save_errno = errno;
662
663       close (fd);
664       g_set_error (error,
665                    G_FILE_ERROR,
666                    g_file_error_from_errno (save_errno),
667                    _("Failed to get attributes of file '%s': fstat() failed: %s"),
668                    display_filename, 
669                    g_strerror (save_errno));
670       g_free (display_filename);
671
672       return FALSE;
673     }
674
675   if (stat_buf.st_size > 0 && S_ISREG (stat_buf.st_mode))
676     {
677       gboolean retval = get_contents_regfile (display_filename,
678                                               &stat_buf,
679                                               fd,
680                                               contents,
681                                               length,
682                                               error);
683       g_free (display_filename);
684
685       return retval;
686     }
687   else
688     {
689       FILE *f;
690       gboolean retval;
691
692       f = fdopen (fd, "r");
693       
694       if (f == NULL)
695         {
696           int save_errno = errno;
697
698           g_set_error (error,
699                        G_FILE_ERROR,
700                        g_file_error_from_errno (save_errno),
701                        _("Failed to open file '%s': fdopen() failed: %s"),
702                        display_filename, 
703                        g_strerror (save_errno));
704           g_free (display_filename);
705
706           return FALSE;
707         }
708   
709       retval = get_contents_stdio (display_filename, f, contents, length, error);
710       g_free (display_filename);
711
712       return retval;
713     }
714 }
715
716 #else  /* G_OS_WIN32 */
717
718 static gboolean
719 get_contents_win32 (const gchar *filename,
720                     gchar      **contents,
721                     gsize       *length,
722                     GError     **error)
723 {
724   FILE *f;
725   gboolean retval;
726   gchar *display_filename = g_filename_display_name (filename);
727   int save_errno;
728   
729   f = g_fopen (filename, "rb");
730   save_errno = errno;
731
732   if (f == NULL)
733     {
734       g_set_error (error,
735                    G_FILE_ERROR,
736                    g_file_error_from_errno (save_errno),
737                    _("Failed to open file '%s': %s"),
738                    display_filename,
739                    g_strerror (save_errno));
740       g_free (display_filename);
741
742       return FALSE;
743     }
744   
745   retval = get_contents_stdio (display_filename, f, contents, length, error);
746   g_free (display_filename);
747
748   return retval;
749 }
750
751 #endif
752
753 /**
754  * g_file_get_contents:
755  * @filename: name of a file to read contents from, in the GLib file name encoding
756  * @contents: location to store an allocated string
757  * @length: location to store length in bytes of the contents, or %NULL
758  * @error: return location for a #GError, or %NULL
759  * 
760  * Reads an entire file into allocated memory, with good error
761  * checking. 
762  *
763  * If the call was successful, it returns %TRUE and sets @contents to the file 
764  * contents and @length to the length of the file contents in bytes. The string 
765  * stored in @contents will be nul-terminated, so for text files you can pass 
766  * %NULL for the @length argument. If the call was not successful, it returns 
767  * %FALSE and sets @error. The error domain is #G_FILE_ERROR. Possible error  
768  * codes are those in the #GFileError enumeration. In the error case, 
769  * @contents is set to %NULL and @length is set to zero.
770  *
771  * Return value: %TRUE on success, %FALSE if an error occurred
772  **/
773 gboolean
774 g_file_get_contents (const gchar *filename,
775                      gchar      **contents,
776                      gsize       *length,
777                      GError     **error)
778 {  
779   g_return_val_if_fail (filename != NULL, FALSE);
780   g_return_val_if_fail (contents != NULL, FALSE);
781
782   *contents = NULL;
783   if (length)
784     *length = 0;
785
786 #ifdef G_OS_WIN32
787   return get_contents_win32 (filename, contents, length, error);
788 #else
789   return get_contents_posix (filename, contents, length, error);
790 #endif
791 }
792
793 #ifdef G_OS_WIN32
794
795 #undef g_file_get_contents
796
797 /* Binary compatibility version. Not for newly compiled code. */
798
799 gboolean
800 g_file_get_contents (const gchar *filename,
801                      gchar      **contents,
802                      gsize       *length,
803                      GError     **error)
804 {
805   gchar *utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, error);
806   gboolean retval;
807
808   if (utf8_filename == NULL)
809     return FALSE;
810
811   retval = g_file_get_contents_utf8 (utf8_filename, contents, length, error);
812
813   g_free (utf8_filename);
814
815   return retval;
816 }
817
818 #endif
819
820 static gboolean
821 rename_file (const char *old_name,
822              const char *new_name,
823              GError **err)
824 {
825   errno = 0;
826   if (g_rename (old_name, new_name) == -1)
827     {
828       int save_errno = errno;
829       gchar *display_old_name = g_filename_display_name (old_name);
830       gchar *display_new_name = g_filename_display_name (new_name);
831
832       g_set_error (err,
833                    G_FILE_ERROR,
834                    g_file_error_from_errno (save_errno),
835                    _("Failed to rename file '%s' to '%s': g_rename() failed: %s"),
836                    display_old_name,
837                    display_new_name,
838                    g_strerror (save_errno));
839
840       g_free (display_old_name);
841       g_free (display_new_name);
842       
843       return FALSE;
844     }
845   
846   return TRUE;
847 }
848
849 static gboolean
850 set_umask_permissions (int           fd,
851                        GError      **err)
852 {
853 #ifdef G_OS_WIN32
854
855   return TRUE;
856
857 #else
858   /* All of this function is just to work around the fact that
859    * there is no way to get the umask without changing it.
860    *
861    * We can't just change-and-reset the umask because that would
862    * lead to a race condition if another thread tried to change
863    * the umask in between the getting and the setting of the umask.
864    * So we have to do the whole thing in a child process.
865    */
866
867   int save_errno;
868   pid_t pid;
869
870   pid = fork ();
871   
872   if (pid == -1)
873     {
874       save_errno = errno;
875       g_set_error (err,
876                    G_FILE_ERROR,
877                    g_file_error_from_errno (save_errno),
878                    _("Could not change file mode: fork() failed: %s"),
879                    g_strerror (save_errno));
880       
881       return FALSE;
882     }
883   else if (pid == 0)
884     {
885       /* child */
886       mode_t mask = umask (0666);
887
888       errno = 0;
889       if (fchmod (fd, 0666 & ~mask) == -1)
890         _exit (errno);
891       else
892         _exit (0);
893
894       return TRUE; /* To quiet gcc */
895     }
896   else
897     { 
898       /* parent */
899       int status;
900
901       errno = 0;
902       if (waitpid (pid, &status, 0) == -1)
903         {
904           save_errno = errno;
905
906           g_set_error (err,
907                        G_FILE_ERROR,
908                        g_file_error_from_errno (save_errno),
909                        _("Could not change file mode: waitpid() failed: %s"),
910                        g_strerror (save_errno));
911
912           return FALSE;
913         }
914
915       if (WIFEXITED (status))
916         {
917           save_errno = WEXITSTATUS (status);
918
919           if (save_errno == 0)
920             {
921               return TRUE;
922             }
923           else
924             {
925               g_set_error (err,
926                            G_FILE_ERROR,
927                            g_file_error_from_errno (save_errno),
928                            _("Could not change file mode: chmod() failed: %s"),
929                            g_strerror (save_errno));
930       
931               return FALSE;
932             }
933         }
934       else if (WIFSIGNALED (status))
935         {
936           g_set_error (err,
937                        G_FILE_ERROR,
938                        G_FILE_ERROR_FAILED,
939                        _("Could not change file mode: Child terminated by signal: %s"),
940                        g_strsignal (WTERMSIG (status)));
941                        
942           return FALSE;
943         }
944       else
945         {
946           /* This shouldn't happen */
947           g_set_error (err,
948                        G_FILE_ERROR,
949                        G_FILE_ERROR_FAILED,
950                        _("Could not change file mode: Child terminated abnormally"));
951           return FALSE;
952         }
953     }
954 #endif
955 }
956
957 static gchar *
958 write_to_temp_file (const gchar *contents,
959                     gssize length,
960                     const gchar *template,
961                     GError **err)
962 {
963   gchar *tmp_name;
964   gchar *display_name;
965   gchar *retval;
966   FILE *file;
967   gint fd;
968   int save_errno;
969
970   retval = NULL;
971   
972   tmp_name = g_strdup_printf ("%s.XXXXXX", template);
973
974   errno = 0;
975   fd = g_mkstemp (tmp_name);
976   display_name = g_filename_display_name (tmp_name);
977       
978   if (fd == -1)
979     {
980       save_errno = errno;
981       g_set_error (err,
982                    G_FILE_ERROR,
983                    g_file_error_from_errno (save_errno),
984                    _("Failed to create file '%s': %s"),
985                    display_name, g_strerror (save_errno));
986       
987       goto out;
988     }
989
990   if (!set_umask_permissions (fd, err))
991     {
992       close (fd);
993       g_unlink (tmp_name);
994
995       goto out;
996     }
997   
998   errno = 0;
999   file = fdopen (fd, "wb");
1000   if (!file)
1001     {
1002       save_errno = errno;
1003       g_set_error (err,
1004                    G_FILE_ERROR,
1005                    g_file_error_from_errno (save_errno),
1006                    _("Failed to open file '%s' for writing: fdopen() failed: %s"),
1007                    display_name,
1008                    g_strerror (save_errno));
1009
1010       close (fd);
1011       g_unlink (tmp_name);
1012       
1013       goto out;
1014     }
1015
1016   if (length > 0)
1017     {
1018       size_t n_written;
1019       
1020       errno = 0;
1021
1022       n_written = fwrite (contents, 1, length, file);
1023
1024       if (n_written < length)
1025         {
1026           save_errno = errno;
1027       
1028           g_set_error (err,
1029                        G_FILE_ERROR,
1030                        g_file_error_from_errno (save_errno),
1031                        _("Failed to write file '%s': fwrite() failed: %s"),
1032                        display_name,
1033                        g_strerror (save_errno));
1034
1035           fclose (file);
1036           g_unlink (tmp_name);
1037           
1038           goto out;
1039         }
1040     }
1041    
1042   errno = 0;
1043   if (fclose (file) == EOF)
1044     { 
1045       save_errno = 0;
1046       
1047       g_set_error (err,
1048                    G_FILE_ERROR,
1049                    g_file_error_from_errno (save_errno),
1050                    _("Failed to close file '%s': fclose() failed: %s"),
1051                    display_name, 
1052                    g_strerror (save_errno));
1053
1054       g_unlink (tmp_name);
1055       
1056       goto out;
1057     }
1058
1059   retval = g_strdup (tmp_name);
1060   
1061  out:
1062   g_free (tmp_name);
1063   g_free (display_name);
1064   
1065   return retval;
1066 }
1067
1068 /**
1069  * g_file_replace:
1070  * @filename: name of a file to write @contents to, in the GLib file name
1071  *   encoding
1072  * @contents: string to write to the file
1073  * @length: length of @contents, or -1 if @contents is a nul-terminated string
1074  * @error: return location for a #GError, or %NULL
1075  *
1076  * Writes all of @contents to a file named @filename, with good error checking.
1077  * If a file called @filename already exists it will be overwritten.
1078  *
1079  * This write is atomic in the sense that it is first written to a temporary
1080  * file which is then renamed to the final name. Notes:
1081  * <itemizedlist>
1082  * <listitem>
1083  *    On Unix, if @filename already exists hard links to @filename will break.
1084  *    Also since the file is recreated, existing permissions, access control
1085  *    lists, metadata etc. may be lost. If @filename is a symbolic link,
1086  *    the link itself will be replaced, not the linked file.
1087  * </listitem>
1088  * <listitem>
1089  *   On Windows renaming a file will not remove an existing file with the
1090  *   new name, so on Windows there is a race condition between the existing
1091  *   file being removed and the temporary file being renamed.
1092  * </listitem>
1093  * <listitem>
1094  *   On Windows there is no way to remove a file that is open to some
1095  *   process, or mapped into memory. Thus, this function will fail if
1096  *   @filename already exists and is open.
1097  * </listitem>
1098  * </itemizedlist>
1099  *
1100  * If the call was sucessful, it returns %TRUE. If the call was not successful,
1101  * it returns %FALSE and sets @error. The error domain is #G_FILE_ERROR.
1102  * Possible error codes are those in the #GFileError enumeration.
1103  *
1104  * Return value: %TRUE on success, %FALSE if an error occurred
1105  *
1106  * Since: 2.8
1107  **/
1108 gboolean
1109 g_file_replace (const gchar *filename,
1110                 const gchar *contents,
1111                 gssize       length,
1112                 GError     **error)
1113 {
1114   gchar *tmp_filename;
1115   gboolean retval;
1116   GError *rename_error = NULL;
1117   
1118   g_return_val_if_fail (filename != NULL, FALSE);
1119   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1120   g_return_val_if_fail (contents != NULL || length == 0, FALSE);
1121   g_return_val_if_fail (length >= -1, FALSE);
1122   
1123   if (length == -1)
1124     length = strlen (contents);
1125
1126   tmp_filename = write_to_temp_file (contents, length, filename, error);
1127   
1128   if (!tmp_filename)
1129     {
1130       retval = FALSE;
1131       goto out;
1132     }
1133
1134   if (!rename_file (tmp_filename, filename, &rename_error))
1135     {
1136 #ifndef G_OS_WIN32
1137
1138       g_unlink (tmp_filename);
1139       g_propagate_error (error, rename_error);
1140       retval = FALSE;
1141       goto out;
1142
1143 #else /* G_OS_WIN32 */
1144       
1145       /* Renaming failed, but on Windows this may just mean
1146        * the file already exists. So if the target file
1147        * exists, try deleting it and do the rename again.
1148        */
1149       if (!g_file_test (filename, G_FILE_TEST_EXISTS))
1150         {
1151           g_unlink (tmp_filename);
1152           g_propagate_error (error, rename_error);
1153           retval = FALSE;
1154           goto out;
1155         }
1156
1157       g_error_free (rename_error);
1158       
1159       if (g_unlink (filename) == -1)
1160         {
1161           gchar *display_filename = g_filename_display_name (filename);
1162
1163           save_errno = errno;
1164           
1165           g_set_error (error,
1166                        G_FILE_ERROR,
1167                        g_file_error_from_errno (save_errno),
1168                        _("Existing file '%s' could not be removed: g_unlink() failed: %s"),
1169                        display_filename,
1170                        g_strerror (save_errno));
1171
1172           g_free (display_filename);
1173           g_unlink (tmp_filename);
1174           retval = FALSE;
1175           goto out;
1176         }
1177       
1178       if (!rename_file (tmp_filename, filename, error))
1179         {
1180           g_unlink (tmp_filename);
1181           retval = FALSE;
1182           goto out;
1183         }
1184
1185 #endif
1186     }
1187
1188   retval = TRUE;
1189   
1190  out:
1191   g_free (tmp_filename);
1192   return retval;
1193 }
1194
1195 /*
1196  * mkstemp() implementation is from the GNU C library.
1197  * Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc.
1198  */
1199 /**
1200  * g_mkstemp:
1201  * @tmpl: template filename
1202  *
1203  * Opens a temporary file. See the mkstemp() documentation
1204  * on most UNIX-like systems. This is a portability wrapper, which simply calls 
1205  * mkstemp() on systems that have it, and implements 
1206  * it in GLib otherwise.
1207  *
1208  * The parameter is a string that should match the rules for
1209  * mkstemp(), i.e. end in "XXXXXX". The X string will 
1210  * be modified to form the name of a file that didn't exist.
1211  * The string should be in the GLib file name encoding. Most importantly, 
1212  * on Windows it should be in UTF-8.
1213  *
1214  * Return value: A file handle (as from open()) to the file
1215  * opened for reading and writing. The file is opened in binary mode
1216  * on platforms where there is a difference. The file handle should be
1217  * closed with close(). In case of errors, -1 is returned.
1218  */
1219 gint
1220 g_mkstemp (gchar *tmpl)
1221 {
1222 #ifdef HAVE_MKSTEMP
1223   return mkstemp (tmpl);
1224 #else
1225   int len;
1226   char *XXXXXX;
1227   int count, fd;
1228   static const char letters[] =
1229     "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
1230   static const int NLETTERS = sizeof (letters) - 1;
1231   glong value;
1232   GTimeVal tv;
1233   static int counter = 0;
1234
1235   len = strlen (tmpl);
1236   if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX"))
1237     {
1238       errno = EINVAL;
1239       return -1;
1240     }
1241
1242   /* This is where the Xs start.  */
1243   XXXXXX = &tmpl[len - 6];
1244
1245   /* Get some more or less random data.  */
1246   g_get_current_time (&tv);
1247   value = (tv.tv_usec ^ tv.tv_sec) + counter++;
1248
1249   for (count = 0; count < 100; value += 7777, ++count)
1250     {
1251       glong v = value;
1252
1253       /* Fill in the random bits.  */
1254       XXXXXX[0] = letters[v % NLETTERS];
1255       v /= NLETTERS;
1256       XXXXXX[1] = letters[v % NLETTERS];
1257       v /= NLETTERS;
1258       XXXXXX[2] = letters[v % NLETTERS];
1259       v /= NLETTERS;
1260       XXXXXX[3] = letters[v % NLETTERS];
1261       v /= NLETTERS;
1262       XXXXXX[4] = letters[v % NLETTERS];
1263       v /= NLETTERS;
1264       XXXXXX[5] = letters[v % NLETTERS];
1265
1266       /* tmpl is in UTF-8 on Windows, thus use g_open() */
1267       fd = g_open (tmpl, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0600);
1268
1269       if (fd >= 0)
1270         return fd;
1271       else if (errno != EEXIST)
1272         /* Any other error will apply also to other names we might
1273          *  try, and there are 2^32 or so of them, so give up now.
1274          */
1275         return -1;
1276     }
1277
1278   /* We got out of the loop because we ran out of combinations to try.  */
1279   errno = EEXIST;
1280   return -1;
1281 #endif
1282 }
1283
1284 #ifdef G_OS_WIN32
1285
1286 #undef g_mkstemp
1287
1288 /* Binary compatibility version. Not for newly compiled code. */
1289
1290 gint
1291 g_mkstemp (gchar *tmpl)
1292 {
1293   int len;
1294   char *XXXXXX;
1295   int count, fd;
1296   static const char letters[] =
1297     "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
1298   static const int NLETTERS = sizeof (letters) - 1;
1299   glong value;
1300   GTimeVal tv;
1301   static int counter = 0;
1302
1303   len = strlen (tmpl);
1304   if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX"))
1305     {
1306       errno = EINVAL;
1307       return -1;
1308     }
1309
1310   /* This is where the Xs start.  */
1311   XXXXXX = &tmpl[len - 6];
1312
1313   /* Get some more or less random data.  */
1314   g_get_current_time (&tv);
1315   value = (tv.tv_usec ^ tv.tv_sec) + counter++;
1316
1317   for (count = 0; count < 100; value += 7777, ++count)
1318     {
1319       glong v = value;
1320
1321       /* Fill in the random bits.  */
1322       XXXXXX[0] = letters[v % NLETTERS];
1323       v /= NLETTERS;
1324       XXXXXX[1] = letters[v % NLETTERS];
1325       v /= NLETTERS;
1326       XXXXXX[2] = letters[v % NLETTERS];
1327       v /= NLETTERS;
1328       XXXXXX[3] = letters[v % NLETTERS];
1329       v /= NLETTERS;
1330       XXXXXX[4] = letters[v % NLETTERS];
1331       v /= NLETTERS;
1332       XXXXXX[5] = letters[v % NLETTERS];
1333
1334       /* This is the backward compatibility system codepage version,
1335        * thus use normal open().
1336        */
1337       fd = open (tmpl, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0600);
1338
1339       if (fd >= 0)
1340         return fd;
1341       else if (errno != EEXIST)
1342         /* Any other error will apply also to other names we might
1343          *  try, and there are 2^32 or so of them, so give up now.
1344          */
1345         return -1;
1346     }
1347
1348   /* We got out of the loop because we ran out of combinations to try.  */
1349   errno = EEXIST;
1350   return -1;
1351 }
1352
1353 #endif
1354
1355 /**
1356  * g_file_open_tmp:
1357  * @tmpl: Template for file name, as in g_mkstemp(), basename only
1358  * @name_used: location to store actual name used
1359  * @error: return location for a #GError
1360  *
1361  * Opens a file for writing in the preferred directory for temporary
1362  * files (as returned by g_get_tmp_dir()). 
1363  *
1364  * @tmpl should be a string in the GLib file name encoding ending with
1365  * six 'X' characters, as the parameter to g_mkstemp() (or mkstemp()).
1366  * However, unlike these functions, the template should only be a
1367  * basename, no directory components are allowed. If template is
1368  * %NULL, a default template is used.
1369  *
1370  * Note that in contrast to g_mkstemp() (and mkstemp()) 
1371  * @tmpl is not modified, and might thus be a read-only literal string.
1372  *
1373  * The actual name used is returned in @name_used if non-%NULL. This
1374  * string should be freed with g_free() when not needed any longer.
1375  * The returned name is in the GLib file name encoding.
1376  *
1377  * Return value: A file handle (as from open()) to 
1378  * the file opened for reading and writing. The file is opened in binary 
1379  * mode on platforms where there is a difference. The file handle should be
1380  * closed with close(). In case of errors, -1 is returned 
1381  * and @error will be set.
1382  **/
1383 gint
1384 g_file_open_tmp (const gchar *tmpl,
1385                  gchar      **name_used,
1386                  GError     **error)
1387 {
1388   int retval;
1389   const char *tmpdir;
1390   char *sep;
1391   char *fulltemplate;
1392   const char *slash;
1393
1394   if (tmpl == NULL)
1395     tmpl = ".XXXXXX";
1396
1397   if ((slash = strchr (tmpl, G_DIR_SEPARATOR)) != NULL
1398 #ifdef G_OS_WIN32
1399       || (strchr (tmpl, '/') != NULL && (slash = "/"))
1400 #endif
1401       )
1402     {
1403       gchar *display_tmpl = g_filename_display_name (tmpl);
1404       char c[2];
1405       c[0] = *slash;
1406       c[1] = '\0';
1407
1408       g_set_error (error,
1409                    G_FILE_ERROR,
1410                    G_FILE_ERROR_FAILED,
1411                    _("Template '%s' invalid, should not contain a '%s'"),
1412                    display_tmpl, c);
1413       g_free (display_tmpl);
1414
1415       return -1;
1416     }
1417   
1418   if (strlen (tmpl) < 6 ||
1419       strcmp (tmpl + strlen (tmpl) - 6, "XXXXXX") != 0)
1420     {
1421       gchar *display_tmpl = g_filename_display_name (tmpl);
1422       g_set_error (error,
1423                    G_FILE_ERROR,
1424                    G_FILE_ERROR_FAILED,
1425                    _("Template '%s' doesn't end with XXXXXX"),
1426                    display_tmpl);
1427       g_free (display_tmpl);
1428       return -1;
1429     }
1430
1431   tmpdir = g_get_tmp_dir ();
1432
1433   if (G_IS_DIR_SEPARATOR (tmpdir [strlen (tmpdir) - 1]))
1434     sep = "";
1435   else
1436     sep = G_DIR_SEPARATOR_S;
1437
1438   fulltemplate = g_strconcat (tmpdir, sep, tmpl, NULL);
1439
1440   retval = g_mkstemp (fulltemplate);
1441
1442   if (retval == -1)
1443     {
1444       int save_errno = errno;
1445       gchar *display_fulltemplate = g_filename_display_name (fulltemplate);
1446
1447       g_set_error (error,
1448                    G_FILE_ERROR,
1449                    g_file_error_from_errno (save_errno),
1450                    _("Failed to create file '%s': %s"),
1451                    display_fulltemplate, g_strerror (save_errno));
1452       g_free (display_fulltemplate);
1453       g_free (fulltemplate);
1454       return -1;
1455     }
1456
1457   if (name_used)
1458     *name_used = fulltemplate;
1459   else
1460     g_free (fulltemplate);
1461
1462   return retval;
1463 }
1464
1465 #ifdef G_OS_WIN32
1466
1467 #undef g_file_open_tmp
1468
1469 /* Binary compatibility version. Not for newly compiled code. */
1470
1471 gint
1472 g_file_open_tmp (const gchar *tmpl,
1473                  gchar      **name_used,
1474                  GError     **error)
1475 {
1476   gchar *utf8_tmpl = g_locale_to_utf8 (tmpl, -1, NULL, NULL, error);
1477   gchar *utf8_name_used;
1478   gint retval;
1479
1480   if (utf8_tmpl == NULL)
1481     return -1;
1482
1483   retval = g_file_open_tmp_utf8 (utf8_tmpl, &utf8_name_used, error);
1484   
1485   if (retval == -1)
1486     return -1;
1487
1488   if (name_used)
1489     *name_used = g_locale_from_utf8 (utf8_name_used, -1, NULL, NULL, NULL);
1490
1491   g_free (utf8_name_used);
1492
1493   return retval;
1494 }
1495
1496 #endif
1497
1498 static gchar *
1499 g_build_pathv (const gchar *separator,
1500                const gchar *first_element,
1501                va_list      args)
1502 {
1503   GString *result;
1504   gint separator_len = strlen (separator);
1505   gboolean is_first = TRUE;
1506   gboolean have_leading = FALSE;
1507   const gchar *single_element = NULL;
1508   const gchar *next_element;
1509   const gchar *last_trailing = NULL;
1510
1511   result = g_string_new (NULL);
1512
1513   next_element = first_element;
1514
1515   while (TRUE)
1516     {
1517       const gchar *element;
1518       const gchar *start;
1519       const gchar *end;
1520
1521       if (next_element)
1522         {
1523           element = next_element;
1524           next_element = va_arg (args, gchar *);
1525         }
1526       else
1527         break;
1528
1529       /* Ignore empty elements */
1530       if (!*element)
1531         continue;
1532       
1533       start = element;
1534
1535       if (separator_len)
1536         {
1537           while (start &&
1538                  strncmp (start, separator, separator_len) == 0)
1539             start += separator_len;
1540         }
1541
1542       end = start + strlen (start);
1543       
1544       if (separator_len)
1545         {
1546           while (end >= start + separator_len &&
1547                  strncmp (end - separator_len, separator, separator_len) == 0)
1548             end -= separator_len;
1549           
1550           last_trailing = end;
1551           while (last_trailing >= element + separator_len &&
1552                  strncmp (last_trailing - separator_len, separator, separator_len) == 0)
1553             last_trailing -= separator_len;
1554
1555           if (!have_leading)
1556             {
1557               /* If the leading and trailing separator strings are in the
1558                * same element and overlap, the result is exactly that element
1559                */
1560               if (last_trailing <= start)
1561                 single_element = element;
1562                   
1563               g_string_append_len (result, element, start - element);
1564               have_leading = TRUE;
1565             }
1566           else
1567             single_element = NULL;
1568         }
1569
1570       if (end == start)
1571         continue;
1572
1573       if (!is_first)
1574         g_string_append (result, separator);
1575       
1576       g_string_append_len (result, start, end - start);
1577       is_first = FALSE;
1578     }
1579
1580   if (single_element)
1581     {
1582       g_string_free (result, TRUE);
1583       return g_strdup (single_element);
1584     }
1585   else
1586     {
1587       if (last_trailing)
1588         g_string_append (result, last_trailing);
1589   
1590       return g_string_free (result, FALSE);
1591     }
1592 }
1593
1594 /**
1595  * g_build_path:
1596  * @separator: a string used to separator the elements of the path.
1597  * @first_element: the first element in the path
1598  * @Varargs: remaining elements in path, terminated by %NULL
1599  * 
1600  * Creates a path from a series of elements using @separator as the
1601  * separator between elements. At the boundary between two elements,
1602  * any trailing occurrences of separator in the first element, or
1603  * leading occurrences of separator in the second element are removed
1604  * and exactly one copy of the separator is inserted.
1605  *
1606  * Empty elements are ignored.
1607  *
1608  * The number of leading copies of the separator on the result is
1609  * the same as the number of leading copies of the separator on
1610  * the first non-empty element.
1611  *
1612  * The number of trailing copies of the separator on the result is
1613  * the same as the number of trailing copies of the separator on
1614  * the last non-empty element. (Determination of the number of
1615  * trailing copies is done without stripping leading copies, so
1616  * if the separator is <literal>ABA</literal>, <literal>ABABA</literal>
1617  * has 1 trailing copy.)
1618  *
1619  * However, if there is only a single non-empty element, and there
1620  * are no characters in that element not part of the leading or
1621  * trailing separators, then the result is exactly the original value
1622  * of that element.
1623  *
1624  * Other than for determination of the number of leading and trailing
1625  * copies of the separator, elements consisting only of copies
1626  * of the separator are ignored.
1627  * 
1628  * Return value: a newly-allocated string that must be freed with g_free().
1629  **/
1630 gchar *
1631 g_build_path (const gchar *separator,
1632               const gchar *first_element,
1633               ...)
1634 {
1635   gchar *str;
1636   va_list args;
1637
1638   g_return_val_if_fail (separator != NULL, NULL);
1639
1640   va_start (args, first_element);
1641   str = g_build_pathv (separator, first_element, args);
1642   va_end (args);
1643
1644   return str;
1645 }
1646
1647 /**
1648  * g_build_filename:
1649  * @first_element: the first element in the path
1650  * @Varargs: remaining elements in path, terminated by %NULL
1651  * 
1652  * Creates a filename from a series of elements using the correct
1653  * separator for filenames.
1654  *
1655  * On Unix, this function behaves identically to <literal>g_build_path
1656  * (G_DIR_SEPARATOR_S, first_element, ....)</literal>.
1657  *
1658  * On Windows, it takes into account that either the backslash
1659  * (<literal>\</literal> or slash (<literal>/</literal>) can be used
1660  * as separator in filenames, but otherwise behaves as on Unix. When
1661  * file pathname separators need to be inserted, the one that last
1662  * previously occurred in the parameters (reading from left to right)
1663  * is used.
1664  *
1665  * No attempt is made to force the resulting filename to be an absolute
1666  * path. If the first element is a relative path, the result will
1667  * be a relative path. 
1668  * 
1669  * Return value: a newly-allocated string that must be freed with g_free().
1670  **/
1671 gchar *
1672 g_build_filename (const gchar *first_element, 
1673                   ...)
1674 {
1675 #ifndef G_OS_WIN32
1676   gchar *str;
1677   va_list args;
1678
1679   va_start (args, first_element);
1680   str = g_build_pathv (G_DIR_SEPARATOR_S, first_element, args);
1681   va_end (args);
1682
1683   return str;
1684 #else
1685   /* Code copied from g_build_pathv(), and modifed to use two
1686    * alternative single-character separators.
1687    */
1688   va_list args;
1689   GString *result;
1690   gboolean is_first = TRUE;
1691   gboolean have_leading = FALSE;
1692   const gchar *single_element = NULL;
1693   const gchar *next_element;
1694   const gchar *last_trailing = NULL;
1695   gchar current_separator = '\\';
1696
1697   va_start (args, first_element);
1698
1699   result = g_string_new (NULL);
1700
1701   next_element = first_element;
1702
1703   while (TRUE)
1704     {
1705       const gchar *element;
1706       const gchar *start;
1707       const gchar *end;
1708
1709       if (next_element)
1710         {
1711           element = next_element;
1712           next_element = va_arg (args, gchar *);
1713         }
1714       else
1715         break;
1716
1717       /* Ignore empty elements */
1718       if (!*element)
1719         continue;
1720       
1721       start = element;
1722
1723       if (TRUE)
1724         {
1725           while (start &&
1726                  (*start == '\\' || *start == '/'))
1727             {
1728               current_separator = *start;
1729               start++;
1730             }
1731         }
1732
1733       end = start + strlen (start);
1734       
1735       if (TRUE)
1736         {
1737           while (end >= start + 1 &&
1738                  (end[-1] == '\\' || end[-1] == '/'))
1739             {
1740               current_separator = end[-1];
1741               end--;
1742             }
1743           
1744           last_trailing = end;
1745           while (last_trailing >= element + 1 &&
1746                  (last_trailing[-1] == '\\' || last_trailing[-1] == '/'))
1747             last_trailing--;
1748
1749           if (!have_leading)
1750             {
1751               /* If the leading and trailing separator strings are in the
1752                * same element and overlap, the result is exactly that element
1753                */
1754               if (last_trailing <= start)
1755                 single_element = element;
1756                   
1757               g_string_append_len (result, element, start - element);
1758               have_leading = TRUE;
1759             }
1760           else
1761             single_element = NULL;
1762         }
1763
1764       if (end == start)
1765         continue;
1766
1767       if (!is_first)
1768         g_string_append_len (result, &current_separator, 1);
1769       
1770       g_string_append_len (result, start, end - start);
1771       is_first = FALSE;
1772     }
1773
1774   va_end (args);
1775
1776   if (single_element)
1777     {
1778       g_string_free (result, TRUE);
1779       return g_strdup (single_element);
1780     }
1781   else
1782     {
1783       if (last_trailing)
1784         g_string_append (result, last_trailing);
1785   
1786       return g_string_free (result, FALSE);
1787     }
1788 #endif
1789 }
1790
1791 /**
1792  * g_file_read_link:
1793  * @filename: the symbolic link
1794  * @error: return location for a #GError
1795  *
1796  * Reads the contents of the symbolic link @filename like the POSIX
1797  * readlink() function.  The returned string is in the encoding used
1798  * for filenames. Use g_filename_to_utf8() to convert it to UTF-8.
1799  *
1800  * Returns: A newly allocated string with the contents of the symbolic link, 
1801  *          or %NULL if an error occurred.
1802  *
1803  * Since: 2.4
1804  */
1805 gchar *
1806 g_file_read_link (const gchar *filename,
1807                   GError     **error)
1808 {
1809 #ifdef HAVE_READLINK
1810   gchar *buffer;
1811   guint size;
1812   gint read_size;    
1813   
1814   size = 256; 
1815   buffer = g_malloc (size);
1816   
1817   while (TRUE) 
1818     {
1819       read_size = readlink (filename, buffer, size);
1820       if (read_size < 0) {
1821         int save_errno = errno;
1822         gchar *display_filename = g_filename_display_name (filename);
1823
1824         g_free (buffer);
1825         g_set_error (error,
1826                      G_FILE_ERROR,
1827                      g_file_error_from_errno (save_errno),
1828                      _("Failed to read the symbolic link '%s': %s"),
1829                      display_filename, 
1830                      g_strerror (save_errno));
1831         g_free (display_filename);
1832         
1833         return NULL;
1834       }
1835     
1836       if (read_size < size) 
1837         {
1838           buffer[read_size] = 0;
1839           return buffer;
1840         }
1841       
1842       size *= 2;
1843       buffer = g_realloc (buffer, size);
1844     }
1845 #else
1846   g_set_error (error,
1847                G_FILE_ERROR,
1848                G_FILE_ERROR_INVAL,
1849                _("Symbolic links not supported"));
1850         
1851   return NULL;
1852 #endif
1853 }
1854
1855 #define __G_FILEUTILS_C__
1856 #include "galiasdef.c"