[2020-02] Use GArray instead of GList when getting custom attributes from an image...
[mono-project.git] / mono / eglib / gfile-posix.c
blobc18850a86262610a3a827c46e901f9c8a332da71
1 /*
2 * File utility functions.
4 * Author:
5 * Gonzalo Paniagua Javier (gonzalo@novell.com)
7 * (C) 2006 Novell, Inc.
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:
17 * The above copyright notice and this permission notice shall be
18 * included in all copies or substantial portions of the Software.
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.
28 #include <config.h>
29 #include <glib.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #ifdef HAVE_UNISTD_H
35 #include <unistd.h>
36 #endif
37 #include <fcntl.h>
38 #include <errno.h>
40 #ifdef _MSC_VER
41 #include <direct.h>
42 #endif
43 #ifdef G_OS_WIN32
44 int mkstemp (char *tmp_template);
45 #endif
47 #ifndef O_LARGEFILE
48 #define OPEN_FLAGS (O_RDONLY)
49 #else
50 #define OPEN_FLAGS (O_RDONLY | O_LARGEFILE)
51 #endif
52 gboolean
53 g_file_get_contents (const gchar *filename, gchar **contents, gsize *length, GError **gerror)
55 gchar *str;
56 int fd;
57 struct stat st;
58 long offset;
59 int nread;
61 g_return_val_if_fail (filename != NULL, FALSE);
62 g_return_val_if_fail (contents != NULL, FALSE);
63 g_return_val_if_fail (gerror == NULL || *gerror == NULL, FALSE);
65 *contents = NULL;
66 if (length)
67 *length = 0;
69 fd = open (filename, OPEN_FLAGS);
70 if (fd == -1) {
71 if (gerror != NULL) {
72 int err = errno;
73 *gerror = g_error_new (G_LOG_DOMAIN, g_file_error_from_errno (err), "Error opening file");
75 return FALSE;
78 if (fstat (fd, &st) != 0) {
79 if (gerror != NULL) {
80 int err = errno;
81 *gerror = g_error_new (G_LOG_DOMAIN, g_file_error_from_errno (err), "Error in fstat()");
83 close (fd);
84 return FALSE;
87 str = g_malloc (st.st_size + 1);
88 offset = 0;
89 do {
90 nread = read (fd, str + offset, st.st_size - offset);
91 if (nread > 0) {
92 offset += nread;
94 } while ((nread > 0 && offset < st.st_size) || (nread == -1 && errno == EINTR));
96 close (fd);
98 #ifdef G_OS_WIN32
99 // Windows defaults to O_TEXT for opened files, meaning that st_size can be larger than
100 // what's actually read into str due to new line conversion.
101 g_assert (offset <= st.st_size);
102 str [offset] = '\0';
103 if (length)
104 *length = offset;
105 #else
106 str [st.st_size] = '\0';
107 if (length) {
108 *length = st.st_size;
110 #endif
112 *contents = str;
113 return TRUE;
116 gint
117 g_file_open_tmp (const gchar *tmpl, gchar **name_used, GError **gerror)
119 const static gchar *default_tmpl = ".XXXXXX";
120 gchar *t;
121 gint fd;
122 size_t len;
124 g_return_val_if_fail (gerror == NULL || *gerror == NULL, -1);
126 if (tmpl == NULL)
127 tmpl = default_tmpl;
129 if (strchr (tmpl, G_DIR_SEPARATOR) != NULL) {
130 if (gerror) {
131 *gerror = g_error_new (G_LOG_DOMAIN, 24, "Template should not have any " G_DIR_SEPARATOR_S);
133 return -1;
136 len = strlen (tmpl);
137 if (len < 6 || strcmp (tmpl + len - 6, "XXXXXX")) {
138 if (gerror) {
139 *gerror = g_error_new (G_LOG_DOMAIN, 24, "Template should end with XXXXXX");
141 return -1;
144 t = g_build_filename (g_get_tmp_dir (), tmpl, (const char*)NULL);
146 fd = mkstemp (t);
148 if (fd == -1) {
149 if (gerror) {
150 int err = errno;
151 *gerror = g_error_new (G_LOG_DOMAIN, g_file_error_from_errno (err), "Error in mkstemp()");
153 g_free (t);
154 return -1;
157 if (name_used) {
158 *name_used = t;
159 } else {
160 g_free (t);
162 return fd;
165 gchar *
166 g_get_current_dir (void)
168 int s = 32;
169 char *buffer = NULL, *r;
170 gboolean fail;
172 do {
173 buffer = g_realloc (buffer, s);
174 r = getcwd (buffer, s);
175 fail = (r == NULL && errno == ERANGE);
176 if (fail) {
177 s <<= 1;
179 } while (fail);
181 /* On amd64 sometimes the bottom 32-bits of r == the bottom 32-bits of buffer
182 * but the top 32-bits of r have overflown to 0xffffffff (seriously wtf getcwd
183 * so we return the buffer here since it has a pointer to the valid string
185 return buffer;