2008-10-10 Miguel de Icaza <miguel@novell.com>
[mono.git] / eglib / src / gfile-posix.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 <config.h>
29 #include <glib.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <errno.h>
33 #include <fcntl.h>
34 #include <sys/stat.h>
35 #include <sys/types.h>
36
37 #ifndef O_LARGEFILE
38 #define OPEN_FLAGS (O_RDONLY)
39 #else
40 #define OPEN_FLAGS (O_RDONLY | O_LARGEFILE)
41 #endif
42 gboolean
43 g_file_get_contents (const gchar *filename, gchar **contents, gsize *length, GError **error)
44 {
45         gchar *str;
46         int fd;
47         struct stat st;
48         long offset;
49         int nread;
50
51         g_return_val_if_fail (filename != NULL, FALSE);
52         g_return_val_if_fail (contents != NULL, FALSE);
53         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
54
55         *contents = NULL;
56         if (length)
57                 *length = 0;
58
59         fd = open (filename, OPEN_FLAGS);
60         if (fd == -1) {
61                 if (error != NULL) {
62                         int err = errno;
63                         *error = g_error_new (G_LOG_DOMAIN, g_file_error_from_errno (err), "Error opening file");
64                 }
65                 return FALSE;
66         }
67
68         if (fstat (fd, &st) != 0) {
69                 if (error != NULL) {
70                         int err = errno;
71                         *error = g_error_new (G_LOG_DOMAIN, g_file_error_from_errno (err), "Error in fstat()");
72                 }
73                 close (fd);
74                 return FALSE;
75         }
76
77         str = g_malloc (st.st_size + 1);
78         offset = 0;
79         do {
80                 nread = read (fd, str + offset, st.st_size - offset);
81                 if (nread > 0) {
82                         offset += nread;
83                 }
84         } while ((nread > 0 && offset < st.st_size) || (nread == -1 && errno == EINTR));
85
86         close (fd);
87         str [st.st_size] = '\0';
88         if (length) {
89                 *length = st.st_size;
90         }
91         *contents = str;
92         return TRUE;
93 }
94
95 gint
96 g_file_open_tmp (const gchar *tmpl, gchar **name_used, GError **error)
97 {
98         const static gchar *default_tmpl = ".XXXXXX";
99         gchar *t;
100         gint fd;
101         size_t len;
102
103         g_return_val_if_fail (error == NULL || *error == NULL, -1);
104
105         if (tmpl == NULL)
106                 tmpl = default_tmpl;
107
108         if (strchr (tmpl, G_DIR_SEPARATOR) != NULL) {
109                 if (error) {
110                         *error = g_error_new (G_LOG_DOMAIN, 24, "Template should not have any " G_DIR_SEPARATOR_S);
111                 }
112                 return -1;
113         }
114
115         len = strlen (tmpl);
116         if (len < 6 || strcmp (tmpl + len - 6, "XXXXXX")) {
117                 if (error) {
118                         *error = g_error_new (G_LOG_DOMAIN, 24, "Template should end with XXXXXX");
119                 }
120                 return -1;
121         }
122
123         t = g_build_filename (g_get_tmp_dir (), tmpl, NULL);
124
125         fd = mkstemp (t);
126
127         if (fd == -1) {
128                 if (error) {
129                         int err = errno;
130                         *error = g_error_new (G_LOG_DOMAIN, g_file_error_from_errno (err), "Error in mkstemp()");
131                 }
132                 g_free (t);
133                 return -1;
134         }
135
136         if (name_used) {
137                 *name_used = t;
138         } else {
139                 g_free (t);
140         }
141         return fd;
142 }