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