make g_file_test(,G_FILE_TEST_IS_EXECUTABLE) return something useful on
[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     default:
353       return G_FILE_ERROR_FAILED;
354       break;
355     }
356 }
357
358 static gboolean
359 get_contents_stdio (const gchar *filename,
360                     FILE        *f,
361                     gchar      **contents,
362                     gsize       *length, 
363                     GError     **error)
364 {
365   gchar buf[2048];
366   size_t bytes;
367   char *str;
368   size_t total_bytes;
369   size_t total_allocated;
370   
371   g_assert (f != NULL);
372
373 #define STARTING_ALLOC 64
374   
375   total_bytes = 0;
376   total_allocated = STARTING_ALLOC;
377   str = g_malloc (STARTING_ALLOC);
378   
379   while (!feof (f))
380     {
381       bytes = fread (buf, 1, 2048, f);
382
383       while ((total_bytes + bytes + 1) > total_allocated)
384         {
385           total_allocated *= 2;
386           str = g_try_realloc (str, total_allocated);
387
388           if (str == NULL)
389             {
390               g_set_error (error,
391                            G_FILE_ERROR,
392                            G_FILE_ERROR_NOMEM,
393                            _("Could not allocate %lu bytes to read file \"%s\""),
394                            (gulong) total_allocated, filename);
395               goto error;
396             }
397         }
398       
399       if (ferror (f))
400         {
401           g_set_error (error,
402                        G_FILE_ERROR,
403                        g_file_error_from_errno (errno),
404                        _("Error reading file '%s': %s"),
405                        filename, g_strerror (errno));
406
407           goto error;
408         }
409
410       memcpy (str + total_bytes, buf, bytes);
411       total_bytes += bytes;
412     }
413
414   fclose (f);
415
416   str[total_bytes] = '\0';
417   
418   if (length)
419     *length = total_bytes;
420   
421   *contents = str;
422   
423   return TRUE;
424
425  error:
426
427   g_free (str);
428   fclose (f);
429   
430   return FALSE;  
431 }
432
433 #ifndef G_OS_WIN32
434
435 static gboolean
436 get_contents_regfile (const gchar *filename,
437                       struct stat *stat_buf,
438                       gint         fd,
439                       gchar      **contents,
440                       gsize       *length,
441                       GError     **error)
442 {
443   gchar *buf;
444   size_t bytes_read;
445   size_t size;
446   size_t alloc_size;
447   
448   size = stat_buf->st_size;
449
450   alloc_size = size + 1;
451   buf = g_try_malloc (alloc_size);
452
453   if (buf == NULL)
454     {
455       g_set_error (error,
456                    G_FILE_ERROR,
457                    G_FILE_ERROR_NOMEM,
458                    _("Could not allocate %lu bytes to read file \"%s\""),
459                    (gulong) alloc_size, filename);
460
461       goto error;
462     }
463   
464   bytes_read = 0;
465   while (bytes_read < size)
466     {
467       gssize rc;
468           
469       rc = read (fd, buf + bytes_read, size - bytes_read);
470
471       if (rc < 0)
472         {
473           if (errno != EINTR) 
474             {
475               g_free (buf);
476                   
477               g_set_error (error,
478                            G_FILE_ERROR,
479                            g_file_error_from_errno (errno),
480                            _("Failed to read from file '%s': %s"),
481                            filename, g_strerror (errno));
482
483               goto error;
484             }
485         }
486       else if (rc == 0)
487         break;
488       else
489         bytes_read += rc;
490     }
491       
492   buf[bytes_read] = '\0';
493
494   if (length)
495     *length = bytes_read;
496   
497   *contents = buf;
498
499   close (fd);
500
501   return TRUE;
502
503  error:
504
505   close (fd);
506   
507   return FALSE;
508 }
509
510 static gboolean
511 get_contents_posix (const gchar *filename,
512                     gchar      **contents,
513                     gsize       *length,
514                     GError     **error)
515 {
516   struct stat stat_buf;
517   gint fd;
518   
519   /* O_BINARY useful on Cygwin */
520   fd = open (filename, O_RDONLY|O_BINARY);
521
522   if (fd < 0)
523     {
524       g_set_error (error,
525                    G_FILE_ERROR,
526                    g_file_error_from_errno (errno),
527                    _("Failed to open file '%s': %s"),
528                    filename, g_strerror (errno));
529
530       return FALSE;
531     }
532
533   /* I don't think this will ever fail, aside from ENOMEM, but. */
534   if (fstat (fd, &stat_buf) < 0)
535     {
536       close (fd);
537       
538       g_set_error (error,
539                    G_FILE_ERROR,
540                    g_file_error_from_errno (errno),
541                    _("Failed to get attributes of file '%s': fstat() failed: %s"),
542                    filename, g_strerror (errno));
543
544       return FALSE;
545     }
546
547   if (stat_buf.st_size > 0 && S_ISREG (stat_buf.st_mode))
548     {
549       return get_contents_regfile (filename,
550                                    &stat_buf,
551                                    fd,
552                                    contents,
553                                    length,
554                                    error);
555     }
556   else
557     {
558       FILE *f;
559
560       f = fdopen (fd, "r");
561       
562       if (f == NULL)
563         {
564           g_set_error (error,
565                        G_FILE_ERROR,
566                        g_file_error_from_errno (errno),
567                        _("Failed to open file '%s': fdopen() failed: %s"),
568                        filename, g_strerror (errno));
569           
570           return FALSE;
571         }
572   
573       return get_contents_stdio (filename, f, contents, length, error);
574     }
575 }
576
577 #else  /* G_OS_WIN32 */
578
579 static gboolean
580 get_contents_win32 (const gchar *filename,
581                     gchar      **contents,
582                     gsize       *length,
583                     GError     **error)
584 {
585   FILE *f;
586
587   /* I guess you want binary mode; maybe you want text sometimes? */
588   f = fopen (filename, "rb");
589
590   if (f == NULL)
591     {
592       g_set_error (error,
593                    G_FILE_ERROR,
594                    g_file_error_from_errno (errno),
595                    _("Failed to open file '%s': %s"),
596                    filename, g_strerror (errno));
597       
598       return FALSE;
599     }
600   
601   return get_contents_stdio (filename, f, contents, length, error);
602 }
603
604 #endif
605
606 /**
607  * g_file_get_contents:
608  * @filename: a file to read contents from
609  * @contents: location to store an allocated string
610  * @length: location to store length in bytes of the contents
611  * @error: return location for a #GError
612  * 
613  * Reads an entire file into allocated memory, with good error
614  * checking. If @error is set, %FALSE is returned, and @contents is set
615  * to %NULL. If %TRUE is returned, @error will not be set, and @contents
616  * will be set to the file contents.  The string stored in @contents
617  * will be nul-terminated, so for text files you can pass %NULL for the
618  * @length argument.  The error domain is #G_FILE_ERROR. Possible
619  * error codes are those in the #GFileError enumeration.
620  *
621  * Return value: %TRUE on success, %FALSE if error is set
622  **/
623 gboolean
624 g_file_get_contents (const gchar *filename,
625                      gchar      **contents,
626                      gsize       *length,
627                      GError     **error)
628 {  
629   g_return_val_if_fail (filename != NULL, FALSE);
630   g_return_val_if_fail (contents != NULL, FALSE);
631
632   *contents = NULL;
633   if (length)
634     *length = 0;
635
636 #ifdef G_OS_WIN32
637   return get_contents_win32 (filename, contents, length, error);
638 #else
639   return get_contents_posix (filename, contents, length, error);
640 #endif
641 }
642
643 /*
644  * mkstemp() implementation is from the GNU C library.
645  * Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc.
646  */
647 /**
648  * g_mkstemp:
649  * @tmpl: template filename
650  *
651  * Opens a temporary file. See the mkstemp() documentation
652  * on most UNIX-like systems. This is a portability wrapper, which simply calls 
653  * mkstemp() on systems that have it, and implements 
654  * it in GLib otherwise.
655  *
656  * The parameter is a string that should match the rules for
657  * mkstemp(), i.e. end in "XXXXXX". The X string will 
658  * be modified to form the name of a file that didn't exist.
659  *
660  * Return value: A file handle (as from open()) to the file
661  * opened for reading and writing. The file is opened in binary mode
662  * on platforms where there is a difference. The file handle should be
663  * closed with close(). In case of errors, -1 is returned.
664  */
665 gint
666 g_mkstemp (gchar *tmpl)
667 {
668 #ifdef HAVE_MKSTEMP
669   return mkstemp (tmpl);
670 #else
671   int len;
672   char *XXXXXX;
673   int count, fd;
674   static const char letters[] =
675     "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
676   static const int NLETTERS = sizeof (letters) - 1;
677   glong value;
678   GTimeVal tv;
679   static int counter = 0;
680
681   len = strlen (tmpl);
682   if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX"))
683     return -1;
684
685   /* This is where the Xs start.  */
686   XXXXXX = &tmpl[len - 6];
687
688   /* Get some more or less random data.  */
689   g_get_current_time (&tv);
690   value = (tv.tv_usec ^ tv.tv_sec) + counter++;
691
692   for (count = 0; count < 100; value += 7777, ++count)
693     {
694       glong v = value;
695
696       /* Fill in the random bits.  */
697       XXXXXX[0] = letters[v % NLETTERS];
698       v /= NLETTERS;
699       XXXXXX[1] = letters[v % NLETTERS];
700       v /= NLETTERS;
701       XXXXXX[2] = letters[v % NLETTERS];
702       v /= NLETTERS;
703       XXXXXX[3] = letters[v % NLETTERS];
704       v /= NLETTERS;
705       XXXXXX[4] = letters[v % NLETTERS];
706       v /= NLETTERS;
707       XXXXXX[5] = letters[v % NLETTERS];
708
709       fd = open (tmpl, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0600);
710
711       if (fd >= 0)
712         return fd;
713       else if (errno != EEXIST)
714         /* Any other error will apply also to other names we might
715          *  try, and there are 2^32 or so of them, so give up now.
716          */
717         return -1;
718     }
719
720   /* We got out of the loop because we ran out of combinations to try.  */
721   return -1;
722 #endif
723 }
724
725 /**
726  * g_file_open_tmp:
727  * @tmpl: Template for file name, as in g_mkstemp(), basename only
728  * @name_used: location to store actual name used
729  * @error: return location for a #GError
730  *
731  * Opens a file for writing in the preferred directory for temporary
732  * files (as returned by g_get_tmp_dir()). 
733  *
734  * @tmpl should be a string ending with six 'X' characters, as the
735  * parameter to g_mkstemp() (or mkstemp()). 
736  * However, unlike these functions, the template should only be a 
737  * basename, no directory components are allowed. If template is %NULL, 
738  * a default template is used.
739  *
740  * Note that in contrast to g_mkstemp() (and mkstemp()) 
741  * @tmpl is not modified, and might thus be a read-only literal string.
742  *
743  * The actual name used is returned in @name_used if non-%NULL. This
744  * string should be freed with g_free() when not needed any longer.
745  *
746  * Return value: A file handle (as from open()) to 
747  * the file opened for reading and writing. The file is opened in binary 
748  * mode on platforms where there is a difference. The file handle should be
749  * closed with close(). In case of errors, -1 is returned 
750  * and @error will be set.
751  **/
752 gint
753 g_file_open_tmp (const gchar *tmpl,
754                  gchar      **name_used,
755                  GError     **error)
756 {
757   int retval;
758   const char *tmpdir;
759   char *sep;
760   char *fulltemplate;
761   const char *slash;
762
763   if (tmpl == NULL)
764     tmpl = ".XXXXXX";
765
766   if ((slash = strchr (tmpl, G_DIR_SEPARATOR)) != NULL
767 #ifdef G_OS_WIN32
768       || (strchr (tmpl, '/') != NULL && (slash = "/"))
769 #endif
770       )
771     {
772       char c[2];
773       c[0] = *slash;
774       c[1] = '\0';
775
776       g_set_error (error,
777                    G_FILE_ERROR,
778                    G_FILE_ERROR_FAILED,
779                    _("Template '%s' invalid, should not contain a '%s'"),
780                    tmpl, c);
781
782       return -1;
783     }
784   
785   if (strlen (tmpl) < 6 ||
786       strcmp (tmpl + strlen (tmpl) - 6, "XXXXXX") != 0)
787     {
788       g_set_error (error,
789                    G_FILE_ERROR,
790                    G_FILE_ERROR_FAILED,
791                    _("Template '%s' doesn't end with XXXXXX"),
792                    tmpl);
793       return -1;
794     }
795
796   tmpdir = g_get_tmp_dir ();
797
798   if (G_IS_DIR_SEPARATOR (tmpdir [strlen (tmpdir) - 1]))
799     sep = "";
800   else
801     sep = G_DIR_SEPARATOR_S;
802
803   fulltemplate = g_strconcat (tmpdir, sep, tmpl, NULL);
804
805   retval = g_mkstemp (fulltemplate);
806
807   if (retval == -1)
808     {
809       g_set_error (error,
810                    G_FILE_ERROR,
811                    g_file_error_from_errno (errno),
812                    _("Failed to create file '%s': %s"),
813                    fulltemplate, g_strerror (errno));
814       g_free (fulltemplate);
815       return -1;
816     }
817
818   if (name_used)
819     *name_used = fulltemplate;
820   else
821     g_free (fulltemplate);
822
823   return retval;
824 }
825
826 static gchar *
827 g_build_pathv (const gchar *separator,
828                const gchar *first_element,
829                va_list      args)
830 {
831   GString *result;
832   gint separator_len = strlen (separator);
833   gboolean is_first = TRUE;
834   gboolean have_leading = FALSE;
835   const gchar *single_element = NULL;
836   const gchar *next_element;
837   const gchar *last_trailing = NULL;
838
839   result = g_string_new (NULL);
840
841   next_element = first_element;
842
843   while (TRUE)
844     {
845       const gchar *element;
846       const gchar *start;
847       const gchar *end;
848
849       if (next_element)
850         {
851           element = next_element;
852           next_element = va_arg (args, gchar *);
853         }
854       else
855         break;
856
857       /* Ignore empty elements */
858       if (!*element)
859         continue;
860       
861       start = element;
862
863       if (separator_len)
864         {
865           while (start &&
866                  strncmp (start, separator, separator_len) == 0)
867             start += separator_len;
868         }
869
870       end = start + strlen (start);
871       
872       if (separator_len)
873         {
874           while (end >= start + separator_len &&
875                  strncmp (end - separator_len, separator, separator_len) == 0)
876             end -= separator_len;
877           
878           last_trailing = end;
879           while (last_trailing >= element + separator_len &&
880                  strncmp (last_trailing - separator_len, separator, separator_len) == 0)
881             last_trailing -= separator_len;
882
883           if (!have_leading)
884             {
885               /* If the leading and trailing separator strings are in the
886                * same element and overlap, the result is exactly that element
887                */
888               if (last_trailing <= start)
889                 single_element = element;
890                   
891               g_string_append_len (result, element, start - element);
892               have_leading = TRUE;
893             }
894           else
895             single_element = NULL;
896         }
897
898       if (end == start)
899         continue;
900
901       if (!is_first)
902         g_string_append (result, separator);
903       
904       g_string_append_len (result, start, end - start);
905       is_first = FALSE;
906     }
907
908   if (single_element)
909     {
910       g_string_free (result, TRUE);
911       return g_strdup (single_element);
912     }
913   else
914     {
915       if (last_trailing)
916         g_string_append (result, last_trailing);
917   
918       return g_string_free (result, FALSE);
919     }
920 }
921
922 /**
923  * g_build_path:
924  * @separator: a string used to separator the elements of the path.
925  * @first_element: the first element in the path
926  * @Varargs: remaining elements in path, terminated by %NULL
927  * 
928  * Creates a path from a series of elements using @separator as the
929  * separator between elements. At the boundary between two elements,
930  * any trailing occurrences of separator in the first element, or
931  * leading occurrences of separator in the second element are removed
932  * and exactly one copy of the separator is inserted.
933  *
934  * Empty elements are ignored.
935  *
936  * The number of leading copies of the separator on the result is
937  * the same as the number of leading copies of the separator on
938  * the first non-empty element.
939  *
940  * The number of trailing copies of the separator on the result is
941  * the same as the number of trailing copies of the separator on
942  * the last non-empty element. (Determination of the number of
943  * trailing copies is done without stripping leading copies, so
944  * if the separator is <literal>ABA</literal>, <literal>ABABA</literal>
945  * has 1 trailing copy.)
946  *
947  * However, if there is only a single non-empty element, and there
948  * are no characters in that element not part of the leading or
949  * trailing separators, then the result is exactly the original value
950  * of that element.
951  *
952  * Other than for determination of the number of leading and trailing
953  * copies of the separator, elements consisting only of copies
954  * of the separator are ignored.
955  * 
956  * Return value: a newly-allocated string that must be freed with g_free().
957  **/
958 gchar *
959 g_build_path (const gchar *separator,
960               const gchar *first_element,
961               ...)
962 {
963   gchar *str;
964   va_list args;
965
966   g_return_val_if_fail (separator != NULL, NULL);
967
968   va_start (args, first_element);
969   str = g_build_pathv (separator, first_element, args);
970   va_end (args);
971
972   return str;
973 }
974
975 /**
976  * g_build_filename:
977  * @first_element: the first element in the path
978  * @Varargs: remaining elements in path, terminated by %NULL
979  * 
980  * Creates a filename from a series of elements using the correct
981  * separator for filenames.
982  *
983  * On Unix, this function behaves identically to <literal>g_build_path
984  * (G_DIR_SEPARATOR_S, first_element, ....)</literal>.
985  *
986  * On Windows, it takes into account that either the backslash
987  * (<literal>\</literal> or slash (<literal>/</literal>) can be used
988  * as separator in filenames, but otherwise behaves as on Unix. When
989  * file pathname separators need to be inserted, the one that last
990  * previously occurred in the parameters (reading from left to right)
991  * is used.
992  *
993  * No attempt is made to force the resulting filename to be an absolute
994  * path. If the first element is a relative path, the result will
995  * be a relative path. 
996  * 
997  * Return value: a newly-allocated string that must be freed with g_free().
998  **/
999 gchar *
1000 g_build_filename (const gchar *first_element, 
1001                   ...)
1002 {
1003 #ifndef G_OS_WIN32
1004   gchar *str;
1005   va_list args;
1006
1007   va_start (args, first_element);
1008   str = g_build_pathv (G_DIR_SEPARATOR_S, first_element, args);
1009   va_end (args);
1010
1011   return str;
1012 #else
1013   /* Code copied from g_build_pathv(), and modifed to use two
1014    * alternative single-character separators.
1015    */
1016   va_list args;
1017   GString *result;
1018   gboolean is_first = TRUE;
1019   gboolean have_leading = FALSE;
1020   const gchar *single_element = NULL;
1021   const gchar *next_element;
1022   const gchar *last_trailing = NULL;
1023   gchar current_separator = '\\';
1024
1025   va_start (args, first_element);
1026
1027   result = g_string_new (NULL);
1028
1029   next_element = first_element;
1030
1031   while (TRUE)
1032     {
1033       const gchar *element;
1034       const gchar *start;
1035       const gchar *end;
1036
1037       if (next_element)
1038         {
1039           element = next_element;
1040           next_element = va_arg (args, gchar *);
1041         }
1042       else
1043         break;
1044
1045       /* Ignore empty elements */
1046       if (!*element)
1047         continue;
1048       
1049       start = element;
1050
1051       if (TRUE)
1052         {
1053           while (start &&
1054                  (*start == '\\' || *start == '/'))
1055             {
1056               current_separator = *start;
1057               start++;
1058             }
1059         }
1060
1061       end = start + strlen (start);
1062       
1063       if (TRUE)
1064         {
1065           while (end >= start + 1 &&
1066                  (end[-1] == '\\' || end[-1] == '/'))
1067             {
1068               current_separator = end[-1];
1069               end--;
1070             }
1071           
1072           last_trailing = end;
1073           while (last_trailing >= element + 1 &&
1074                  (last_trailing[-1] == '\\' || last_trailing[-1] == '/'))
1075             last_trailing--;
1076
1077           if (!have_leading)
1078             {
1079               /* If the leading and trailing separator strings are in the
1080                * same element and overlap, the result is exactly that element
1081                */
1082               if (last_trailing <= start)
1083                 single_element = element;
1084                   
1085               g_string_append_len (result, element, start - element);
1086               have_leading = TRUE;
1087             }
1088           else
1089             single_element = NULL;
1090         }
1091
1092       if (end == start)
1093         continue;
1094
1095       if (!is_first)
1096         g_string_append_len (result, &current_separator, 1);
1097       
1098       g_string_append_len (result, start, end - start);
1099       is_first = FALSE;
1100     }
1101
1102   va_end (args);
1103
1104   if (single_element)
1105     {
1106       g_string_free (result, TRUE);
1107       return g_strdup (single_element);
1108     }
1109   else
1110     {
1111       if (last_trailing)
1112         g_string_append (result, last_trailing);
1113   
1114       return g_string_free (result, FALSE);
1115     }
1116 #endif
1117 }
1118
1119 /**
1120  * g_file_read_link:
1121  * @filename: the symbolic link
1122  * @error: return location for a #GError
1123  *
1124  * Reads the contents of the symbolic link @filename like the POSIX readlink() function.
1125  * The returned string is in the encoding used for filenames. Use g_filename_to_utf8() to 
1126  * convert it to UTF-8.
1127  *
1128  * Returns: A newly allocated string with the contents of the symbolic link, 
1129  *          or %NULL if an error occurred.
1130  *
1131  * Since: 2.4
1132  */
1133 gchar *
1134 g_file_read_link (const gchar *filename,
1135                   GError     **error)
1136 {
1137 #ifdef HAVE_READLINK
1138   gchar *buffer;
1139   guint size;
1140   gint read_size;    
1141   
1142   size = 256; 
1143   buffer = g_malloc (size);
1144   
1145   while (TRUE) 
1146     {
1147       read_size = readlink (filename, buffer, size);
1148       if (read_size < 0) {
1149         g_free (buffer);
1150         g_set_error (error,
1151                      G_FILE_ERROR,
1152                      g_file_error_from_errno (errno),
1153                      _("Failed to read the symbolic link '%s': %s"),
1154                      filename, g_strerror (errno));
1155         
1156         return NULL;
1157       }
1158     
1159       if (read_size < size) 
1160         {
1161           buffer[read_size] = 0;
1162           return buffer;
1163         }
1164       
1165       size *= 2;
1166       buffer = g_realloc (buffer, size);
1167     }
1168 #else
1169   g_set_error (error,
1170                G_FILE_ERROR,
1171                G_FILE_ERROR_INVAL,
1172                _("Symbolic links not supported"));
1173         
1174   return NULL;
1175 #endif
1176 }