Add new files.
[platform/upstream/glib.git] / 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 "glib.h"
22
23 #include <sys/stat.h>
24 #include <unistd.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <fcntl.h>
31
32
33 #define _(x) x
34
35 /**
36  * g_file_test:
37  * @filename: a filename to test
38  * @test: bitfield of #GFileTest flags
39  * 
40  * Returns TRUE if any of the tests in the bitfield @test are
41  * TRUE. For example, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)
42  * will return TRUE if the file exists; the check whether it's
43  * a directory doesn't matter since the existence test is TRUE.
44  * With the current set of available tests, there's no point
45  * passing in more than one test at a time.
46  *
47  * Return value: whether a test was TRUE
48  **/
49 gboolean
50 g_file_test (const gchar *filename,
51              GFileTest    test)
52 {
53   if (test & G_FILE_TEST_EXISTS)
54     return (access (filename, F_OK) == 0);
55   else if (test & G_FILE_TEST_IS_EXECUTABLE)
56     return (access (filename, X_OK) == 0);
57   else
58     {
59       struct stat s;
60       
61       if (stat (filename, &s) < 0)
62         return FALSE;
63
64       if ((test & G_FILE_TEST_IS_REGULAR) &&
65           S_ISREG (s.st_mode))
66         return TRUE;
67       else if ((test & G_FILE_TEST_IS_DIR) &&
68                S_ISDIR (s.st_mode))
69         return TRUE;
70       else if ((test & G_FILE_TEST_IS_SYMLINK) &&
71                S_ISLNK (s.st_mode))
72         return TRUE;
73       else
74         return FALSE;
75     }
76 }
77
78 GQuark
79 g_file_error_quark (void)
80 {
81   static GQuark q = 0;
82   if (q == 0)
83     q = g_quark_from_static_string ("g-file-error-quark");
84
85   return q;
86 }
87
88 GFileError
89 g_file_error_from_errno (gint en)
90 {
91   switch (en)
92     {
93 #ifdef EEXIST
94     case EEXIST:
95       return G_FILE_ERROR_EXIST;
96       break;
97 #endif
98
99 #ifdef EISDIR
100     case EISDIR:
101       return G_FILE_ERROR_ISDIR;
102       break;
103 #endif
104
105 #ifdef EACCES
106     case EACCES:
107       return G_FILE_ERROR_ACCES;
108       break;
109 #endif
110
111 #ifdef ENAMETOOLONG
112     case ENAMETOOLONG:
113       return G_FILE_ERROR_NAMETOOLONG;
114       break;
115 #endif
116
117 #ifdef ENOENT
118     case ENOENT:
119       return G_FILE_ERROR_NOENT;
120       break;
121 #endif
122
123 #ifdef ENOTDIR
124     case ENOTDIR:
125       return G_FILE_ERROR_NOTDIR;
126       break;
127 #endif
128
129 #ifdef ENXIO
130     case ENXIO:
131       return G_FILE_ERROR_NXIO;
132       break;
133 #endif
134
135 #ifdef ENODEV
136     case ENODEV:
137       return G_FILE_ERROR_NODEV;
138       break;
139 #endif
140
141 #ifdef EROFS
142     case EROFS:
143       return G_FILE_ERROR_ROFS;
144       break;
145 #endif
146
147 #ifdef ETXTBSY
148     case ETXTBSY:
149       return G_FILE_ERROR_TXTBSY;
150       break;
151 #endif
152
153 #ifdef EFAULT
154     case EFAULT:
155       return G_FILE_ERROR_FAULT;
156       break;
157 #endif
158
159 #ifdef ELOOP
160     case ELOOP:
161       return G_FILE_ERROR_LOOP;
162       break;
163 #endif
164
165 #ifdef ENOSPC
166     case ENOSPC:
167       return G_FILE_ERROR_NOSPC;
168       break;
169 #endif
170
171 #ifdef ENOMEM
172     case ENOMEM:
173       return G_FILE_ERROR_NOMEM;
174       break;
175 #endif
176
177 #ifdef EMFILE
178     case EMFILE:
179       return G_FILE_ERROR_MFILE;
180       break;
181 #endif
182
183 #ifdef ENFILE
184     case ENFILE:
185       return G_FILE_ERROR_NFILE;
186       break;
187 #endif
188
189 #ifdef EBADF
190     case EBADF:
191       return G_FILE_ERROR_BADF;
192       break;
193 #endif
194
195 #ifdef EINVAL
196     case EINVAL:
197       return G_FILE_ERROR_INVAL;
198       break;
199 #endif
200
201 #ifdef EPIPE
202     case EPIPE:
203       return G_FILE_ERROR_PIPE;
204       break;
205 #endif
206
207 #ifdef EAGAIN
208     case EAGAIN:
209       return G_FILE_ERROR_AGAIN;
210       break;
211 #endif
212
213 #ifdef EINTR
214     case EINTR:
215       return G_FILE_ERROR_INTR;
216       break;
217 #endif
218
219 #ifdef EIO
220     case EIO:
221       return G_FILE_ERROR_IO;
222       break;
223 #endif
224
225 #ifdef EPERM
226     case EPERM:
227       return G_FILE_ERROR_PERM;
228       break;
229 #endif
230       
231     default:
232       return G_FILE_ERROR_FAILED;
233       break;
234     }
235 }
236
237 static gboolean
238 get_contents_stdio (const gchar *filename,
239                     FILE        *f,
240                     gchar      **contents,
241                     guint       *length,
242                     GError     **error)
243 {
244   gchar buf[2048];
245   size_t bytes;
246   GString *str;
247
248   g_assert (f != NULL);
249   
250   str = g_string_new ("");
251   
252   while (!feof (f))
253     {
254       bytes = fread (buf, 1, 2048, f);
255       
256       if (ferror (f))
257         {
258           g_set_error (error,
259                        G_FILE_ERROR,
260                        g_file_error_from_errno (errno),
261                        _("Error reading file '%s': %s"),
262                        filename, strerror (errno));
263
264           g_string_free (str, TRUE);
265           
266           return FALSE;
267         }
268
269       g_string_append_len (str, buf, bytes);
270     }
271
272   fclose (f);
273
274   if (length)
275     *length = str->len;
276   
277   *contents = g_string_free (str, FALSE);
278
279   return TRUE;  
280 }
281
282 static gboolean
283 get_contents_regfile (const gchar *filename,
284                       struct stat *stat_buf,
285                       gint         fd,
286                       gchar      **contents,
287                       guint       *length,
288                       GError     **error)
289 {
290   gchar *buf;
291   size_t bytes_read;
292   size_t size;
293       
294   size = stat_buf->st_size;
295
296   buf = g_new (gchar, size + 1);
297       
298   bytes_read = 0;
299   while (bytes_read < size)
300     {
301       gint rc;
302           
303       rc = read (fd, buf + bytes_read, size - bytes_read);
304
305       if (rc < 0)
306         {
307           if (errno != EINTR) 
308             {
309               close (fd);
310
311               g_free (buf);
312                   
313               g_set_error (error,
314                            G_FILE_ERROR,
315                            g_file_error_from_errno (errno),
316                            _("Failed to read from file '%s': %s"),
317                            filename, strerror (errno));
318
319               return FALSE;
320             }
321         }
322       else if (rc == 0)
323         break;
324       else
325         bytes_read += rc;
326     }
327       
328   buf[bytes_read] = '\0';
329
330   if (length)
331     *length = bytes_read;
332   
333   *contents = buf;
334
335   return TRUE;
336 }
337
338 static gboolean
339 get_contents_posix (const gchar *filename,
340                     gchar      **contents,
341                     guint       *length,
342                     GError     **error)
343 {
344   struct stat stat_buf;
345   gint fd;
346   
347   fd = open (filename, O_RDONLY);
348
349   if (fd < 0)
350     {
351       g_set_error (error,
352                    G_FILE_ERROR,
353                    g_file_error_from_errno (errno),
354                    _("Failed to open file '%s': %s"),
355                    filename, strerror (errno));
356
357       return FALSE;
358     }
359
360   /* I don't think this will ever fail, aside from ENOMEM, but. */
361   if (fstat (fd, &stat_buf) < 0)
362     {
363       close (fd);
364       
365       g_set_error (error,
366                    G_FILE_ERROR,
367                    g_file_error_from_errno (errno),
368                    _("Failed to get attributes of file '%s': fstat() failed: %s"),
369                    filename, strerror (errno));
370
371       return FALSE;
372     }
373
374   if (stat_buf.st_size > 0 && S_ISREG (stat_buf.st_mode))
375     {
376       return get_contents_regfile (filename,
377                                    &stat_buf,
378                                    fd,
379                                    contents,
380                                    length,
381                                    error);
382     }
383   else
384     {
385       FILE *f;
386
387       f = fdopen (fd, "r");
388       
389       if (f == NULL)
390         {
391           g_set_error (error,
392                        G_FILE_ERROR,
393                        g_file_error_from_errno (errno),
394                        _("Failed to open file '%s': fdopen() failed: %s"),
395                        filename, strerror (errno));
396           
397           return FALSE;
398         }
399   
400       return get_contents_stdio (filename, f, contents, length, error);
401     }
402 }
403
404 #ifdef G_OS_WIN32
405 static gboolean
406 get_contents_win32 (const gchar *filename,
407                     gchar      **contents,
408                     guint       *length,
409                     GError     **error)
410 {
411   FILE *f;
412
413   /* I guess you want binary mode; maybe you want text sometimes? */
414   f = fopen (filename, "rb");
415
416   if (f == NULL)
417     {
418       g_set_error (error,
419                    G_FILE_ERROR,
420                    g_file_error_from_errno (errno),
421                    _("Failed to open file '%s': %s"),
422                    filename, strerror (errno));
423       
424       return FALSE;
425     }
426   
427   return get_contents_stdio (filename, f, contents, length, error);
428 }
429 #endif
430
431 /**
432  * g_file_get_contents:
433  * @filename: a file to read contents from
434  * @contents: location to store an allocated string
435  * @length: location to store length in bytes of the contents
436  * @error: return location for a #GError
437  * 
438  * Reads an entire file into allocated memory, with good error
439  * checking. If @error is set, FALSE is returned, and @contents is set
440  * to NULL. If TRUE is returned, @error will not be set, and @contents
441  * will be set to the file contents.  The string stored in @contents
442  * will be nul-terminated, so for text files you can pass NULL for the
443  * @length argument.  The error domain is #G_FILE_ERROR. Possible
444  * error codes are those in the #GFileError enumeration.
445  *
446  * FIXME currently crashes if the file is too big to fit in memory;
447  * should probably use g_try_malloc() when we have that function.
448  * 
449  * Return value: TRUE on success, FALSE if error is set
450  **/
451 gboolean
452 g_file_get_contents (const gchar *filename,
453                      gchar      **contents,
454                      guint       *length,
455                      GError     **error)
456 {  
457   g_return_val_if_fail (filename != NULL, FALSE);
458   g_return_val_if_fail (contents != NULL, FALSE);
459
460   *contents = NULL;
461   if (length)
462     *length = 0;
463
464 #ifdef G_OS_WIN32
465   return get_contents_win32 (filename, contents, length, error);
466 #else
467   return get_contents_posix (filename, contents, length, error);
468 #endif
469 }
470