[xbuild] Exec task - add support for custom error/warning regex.
[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 #ifdef HAVE_UNISTD_H
37 #include <unistd.h>
38 #endif
39
40 #ifdef _MSC_VER
41 #include <direct.h>
42 int mkstemp (char *tmp_template);
43 #endif
44
45 #ifndef O_LARGEFILE
46 #define OPEN_FLAGS (O_RDONLY)
47 #else
48 #define OPEN_FLAGS (O_RDONLY | O_LARGEFILE)
49 #endif
50 gboolean
51 g_file_get_contents (const gchar *filename, gchar **contents, gsize *length, GError **error)
52 {
53         gchar *str;
54         int fd;
55         struct stat st;
56         long offset;
57         int nread;
58
59         g_return_val_if_fail (filename != NULL, FALSE);
60         g_return_val_if_fail (contents != NULL, FALSE);
61         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
62
63         *contents = NULL;
64         if (length)
65                 *length = 0;
66
67         fd = open (filename, OPEN_FLAGS);
68         if (fd == -1) {
69                 if (error != NULL) {
70                         int err = errno;
71                         *error = g_error_new (G_LOG_DOMAIN, g_file_error_from_errno (err), "Error opening file");
72                 }
73                 return FALSE;
74         }
75
76         if (fstat (fd, &st) != 0) {
77                 if (error != NULL) {
78                         int err = errno;
79                         *error = g_error_new (G_LOG_DOMAIN, g_file_error_from_errno (err), "Error in fstat()");
80                 }
81                 close (fd);
82                 return FALSE;
83         }
84
85         str = g_malloc (st.st_size + 1);
86         offset = 0;
87         do {
88                 nread = read (fd, str + offset, st.st_size - offset);
89                 if (nread > 0) {
90                         offset += nread;
91                 }
92         } while ((nread > 0 && offset < st.st_size) || (nread == -1 && errno == EINTR));
93
94         close (fd);
95         str [st.st_size] = '\0';
96         if (length) {
97                 *length = st.st_size;
98         }
99         *contents = str;
100         return TRUE;
101 }
102
103 gint
104 g_file_open_tmp (const gchar *tmpl, gchar **name_used, GError **error)
105 {
106         const static gchar *default_tmpl = ".XXXXXX";
107         gchar *t;
108         gint fd;
109         size_t len;
110
111         g_return_val_if_fail (error == NULL || *error == NULL, -1);
112
113         if (tmpl == NULL)
114                 tmpl = default_tmpl;
115
116         if (strchr (tmpl, G_DIR_SEPARATOR) != NULL) {
117                 if (error) {
118                         *error = g_error_new (G_LOG_DOMAIN, 24, "Template should not have any " G_DIR_SEPARATOR_S);
119                 }
120                 return -1;
121         }
122
123         len = strlen (tmpl);
124         if (len < 6 || strcmp (tmpl + len - 6, "XXXXXX")) {
125                 if (error) {
126                         *error = g_error_new (G_LOG_DOMAIN, 24, "Template should end with XXXXXX");
127                 }
128                 return -1;
129         }
130
131         t = g_build_filename (g_get_tmp_dir (), tmpl, NULL);
132
133         fd = mkstemp (t);
134
135         if (fd == -1) {
136                 if (error) {
137                         int err = errno;
138                         *error = g_error_new (G_LOG_DOMAIN, g_file_error_from_errno (err), "Error in mkstemp()");
139                 }
140                 g_free (t);
141                 return -1;
142         }
143
144         if (name_used) {
145                 *name_used = t;
146         } else {
147                 g_free (t);
148         }
149         return fd;
150 }
151
152 gchar *
153 g_get_current_dir (void)
154 {
155         int s = 32;
156         char *buffer = NULL, *r;
157         gboolean fail;
158         
159         do {
160                 buffer = g_realloc (buffer, s);
161                 r = getcwd (buffer, s);
162                 fail = (r == NULL && errno == ERANGE);
163                 if (fail) {
164                         s <<= 1;
165                 }
166         } while (fail);
167
168         /* On amd64 sometimes the bottom 32-bits of r == the bottom 32-bits of buffer
169          * but the top 32-bits of r have overflown to 0xffffffff (seriously wtf getcwd
170          * so we return the buffer here since it has a pointer to the valid string
171          */
172         return buffer;
173 }
174