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