Fix #151193, Stepan Kasal:
[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 <fcntl.h>
37 #include <stdlib.h>
38
39 #ifdef G_OS_WIN32
40 #include <io.h>
41 #ifndef F_OK
42 #define F_OK 0
43 #define W_OK 2
44 #define R_OK 4
45 #endif /* !F_OK */
46
47 #ifndef S_ISREG
48 #define S_ISREG(mode) ((mode)&_S_IFREG)
49 #endif
50
51 #ifndef S_ISDIR
52 #define S_ISDIR(mode) ((mode)&_S_IFDIR)
53 #endif
54
55 #endif /* G_OS_WIN32 */
56
57 #ifndef S_ISLNK
58 #define S_ISLNK(x) 0
59 #endif
60
61 #ifndef O_BINARY
62 #define O_BINARY 0
63 #endif
64
65 #include "glibintl.h"
66
67 #ifdef G_OS_WIN32
68 #define G_IS_DIR_SEPARATOR(c) (c == G_DIR_SEPARATOR || c == '/')
69 #else
70 #define G_IS_DIR_SEPARATOR(c) (c == G_DIR_SEPARATOR)
71 #endif
72
73 /**
74  * g_file_test:
75  * @filename: a filename to test
76  * @test: bitfield of #GFileTest flags
77  * 
78  * Returns %TRUE if any of the tests in the bitfield @test are
79  * %TRUE. For example, <literal>(G_FILE_TEST_EXISTS | 
80  * G_FILE_TEST_IS_DIR)</literal> will return %TRUE if the file exists; 
81  * the check whether it's a directory doesn't matter since the existence 
82  * test is %TRUE. With the current set of available tests, there's no point
83  * passing in more than one test at a time.
84  * 
85  * Apart from %G_FILE_TEST_IS_SYMLINK all tests follow symbolic links,
86  * so for a symbolic link to a regular file g_file_test() will return
87  * %TRUE for both %G_FILE_TEST_IS_SYMLINK and %G_FILE_TEST_IS_REGULAR.
88  *
89  * Note, that for a dangling symbolic link g_file_test() will return
90  * %TRUE for %G_FILE_TEST_IS_SYMLINK and %FALSE for all other flags.
91  *
92  * You should never use g_file_test() to test whether it is safe
93  * to perform an operaton, because there is always the possibility
94  * of the condition changing before you actually perform the operation.
95  * For example, you might think you could use %G_FILE_TEST_IS_SYMLINK
96  * to know whether it is is safe to write to a file without being
97  * tricked into writing into a different location. It doesn't work!
98  *
99  * <informalexample><programlisting>
100  * /&ast; DON'T DO THIS &ast;/
101  *  if (!g_file_test (filename, G_FILE_TEST_IS_SYMLINK)) {
102  *    fd = open (filename, O_WRONLY);
103  *    /&ast; write to fd &ast;/
104  *  }
105  * </programlisting></informalexample>
106  *
107  * Another thing to note is that %G_FILE_TEST_EXISTS and
108  * %G_FILE_TEST_IS_EXECUTABLE are implemented using the access()
109  * system call. This usually doesn't matter, but if your program
110  * is setuid or setgid it means that these tests will give you
111  * the answer for the real user ID and group ID , rather than the
112  * effective user ID and group ID.
113  *
114  * Return value: whether a test was %TRUE
115  **/
116 gboolean
117 g_file_test (const gchar *filename,
118              GFileTest    test)
119 {
120   if ((test & G_FILE_TEST_EXISTS) && (access (filename, F_OK) == 0))
121     return TRUE;
122   
123 #ifndef G_OS_WIN32
124   if ((test & G_FILE_TEST_IS_EXECUTABLE) && (access (filename, X_OK) == 0))
125     {
126       if (getuid () != 0)
127         return TRUE;
128
129       /* For root, on some POSIX systems, access (filename, X_OK)
130        * will succeed even if no executable bits are set on the
131        * file. We fall through to a stat test to avoid that.
132        */
133     }
134   else
135     test &= ~G_FILE_TEST_IS_EXECUTABLE;
136 #endif  
137
138   if (test & G_FILE_TEST_IS_SYMLINK)
139     {
140 #ifdef G_OS_WIN32
141       /* no sym links on win32, no lstat in msvcrt */
142 #else
143       struct stat s;
144
145       if ((lstat (filename, &s) == 0) && S_ISLNK (s.st_mode))
146         return TRUE;
147 #endif
148     }
149   
150   if (test & (G_FILE_TEST_IS_REGULAR |
151               G_FILE_TEST_IS_DIR |
152               G_FILE_TEST_IS_EXECUTABLE))
153     {
154       struct stat s;
155       
156       if (stat (filename, &s) == 0)
157         {
158           if ((test & G_FILE_TEST_IS_REGULAR) && S_ISREG (s.st_mode))
159             return TRUE;
160           
161           if ((test & G_FILE_TEST_IS_DIR) && S_ISDIR (s.st_mode))
162             return TRUE;
163
164 #ifndef G_OS_WIN32
165           /* The extra test for root when access (file, X_OK) succeeds.
166            * Probably only makes sense on Unix.
167            */
168           if ((test & G_FILE_TEST_IS_EXECUTABLE) &&
169               ((s.st_mode & S_IXOTH) ||
170                (s.st_mode & S_IXUSR) ||
171                (s.st_mode & S_IXGRP)))
172             return TRUE;
173 #else
174           if ((test & G_FILE_TEST_IS_EXECUTABLE) &&
175               (s.st_mode & _S_IEXEC))
176             return TRUE;
177 #endif
178         }
179     }
180
181   return FALSE;
182 }
183
184 GQuark
185 g_file_error_quark (void)
186 {
187   static GQuark q = 0;
188   if (q == 0)
189     q = g_quark_from_static_string ("g-file-error-quark");
190
191   return q;
192 }
193
194 /**
195  * g_file_error_from_errno:
196  * @err_no: an "errno" value
197  * 
198  * Gets a #GFileError constant based on the passed-in @errno.
199  * For example, if you pass in %EEXIST this function returns
200  * #G_FILE_ERROR_EXIST. Unlike @errno values, you can portably
201  * assume that all #GFileError values will exist.
202  *
203  * Normally a #GFileError value goes into a #GError returned
204  * from a function that manipulates files. So you would use
205  * g_file_error_from_errno() when constructing a #GError.
206  * 
207  * Return value: #GFileError corresponding to the given @errno
208  **/
209 GFileError
210 g_file_error_from_errno (gint err_no)
211 {
212   switch (err_no)
213     {
214 #ifdef EEXIST
215     case EEXIST:
216       return G_FILE_ERROR_EXIST;
217       break;
218 #endif
219
220 #ifdef EISDIR
221     case EISDIR:
222       return G_FILE_ERROR_ISDIR;
223       break;
224 #endif
225
226 #ifdef EACCES
227     case EACCES:
228       return G_FILE_ERROR_ACCES;
229       break;
230 #endif
231
232 #ifdef ENAMETOOLONG
233     case ENAMETOOLONG:
234       return G_FILE_ERROR_NAMETOOLONG;
235       break;
236 #endif
237
238 #ifdef ENOENT
239     case ENOENT:
240       return G_FILE_ERROR_NOENT;
241       break;
242 #endif
243
244 #ifdef ENOTDIR
245     case ENOTDIR:
246       return G_FILE_ERROR_NOTDIR;
247       break;
248 #endif
249
250 #ifdef ENXIO
251     case ENXIO:
252       return G_FILE_ERROR_NXIO;
253       break;
254 #endif
255
256 #ifdef ENODEV
257     case ENODEV:
258       return G_FILE_ERROR_NODEV;
259       break;
260 #endif
261
262 #ifdef EROFS
263     case EROFS:
264       return G_FILE_ERROR_ROFS;
265       break;
266 #endif
267
268 #ifdef ETXTBSY
269     case ETXTBSY:
270       return G_FILE_ERROR_TXTBSY;
271       break;
272 #endif
273
274 #ifdef EFAULT
275     case EFAULT:
276       return G_FILE_ERROR_FAULT;
277       break;
278 #endif
279
280 #ifdef ELOOP
281     case ELOOP:
282       return G_FILE_ERROR_LOOP;
283       break;
284 #endif
285
286 #ifdef ENOSPC
287     case ENOSPC:
288       return G_FILE_ERROR_NOSPC;
289       break;
290 #endif
291
292 #ifdef ENOMEM
293     case ENOMEM:
294       return G_FILE_ERROR_NOMEM;
295       break;
296 #endif
297
298 #ifdef EMFILE
299     case EMFILE:
300       return G_FILE_ERROR_MFILE;
301       break;
302 #endif
303
304 #ifdef ENFILE
305     case ENFILE:
306       return G_FILE_ERROR_NFILE;
307       break;
308 #endif
309
310 #ifdef EBADF
311     case EBADF:
312       return G_FILE_ERROR_BADF;
313       break;
314 #endif
315
316 #ifdef EINVAL
317     case EINVAL:
318       return G_FILE_ERROR_INVAL;
319       break;
320 #endif
321
322 #ifdef EPIPE
323     case EPIPE:
324       return G_FILE_ERROR_PIPE;
325       break;
326 #endif
327
328 #ifdef EAGAIN
329     case EAGAIN:
330       return G_FILE_ERROR_AGAIN;
331       break;
332 #endif
333
334 #ifdef EINTR
335     case EINTR:
336       return G_FILE_ERROR_INTR;
337       break;
338 #endif
339
340 #ifdef EIO
341     case EIO:
342       return G_FILE_ERROR_IO;
343       break;
344 #endif
345
346 #ifdef EPERM
347     case EPERM:
348       return G_FILE_ERROR_PERM;
349       break;
350 #endif
351
352 #ifdef ENOSYS
353     case ENOSYS:
354       return G_FILE_ERROR_NOSYS;
355       break;
356 #endif
357
358     default:
359       return G_FILE_ERROR_FAILED;
360       break;
361     }
362 }
363
364 static gboolean
365 get_contents_stdio (const gchar *filename,
366                     FILE        *f,
367                     gchar      **contents,
368                     gsize       *length, 
369                     GError     **error)
370 {
371   gchar buf[2048];
372   size_t bytes;
373   char *str;
374   size_t total_bytes;
375   size_t total_allocated;
376   
377   g_assert (f != NULL);
378
379 #define STARTING_ALLOC 64
380   
381   total_bytes = 0;
382   total_allocated = STARTING_ALLOC;
383   str = g_malloc (STARTING_ALLOC);
384   
385   while (!feof (f))
386     {
387       bytes = fread (buf, 1, 2048, f);
388
389       while ((total_bytes + bytes + 1) > total_allocated)
390         {
391           total_allocated *= 2;
392           str = g_try_realloc (str, total_allocated);
393
394           if (str == NULL)
395             {
396               g_set_error (error,
397                            G_FILE_ERROR,
398                            G_FILE_ERROR_NOMEM,
399                            _("Could not allocate %lu bytes to read file \"%s\""),
400                            (gulong) total_allocated, filename);
401               goto error;
402             }
403         }
404       
405       if (ferror (f))
406         {
407           g_set_error (error,
408                        G_FILE_ERROR,
409                        g_file_error_from_errno (errno),
410                        _("Error reading file '%s': %s"),
411                        filename, g_strerror (errno));
412
413           goto error;
414         }
415
416       memcpy (str + total_bytes, buf, bytes);
417       total_bytes += bytes;
418     }
419
420   fclose (f);
421
422   str[total_bytes] = '\0';
423   
424   if (length)
425     *length = total_bytes;
426   
427   *contents = str;
428   
429   return TRUE;
430
431  error:
432
433   g_free (str);
434   fclose (f);
435   
436   return FALSE;  
437 }
438
439 #ifndef G_OS_WIN32
440
441 static gboolean
442 get_contents_regfile (const gchar *filename,
443                       struct stat *stat_buf,
444                       gint         fd,
445                       gchar      **contents,
446                       gsize       *length,
447                       GError     **error)
448 {
449   gchar *buf;
450   size_t bytes_read;
451   size_t size;
452   size_t alloc_size;
453   
454   size = stat_buf->st_size;
455
456   alloc_size = size + 1;
457   buf = g_try_malloc (alloc_size);
458
459   if (buf == NULL)
460     {
461       g_set_error (error,
462                    G_FILE_ERROR,
463                    G_FILE_ERROR_NOMEM,
464                    _("Could not allocate %lu bytes to read file \"%s\""),
465                    (gulong) alloc_size, filename);
466
467       goto error;
468     }
469   
470   bytes_read = 0;
471   while (bytes_read < size)
472     {
473       gssize rc;
474           
475       rc = read (fd, buf + bytes_read, size - bytes_read);
476
477       if (rc < 0)
478         {
479           if (errno != EINTR) 
480             {
481               g_free (buf);
482                   
483               g_set_error (error,
484                            G_FILE_ERROR,
485                            g_file_error_from_errno (errno),
486                            _("Failed to read from file '%s': %s"),
487                            filename, g_strerror (errno));
488
489               goto error;
490             }
491         }
492       else if (rc == 0)
493         break;
494       else
495         bytes_read += rc;
496     }
497       
498   buf[bytes_read] = '\0';
499
500   if (length)
501     *length = bytes_read;
502   
503   *contents = buf;
504
505   close (fd);
506
507   return TRUE;
508
509  error:
510
511   close (fd);
512   
513   return FALSE;
514 }
515
516 static gboolean
517 get_contents_posix (const gchar *filename,
518                     gchar      **contents,
519                     gsize       *length,
520                     GError     **error)
521 {
522   struct stat stat_buf;
523   gint fd;
524   
525   /* O_BINARY useful on Cygwin */
526   fd = open (filename, O_RDONLY|O_BINARY);
527
528   if (fd < 0)
529     {
530       g_set_error (error,
531                    G_FILE_ERROR,
532                    g_file_error_from_errno (errno),
533                    _("Failed to open file '%s': %s"),
534                    filename, g_strerror (errno));
535
536       return FALSE;
537     }
538
539   /* I don't think this will ever fail, aside from ENOMEM, but. */
540   if (fstat (fd, &stat_buf) < 0)
541     {
542       close (fd);
543       
544       g_set_error (error,
545                    G_FILE_ERROR,
546                    g_file_error_from_errno (errno),
547                    _("Failed to get attributes of file '%s': fstat() failed: %s"),
548                    filename, g_strerror (errno));
549
550       return FALSE;
551     }
552
553   if (stat_buf.st_size > 0 && S_ISREG (stat_buf.st_mode))
554     {
555       return get_contents_regfile (filename,
556                                    &stat_buf,
557                                    fd,
558                                    contents,
559                                    length,
560                                    error);
561     }
562   else
563     {
564       FILE *f;
565
566       f = fdopen (fd, "r");
567       
568       if (f == NULL)
569         {
570           g_set_error (error,
571                        G_FILE_ERROR,
572                        g_file_error_from_errno (errno),
573                        _("Failed to open file '%s': fdopen() failed: %s"),
574                        filename, g_strerror (errno));
575           
576           return FALSE;
577         }
578   
579       return get_contents_stdio (filename, f, contents, length, error);
580     }
581 }
582
583 #else  /* G_OS_WIN32 */
584
585 static gboolean
586 get_contents_win32 (const gchar *filename,
587                     gchar      **contents,
588                     gsize       *length,
589                     GError     **error)
590 {
591   FILE *f;
592
593   /* I guess you want binary mode; maybe you want text sometimes? */
594   f = fopen (filename, "rb");
595
596   if (f == NULL)
597     {
598       g_set_error (error,
599                    G_FILE_ERROR,
600                    g_file_error_from_errno (errno),
601                    _("Failed to open file '%s': %s"),
602                    filename, g_strerror (errno));
603       
604       return FALSE;
605     }
606   
607   return get_contents_stdio (filename, f, contents, length, error);
608 }
609
610 #endif
611
612 /**
613  * g_file_get_contents:
614  * @filename: a file to read contents from
615  * @contents: location to store an allocated string
616  * @length: location to store length in bytes of the contents
617  * @error: return location for a #GError
618  * 
619  * Reads an entire file into allocated memory, with good error
620  * checking. If @error is set, %FALSE is returned, and @contents is set
621  * to %NULL. If %TRUE is returned, @error will not be set, and @contents
622  * will be set to the file contents.  The string stored in @contents
623  * will be nul-terminated, so for text files you can pass %NULL for the
624  * @length argument.  The error domain is #G_FILE_ERROR. Possible
625  * error codes are those in the #GFileError enumeration.
626  *
627  * Return value: %TRUE on success, %FALSE if error is set
628  **/
629 gboolean
630 g_file_get_contents (const gchar *filename,
631                      gchar      **contents,
632                      gsize       *length,
633                      GError     **error)
634 {  
635   g_return_val_if_fail (filename != NULL, FALSE);
636   g_return_val_if_fail (contents != NULL, FALSE);
637
638   *contents = NULL;
639   if (length)
640     *length = 0;
641
642 #ifdef G_OS_WIN32
643   return get_contents_win32 (filename, contents, length, error);
644 #else
645   return get_contents_posix (filename, contents, length, error);
646 #endif
647 }
648
649 /*
650  * mkstemp() implementation is from the GNU C library.
651  * Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc.
652  */
653 /**
654  * g_mkstemp:
655  * @tmpl: template filename
656  *
657  * Opens a temporary file. See the mkstemp() documentation
658  * on most UNIX-like systems. This is a portability wrapper, which simply calls 
659  * mkstemp() on systems that have it, and implements 
660  * it in GLib otherwise.
661  *
662  * The parameter is a string that should match the rules for
663  * mkstemp(), i.e. end in "XXXXXX". The X string will 
664  * be modified to form the name of a file that didn't exist.
665  *
666  * Return value: A file handle (as from open()) to the file
667  * opened for reading and writing. The file is opened in binary mode
668  * on platforms where there is a difference. The file handle should be
669  * closed with close(). In case of errors, -1 is returned.
670  */
671 gint
672 g_mkstemp (gchar *tmpl)
673 {
674 #ifdef HAVE_MKSTEMP
675   return mkstemp (tmpl);
676 #else
677   int len;
678   char *XXXXXX;
679   int count, fd;
680   static const char letters[] =
681     "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
682   static const int NLETTERS = sizeof (letters) - 1;
683   glong value;
684   GTimeVal tv;
685   static int counter = 0;
686
687   len = strlen (tmpl);
688   if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX"))
689     return -1;
690
691   /* This is where the Xs start.  */
692   XXXXXX = &tmpl[len - 6];
693
694   /* Get some more or less random data.  */
695   g_get_current_time (&tv);
696   value = (tv.tv_usec ^ tv.tv_sec) + counter++;
697
698   for (count = 0; count < 100; value += 7777, ++count)
699     {
700       glong v = value;
701
702       /* Fill in the random bits.  */
703       XXXXXX[0] = letters[v % NLETTERS];
704       v /= NLETTERS;
705       XXXXXX[1] = letters[v % NLETTERS];
706       v /= NLETTERS;
707       XXXXXX[2] = letters[v % NLETTERS];
708       v /= NLETTERS;
709       XXXXXX[3] = letters[v % NLETTERS];
710       v /= NLETTERS;
711       XXXXXX[4] = letters[v % NLETTERS];
712       v /= NLETTERS;
713       XXXXXX[5] = letters[v % NLETTERS];
714
715       fd = open (tmpl, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0600);
716
717       if (fd >= 0)
718         return fd;
719       else if (errno != EEXIST)
720         /* Any other error will apply also to other names we might
721          *  try, and there are 2^32 or so of them, so give up now.
722          */
723         return -1;
724     }
725
726   /* We got out of the loop because we ran out of combinations to try.  */
727   return -1;
728 #endif
729 }
730
731 /**
732  * g_file_open_tmp:
733  * @tmpl: Template for file name, as in g_mkstemp(), basename only
734  * @name_used: location to store actual name used
735  * @error: return location for a #GError
736  *
737  * Opens a file for writing in the preferred directory for temporary
738  * files (as returned by g_get_tmp_dir()). 
739  *
740  * @tmpl should be a string ending with six 'X' characters, as the
741  * parameter to g_mkstemp() (or mkstemp()). 
742  * However, unlike these functions, the template should only be a 
743  * basename, no directory components are allowed. If template is %NULL, 
744  * a default template is used.
745  *
746  * Note that in contrast to g_mkstemp() (and mkstemp()) 
747  * @tmpl is not modified, and might thus be a read-only literal string.
748  *
749  * The actual name used is returned in @name_used if non-%NULL. This
750  * string should be freed with g_free() when not needed any longer.
751  *
752  * Return value: A file handle (as from open()) to 
753  * the file opened for reading and writing. The file is opened in binary 
754  * mode on platforms where there is a difference. The file handle should be
755  * closed with close(). In case of errors, -1 is returned 
756  * and @error will be set.
757  **/
758 gint
759 g_file_open_tmp (const gchar *tmpl,
760                  gchar      **name_used,
761                  GError     **error)
762 {
763   int retval;
764   const char *tmpdir;
765   char *sep;
766   char *fulltemplate;
767   const char *slash;
768
769   if (tmpl == NULL)
770     tmpl = ".XXXXXX";
771
772   if ((slash = strchr (tmpl, G_DIR_SEPARATOR)) != NULL
773 #ifdef G_OS_WIN32
774       || (strchr (tmpl, '/') != NULL && (slash = "/"))
775 #endif
776       )
777     {
778       char c[2];
779       c[0] = *slash;
780       c[1] = '\0';
781
782       g_set_error (error,
783                    G_FILE_ERROR,
784                    G_FILE_ERROR_FAILED,
785                    _("Template '%s' invalid, should not contain a '%s'"),
786                    tmpl, c);
787
788       return -1;
789     }
790   
791   if (strlen (tmpl) < 6 ||
792       strcmp (tmpl + strlen (tmpl) - 6, "XXXXXX") != 0)
793     {
794       g_set_error (error,
795                    G_FILE_ERROR,
796                    G_FILE_ERROR_FAILED,
797                    _("Template '%s' doesn't end with XXXXXX"),
798                    tmpl);
799       return -1;
800     }
801
802   tmpdir = g_get_tmp_dir ();
803
804   if (G_IS_DIR_SEPARATOR (tmpdir [strlen (tmpdir) - 1]))
805     sep = "";
806   else
807     sep = G_DIR_SEPARATOR_S;
808
809   fulltemplate = g_strconcat (tmpdir, sep, tmpl, NULL);
810
811   retval = g_mkstemp (fulltemplate);
812
813   if (retval == -1)
814     {
815       g_set_error (error,
816                    G_FILE_ERROR,
817                    g_file_error_from_errno (errno),
818                    _("Failed to create file '%s': %s"),
819                    fulltemplate, g_strerror (errno));
820       g_free (fulltemplate);
821       return -1;
822     }
823
824   if (name_used)
825     *name_used = fulltemplate;
826   else
827     g_free (fulltemplate);
828
829   return retval;
830 }
831
832 static gchar *
833 g_build_pathv (const gchar *separator,
834                const gchar *first_element,
835                va_list      args)
836 {
837   GString *result;
838   gint separator_len = strlen (separator);
839   gboolean is_first = TRUE;
840   gboolean have_leading = FALSE;
841   const gchar *single_element = NULL;
842   const gchar *next_element;
843   const gchar *last_trailing = NULL;
844
845   result = g_string_new (NULL);
846
847   next_element = first_element;
848
849   while (TRUE)
850     {
851       const gchar *element;
852       const gchar *start;
853       const gchar *end;
854
855       if (next_element)
856         {
857           element = next_element;
858           next_element = va_arg (args, gchar *);
859         }
860       else
861         break;
862
863       /* Ignore empty elements */
864       if (!*element)
865         continue;
866       
867       start = element;
868
869       if (separator_len)
870         {
871           while (start &&
872                  strncmp (start, separator, separator_len) == 0)
873             start += separator_len;
874         }
875
876       end = start + strlen (start);
877       
878       if (separator_len)
879         {
880           while (end >= start + separator_len &&
881                  strncmp (end - separator_len, separator, separator_len) == 0)
882             end -= separator_len;
883           
884           last_trailing = end;
885           while (last_trailing >= element + separator_len &&
886                  strncmp (last_trailing - separator_len, separator, separator_len) == 0)
887             last_trailing -= separator_len;
888
889           if (!have_leading)
890             {
891               /* If the leading and trailing separator strings are in the
892                * same element and overlap, the result is exactly that element
893                */
894               if (last_trailing <= start)
895                 single_element = element;
896                   
897               g_string_append_len (result, element, start - element);
898               have_leading = TRUE;
899             }
900           else
901             single_element = NULL;
902         }
903
904       if (end == start)
905         continue;
906
907       if (!is_first)
908         g_string_append (result, separator);
909       
910       g_string_append_len (result, start, end - start);
911       is_first = FALSE;
912     }
913
914   if (single_element)
915     {
916       g_string_free (result, TRUE);
917       return g_strdup (single_element);
918     }
919   else
920     {
921       if (last_trailing)
922         g_string_append (result, last_trailing);
923   
924       return g_string_free (result, FALSE);
925     }
926 }
927
928 /**
929  * g_build_path:
930  * @separator: a string used to separator the elements of the path.
931  * @first_element: the first element in the path
932  * @Varargs: remaining elements in path, terminated by %NULL
933  * 
934  * Creates a path from a series of elements using @separator as the
935  * separator between elements. At the boundary between two elements,
936  * any trailing occurrences of separator in the first element, or
937  * leading occurrences of separator in the second element are removed
938  * and exactly one copy of the separator is inserted.
939  *
940  * Empty elements are ignored.
941  *
942  * The number of leading copies of the separator on the result is
943  * the same as the number of leading copies of the separator on
944  * the first non-empty element.
945  *
946  * The number of trailing copies of the separator on the result is
947  * the same as the number of trailing copies of the separator on
948  * the last non-empty element. (Determination of the number of
949  * trailing copies is done without stripping leading copies, so
950  * if the separator is <literal>ABA</literal>, <literal>ABABA</literal>
951  * has 1 trailing copy.)
952  *
953  * However, if there is only a single non-empty element, and there
954  * are no characters in that element not part of the leading or
955  * trailing separators, then the result is exactly the original value
956  * of that element.
957  *
958  * Other than for determination of the number of leading and trailing
959  * copies of the separator, elements consisting only of copies
960  * of the separator are ignored.
961  * 
962  * Return value: a newly-allocated string that must be freed with g_free().
963  **/
964 gchar *
965 g_build_path (const gchar *separator,
966               const gchar *first_element,
967               ...)
968 {
969   gchar *str;
970   va_list args;
971
972   g_return_val_if_fail (separator != NULL, NULL);
973
974   va_start (args, first_element);
975   str = g_build_pathv (separator, first_element, args);
976   va_end (args);
977
978   return str;
979 }
980
981 /**
982  * g_build_filename:
983  * @first_element: the first element in the path
984  * @Varargs: remaining elements in path, terminated by %NULL
985  * 
986  * Creates a filename from a series of elements using the correct
987  * separator for filenames.
988  *
989  * On Unix, this function behaves identically to <literal>g_build_path
990  * (G_DIR_SEPARATOR_S, first_element, ....)</literal>.
991  *
992  * On Windows, it takes into account that either the backslash
993  * (<literal>\</literal> or slash (<literal>/</literal>) can be used
994  * as separator in filenames, but otherwise behaves as on Unix. When
995  * file pathname separators need to be inserted, the one that last
996  * previously occurred in the parameters (reading from left to right)
997  * is used.
998  *
999  * No attempt is made to force the resulting filename to be an absolute
1000  * path. If the first element is a relative path, the result will
1001  * be a relative path. 
1002  * 
1003  * Return value: a newly-allocated string that must be freed with g_free().
1004  **/
1005 gchar *
1006 g_build_filename (const gchar *first_element, 
1007                   ...)
1008 {
1009 #ifndef G_OS_WIN32
1010   gchar *str;
1011   va_list args;
1012
1013   va_start (args, first_element);
1014   str = g_build_pathv (G_DIR_SEPARATOR_S, first_element, args);
1015   va_end (args);
1016
1017   return str;
1018 #else
1019   /* Code copied from g_build_pathv(), and modifed to use two
1020    * alternative single-character separators.
1021    */
1022   va_list args;
1023   GString *result;
1024   gboolean is_first = TRUE;
1025   gboolean have_leading = FALSE;
1026   const gchar *single_element = NULL;
1027   const gchar *next_element;
1028   const gchar *last_trailing = NULL;
1029   gchar current_separator = '\\';
1030
1031   va_start (args, first_element);
1032
1033   result = g_string_new (NULL);
1034
1035   next_element = first_element;
1036
1037   while (TRUE)
1038     {
1039       const gchar *element;
1040       const gchar *start;
1041       const gchar *end;
1042
1043       if (next_element)
1044         {
1045           element = next_element;
1046           next_element = va_arg (args, gchar *);
1047         }
1048       else
1049         break;
1050
1051       /* Ignore empty elements */
1052       if (!*element)
1053         continue;
1054       
1055       start = element;
1056
1057       if (TRUE)
1058         {
1059           while (start &&
1060                  (*start == '\\' || *start == '/'))
1061             {
1062               current_separator = *start;
1063               start++;
1064             }
1065         }
1066
1067       end = start + strlen (start);
1068       
1069       if (TRUE)
1070         {
1071           while (end >= start + 1 &&
1072                  (end[-1] == '\\' || end[-1] == '/'))
1073             {
1074               current_separator = end[-1];
1075               end--;
1076             }
1077           
1078           last_trailing = end;
1079           while (last_trailing >= element + 1 &&
1080                  (last_trailing[-1] == '\\' || last_trailing[-1] == '/'))
1081             last_trailing--;
1082
1083           if (!have_leading)
1084             {
1085               /* If the leading and trailing separator strings are in the
1086                * same element and overlap, the result is exactly that element
1087                */
1088               if (last_trailing <= start)
1089                 single_element = element;
1090                   
1091               g_string_append_len (result, element, start - element);
1092               have_leading = TRUE;
1093             }
1094           else
1095             single_element = NULL;
1096         }
1097
1098       if (end == start)
1099         continue;
1100
1101       if (!is_first)
1102         g_string_append_len (result, &current_separator, 1);
1103       
1104       g_string_append_len (result, start, end - start);
1105       is_first = FALSE;
1106     }
1107
1108   va_end (args);
1109
1110   if (single_element)
1111     {
1112       g_string_free (result, TRUE);
1113       return g_strdup (single_element);
1114     }
1115   else
1116     {
1117       if (last_trailing)
1118         g_string_append (result, last_trailing);
1119   
1120       return g_string_free (result, FALSE);
1121     }
1122 #endif
1123 }
1124
1125 /**
1126  * g_file_read_link:
1127  * @filename: the symbolic link
1128  * @error: return location for a #GError
1129  *
1130  * Reads the contents of the symbolic link @filename like the POSIX readlink() function.
1131  * The returned string is in the encoding used for filenames. Use g_filename_to_utf8() to 
1132  * convert it to UTF-8.
1133  *
1134  * Returns: A newly allocated string with the contents of the symbolic link, 
1135  *          or %NULL if an error occurred.
1136  *
1137  * Since: 2.4
1138  */
1139 gchar *
1140 g_file_read_link (const gchar *filename,
1141                   GError     **error)
1142 {
1143 #ifdef HAVE_READLINK
1144   gchar *buffer;
1145   guint size;
1146   gint read_size;    
1147   
1148   size = 256; 
1149   buffer = g_malloc (size);
1150   
1151   while (TRUE) 
1152     {
1153       read_size = readlink (filename, buffer, size);
1154       if (read_size < 0) {
1155         g_free (buffer);
1156         g_set_error (error,
1157                      G_FILE_ERROR,
1158                      g_file_error_from_errno (errno),
1159                      _("Failed to read the symbolic link '%s': %s"),
1160                      filename, g_strerror (errno));
1161         
1162         return NULL;
1163       }
1164     
1165       if (read_size < size) 
1166         {
1167           buffer[read_size] = 0;
1168           return buffer;
1169         }
1170       
1171       size *= 2;
1172       buffer = g_realloc (buffer, size);
1173     }
1174 #else
1175   g_set_error (error,
1176                G_FILE_ERROR,
1177                G_FILE_ERROR_INVAL,
1178                _("Symbolic links not supported"));
1179         
1180   return NULL;
1181 #endif
1182 }