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