New test.
[mono.git] / eglib / src / gfile.c
1 /*
2  * File utility functions.
3  *
4  * Author:
5  *   Gonzalo Paniagua Javier (gonzalo@novell.com)
6  *
7  * (C) 2006 Novell, Inc.
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining
10  * a copy of this software and associated documentation files (the
11  * "Software"), to deal in the Software without restriction, including
12  * without limitation the rights to use, copy, modify, merge, publish,
13  * distribute, sublicense, and/or sell copies of the Software, and to
14  * permit persons to whom the Software is furnished to do so, subject to
15  * the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be
18  * included in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27  */
28 #include <glib.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <errno.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36
37 GFileError
38 g_file_error_from_errno (gint err_no)
39 {
40         switch (err_no) {
41         case EEXIST:
42                 return G_FILE_ERROR_EXIST;
43         case EISDIR:
44                 return G_FILE_ERROR_ISDIR;
45         case EACCES:
46                 return G_FILE_ERROR_ACCES;
47         case ENAMETOOLONG:
48                 return G_FILE_ERROR_NAMETOOLONG;
49         case ENOENT:
50                 return G_FILE_ERROR_NOENT;
51         case ENOTDIR:
52                 return G_FILE_ERROR_NOTDIR;
53         case ENXIO:
54                 return G_FILE_ERROR_NXIO;
55         case ENODEV:
56                 return G_FILE_ERROR_NODEV;
57         case EROFS:
58                 return G_FILE_ERROR_ROFS;
59 #ifdef ETXTBSY
60         case ETXTBSY:
61                 return G_FILE_ERROR_TXTBSY;
62 #endif
63         case EFAULT:
64                 return G_FILE_ERROR_FAULT;
65 #ifdef ELOOP
66         case ELOOP:
67                 return G_FILE_ERROR_LOOP;
68 #endif
69         case ENOSPC:
70                 return G_FILE_ERROR_NOSPC;
71         case ENOMEM:
72                 return G_FILE_ERROR_NOMEM;
73         case EMFILE:
74                 return G_FILE_ERROR_MFILE;
75         case ENFILE:
76                 return G_FILE_ERROR_NFILE;
77         case EBADF:
78                 return G_FILE_ERROR_BADF;
79         case EINVAL:
80                 return G_FILE_ERROR_INVAL;
81         case EPIPE:
82                 return G_FILE_ERROR_PIPE;
83         case EAGAIN:
84                 return G_FILE_ERROR_AGAIN;
85         case EINTR:
86                 return G_FILE_ERROR_INTR;
87         case EIO:
88                 return G_FILE_ERROR_IO;
89         case EPERM:
90                 return G_FILE_ERROR_PERM;
91         case ENOSYS:
92                 return G_FILE_ERROR_NOSYS;
93         default:
94                 return G_FILE_ERROR_FAILED;
95         }
96 }
97
98 #ifndef O_LARGEFILE
99 #define OPEN_FLAGS (O_RDONLY)
100 #else
101 #define OPEN_FLAGS (O_RDONLY | O_LARGEFILE)
102 #endif
103 gboolean
104 g_file_get_contents (const gchar *filename, gchar **contents, gsize *length, GError **error)
105 {
106         gchar *str;
107         int fd;
108         struct stat st;
109         long offset;
110         int nread;
111
112         g_return_val_if_fail (filename != NULL, FALSE);
113         g_return_val_if_fail (contents != NULL, FALSE);
114         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
115
116         *contents = NULL;
117         if (length)
118                 *length = 0;
119
120         fd = open (filename, OPEN_FLAGS);
121         if (fd == -1) {
122                 if (error != NULL) {
123                         int err = errno;
124                         *error = g_error_new (G_LOG_DOMAIN, g_file_error_from_errno (err), "Error opening file");
125                 }
126                 return FALSE;
127         }
128
129         if (fstat (fd, &st) != 0) {
130                 if (error != NULL) {
131                         int err = errno;
132                         *error = g_error_new (G_LOG_DOMAIN, g_file_error_from_errno (err), "Error in fstat()");
133                 }
134                 close (fd);
135                 return FALSE;
136         }
137
138         str = g_malloc (st.st_size + 1);
139         offset = 0;
140         do {
141                 nread = read (fd, str + offset, st.st_size - offset);
142                 if (nread > 0) {
143                         offset += nread;
144                 }
145         } while ((nread > 0 && offset < st.st_size) || (nread == -1 && errno == EINTR));
146
147         close (fd);
148         str [st.st_size] = '\0';
149         if (length) {
150                 *length = st.st_size;
151         }
152         *contents = str;
153         return TRUE;
154 }
155
156 gint
157 g_file_open_tmp (const gchar *tmpl, gchar **name_used, GError **error)
158 {
159         const static gchar *default_tmpl = ".XXXXXX";
160         gchar *t;
161         gint fd;
162         gint len;
163
164         g_return_val_if_fail (error == NULL || *error == NULL, -1);
165
166         if (tmpl == NULL)
167                 tmpl = default_tmpl;
168
169         if (strchr (tmpl, G_DIR_SEPARATOR) != NULL) {
170                 if (error) {
171                         *error = g_error_new (G_LOG_DOMAIN, 24, "Template should not have any " G_DIR_SEPARATOR_S);
172                 }
173                 return -1;
174         }
175
176         len = strlen (tmpl);
177         if (len < 6 || strcmp (tmpl + len - 6, "XXXXXX")) {
178                 if (error) {
179                         *error = g_error_new (G_LOG_DOMAIN, 24, "Template should end with XXXXXX");
180                 }
181                 return -1;
182         }
183
184         t = g_build_filename (g_get_tmp_dir (), tmpl, NULL);
185         fd = mkstemp (t);
186         if (fd == -1) {
187                 if (error) {
188                         int err = errno;
189                         *error = g_error_new (G_LOG_DOMAIN, g_file_error_from_errno (err), "Error in mkstemp()");
190                 }
191                 g_free (t);
192                 return -1;
193         }
194
195         if (name_used) {
196                 *name_used = t;
197         } else {
198                 g_free (t);
199         }
200         return fd;
201 }
202
203 gboolean
204 g_file_test (const gchar *filename, GFileTest test)
205 {
206         struct stat st;
207         gboolean have_stat;
208
209         if (filename == NULL || test == 0)
210                 return FALSE;
211
212         have_stat = FALSE;
213 #ifdef G_OS_WIN32
214 #else
215         if ((test & G_FILE_TEST_EXISTS) != 0) {
216                 if (access (filename, F_OK) == 0)
217                         return TRUE;
218         }
219
220         if ((test & G_FILE_TEST_IS_EXECUTABLE) != 0) {
221                 if (access (filename, X_OK) == 0)
222                         return TRUE;
223         }
224         if ((test & G_FILE_TEST_IS_SYMLINK) != 0) {
225                 have_stat = (lstat (filename, &st) == 0);
226                 if (have_stat && S_ISLNK (st.st_mode))
227                         return TRUE;
228         }
229 #endif
230
231         if ((test & G_FILE_TEST_IS_REGULAR) != 0) {
232                 if (!have_stat)
233                         have_stat = (stat (filename, &st) == 0);
234                 if (have_stat && S_ISREG (st.st_mode))
235                         return TRUE;
236         }
237         if ((test & G_FILE_TEST_IS_DIR) != 0) {
238                 if (!have_stat)
239                         have_stat = (stat (filename, &st) == 0);
240                 if (have_stat && S_ISDIR (st.st_mode))
241                         return TRUE;
242         }
243         return FALSE;
244 }
245