1/* Unit tests for gfileutils
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 *
4 * This work is provided "as is"; redistribution and modification
5 * in whole or in part, in any medium, physical or electronic is
6 * permitted without restriction.
7 *
8 * This work is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * In no event shall the authors or contributors be liable for any
13 * direct, indirect, incidental, special, exemplary, or consequential
14 * damages (including, but not limited to, procurement of substitute
15 * goods or services; loss of use, data, or profits; or business
16 * interruption) however caused and on any theory of liability, whether
17 * in contract, strict liability, or tort (including negligence or
18 * otherwise) arising in any way out of the use of this software, even
19 * if advised of the possibility of such damage.
20 */
21
22#include "config.h"
23#include <string.h>
24#include <errno.h>
25
26/* We are testing some deprecated APIs here */
27#ifndef GLIB_DISABLE_DEPRECATION_WARNINGS
28#define GLIB_DISABLE_DEPRECATION_WARNINGS
29#endif
30
31#include <glib.h>
32
33/* Test our stdio wrappers here; this disables redefining (e.g.) g_open() to open() */
34#define G_STDIO_WRAP_ON_UNIX
35#include <glib/gstdio.h>
36
37#ifdef G_OS_UNIX
38#include <unistd.h>
39#include <sys/types.h>
40#include <sys/stat.h>
41#include <utime.h>
42
43#define G_TEST_DIR_MODE 0555
44#endif
45#include <fcntl.h>
46#ifdef G_OS_WIN32
47#include <windows.h>
48#include <sys/utime.h>
49#include <io.h>
50#ifndef S_ISDIR
51#define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR)
52#endif
53#ifndef F_OK
54#define F_OK 0
55#endif
56
57#define G_TEST_DIR_MODE (S_IWRITE | S_IREAD)
58#endif
59
60#define S G_DIR_SEPARATOR_S
61
62static void
63check_string (gchar *str, const gchar *expected)
64{
65 g_assert_nonnull (str);
66 g_assert_cmpstr (str, ==, expected);
67 g_free (mem: str);
68}
69
70static void
71test_build_path (void)
72{
73/* check_string (g_build_path ("", NULL), "");*/
74 check_string (str: g_build_path (separator: "", first_element: "", NULL), expected: "");
75 check_string (str: g_build_path (separator: "", first_element: "x", NULL), expected: "x");
76 check_string (str: g_build_path (separator: "", first_element: "x", "y", NULL), expected: "xy");
77 check_string (str: g_build_path (separator: "", first_element: "x", "y", "z", NULL), expected: "xyz");
78
79/* check_string (g_build_path (":", NULL), "");*/
80 check_string (str: g_build_path (separator: ":", first_element: ":", NULL), expected: ":");
81 check_string (str: g_build_path (separator: ":", first_element: ":x", NULL), expected: ":x");
82 check_string (str: g_build_path (separator: ":", first_element: "x:", NULL), expected: "x:");
83 check_string (str: g_build_path (separator: ":", first_element: "", "x", NULL), expected: "x");
84 check_string (str: g_build_path (separator: ":", first_element: "", ":x", NULL), expected: ":x");
85 check_string (str: g_build_path (separator: ":", first_element: ":", "x", NULL), expected: ":x");
86 check_string (str: g_build_path (separator: ":", first_element: "::", "x", NULL), expected: "::x");
87 check_string (str: g_build_path (separator: ":", first_element: "x", "", NULL), expected: "x");
88 check_string (str: g_build_path (separator: ":", first_element: "x:", "", NULL), expected: "x:");
89 check_string (str: g_build_path (separator: ":", first_element: "x", ":", NULL), expected: "x:");
90 check_string (str: g_build_path (separator: ":", first_element: "x", "::", NULL), expected: "x::");
91 check_string (str: g_build_path (separator: ":", first_element: "x", "y", NULL), expected: "x:y");
92 check_string (str: g_build_path (separator: ":", first_element: ":x", "y", NULL), expected: ":x:y");
93 check_string (str: g_build_path (separator: ":", first_element: "x", "y:", NULL), expected: "x:y:");
94 check_string (str: g_build_path (separator: ":", first_element: ":x:", ":y:", NULL), expected: ":x:y:");
95 check_string (str: g_build_path (separator: ":", first_element: ":x::", "::y:", NULL), expected: ":x:y:");
96 check_string (str: g_build_path (separator: ":", first_element: "x", "","y", NULL), expected: "x:y");
97 check_string (str: g_build_path (separator: ":", first_element: "x", ":", "y", NULL), expected: "x:y");
98 check_string (str: g_build_path (separator: ":", first_element: "x", "::", "y", NULL), expected: "x:y");
99 check_string (str: g_build_path (separator: ":", first_element: "x", "y", "z", NULL), expected: "x:y:z");
100 check_string (str: g_build_path (separator: ":", first_element: ":x:", ":y:", ":z:", NULL), expected: ":x:y:z:");
101 check_string (str: g_build_path (separator: ":", first_element: "::x::", "::y::", "::z::", NULL), expected: "::x:y:z::");
102
103/* check_string (g_build_path ("::", NULL), "");*/
104 check_string (str: g_build_path (separator: "::", first_element: "::", NULL), expected: "::");
105 check_string (str: g_build_path (separator: "::", first_element: ":::", NULL), expected: ":::");
106 check_string (str: g_build_path (separator: "::", first_element: "::x", NULL), expected: "::x");
107 check_string (str: g_build_path (separator: "::", first_element: "x::", NULL), expected: "x::");
108 check_string (str: g_build_path (separator: "::", first_element: "", "x", NULL), expected: "x");
109 check_string (str: g_build_path (separator: "::", first_element: "", "::x", NULL), expected: "::x");
110 check_string (str: g_build_path (separator: "::", first_element: "::", "x", NULL), expected: "::x");
111 check_string (str: g_build_path (separator: "::", first_element: "::::", "x", NULL), expected: "::::x");
112 check_string (str: g_build_path (separator: "::", first_element: "x", "", NULL), expected: "x");
113 check_string (str: g_build_path (separator: "::", first_element: "x::", "", NULL), expected: "x::");
114 check_string (str: g_build_path (separator: "::", first_element: "x", "::", NULL), expected: "x::");
115
116 /* This following is weird, but keeps the definition simple */
117 check_string (str: g_build_path (separator: "::", first_element: "x", ":::", NULL), expected: "x:::::");
118 check_string (str: g_build_path (separator: "::", first_element: "x", "::::", NULL), expected: "x::::");
119 check_string (str: g_build_path (separator: "::", first_element: "x", "y", NULL), expected: "x::y");
120 check_string (str: g_build_path (separator: "::", first_element: "::x", "y", NULL), expected: "::x::y");
121 check_string (str: g_build_path (separator: "::", first_element: "x", "y::", NULL), expected: "x::y::");
122 check_string (str: g_build_path (separator: "::", first_element: "::x::", "::y::", NULL), expected: "::x::y::");
123 check_string (str: g_build_path (separator: "::", first_element: "::x:::", ":::y::", NULL), expected: "::x::::y::");
124 check_string (str: g_build_path (separator: "::", first_element: "::x::::", "::::y::", NULL), expected: "::x::y::");
125 check_string (str: g_build_path (separator: "::", first_element: "x", "", "y", NULL), expected: "x::y");
126 check_string (str: g_build_path (separator: "::", first_element: "x", "::", "y", NULL), expected: "x::y");
127 check_string (str: g_build_path (separator: "::", first_element: "x", "::::", "y", NULL), expected: "x::y");
128 check_string (str: g_build_path (separator: "::", first_element: "x", "y", "z", NULL), expected: "x::y::z");
129 check_string (str: g_build_path (separator: "::", first_element: "::x::", "::y::", "::z::", NULL), expected: "::x::y::z::");
130 check_string (str: g_build_path (separator: "::", first_element: ":::x:::", ":::y:::", ":::z:::", NULL), expected: ":::x::::y::::z:::");
131 check_string (str: g_build_path (separator: "::", first_element: "::::x::::", "::::y::::", "::::z::::", NULL), expected: "::::x::y::z::::");
132}
133
134static void
135test_build_pathv (void)
136{
137 gchar *args[10];
138
139 g_assert_null (g_build_pathv ("", NULL));
140 args[0] = NULL;
141 check_string (str: g_build_pathv (separator: "", args), expected: "");
142 args[0] = ""; args[1] = NULL;
143 check_string (str: g_build_pathv (separator: "", args), expected: "");
144 args[0] = "x"; args[1] = NULL;
145 check_string (str: g_build_pathv (separator: "", args), expected: "x");
146 args[0] = "x"; args[1] = "y"; args[2] = NULL;
147 check_string (str: g_build_pathv (separator: "", args), expected: "xy");
148 args[0] = "x"; args[1] = "y"; args[2] = "z", args[3] = NULL;
149 check_string (str: g_build_pathv (separator: "", args), expected: "xyz");
150
151 args[0] = NULL;
152 check_string (str: g_build_pathv (separator: ":", args), expected: "");
153 args[0] = ":"; args[1] = NULL;
154 check_string (str: g_build_pathv (separator: ":", args), expected: ":");
155 args[0] = ":x"; args[1] = NULL;
156 check_string (str: g_build_pathv (separator: ":", args), expected: ":x");
157 args[0] = "x:"; args[1] = NULL;
158 check_string (str: g_build_pathv (separator: ":", args), expected: "x:");
159 args[0] = ""; args[1] = "x"; args[2] = NULL;
160 check_string (str: g_build_pathv (separator: ":", args), expected: "x");
161 args[0] = ""; args[1] = ":x"; args[2] = NULL;
162 check_string (str: g_build_pathv (separator: ":", args), expected: ":x");
163 args[0] = ":"; args[1] = "x"; args[2] = NULL;
164 check_string (str: g_build_pathv (separator: ":", args), expected: ":x");
165 args[0] = "::"; args[1] = "x"; args[2] = NULL;
166 check_string (str: g_build_pathv (separator: ":", args), expected: "::x");
167 args[0] = "x"; args[1] = ""; args[2] = NULL;
168 check_string (str: g_build_pathv (separator: ":", args), expected: "x");
169 args[0] = "x:"; args[1] = ""; args[2] = NULL;
170 check_string (str: g_build_pathv (separator: ":", args), expected: "x:");
171 args[0] = "x"; args[1] = ":"; args[2] = NULL;
172 check_string (str: g_build_pathv (separator: ":", args), expected: "x:");
173 args[0] = "x"; args[1] = "::"; args[2] = NULL;
174 check_string (str: g_build_pathv (separator: ":", args), expected: "x::");
175 args[0] = "x"; args[1] = "y"; args[2] = NULL;
176 check_string (str: g_build_pathv (separator: ":", args), expected: "x:y");
177 args[0] = ":x"; args[1] = "y"; args[2] = NULL;
178 check_string (str: g_build_pathv (separator: ":", args), expected: ":x:y");
179 args[0] = "x"; args[1] = "y:"; args[2] = NULL;
180 check_string (str: g_build_pathv (separator: ":", args), expected: "x:y:");
181 args[0] = ":x:"; args[1] = ":y:"; args[2] = NULL;
182 check_string (str: g_build_pathv (separator: ":", args), expected: ":x:y:");
183 args[0] = ":x::"; args[1] = "::y:"; args[2] = NULL;
184 check_string (str: g_build_pathv (separator: ":", args), expected: ":x:y:");
185 args[0] = "x"; args[1] = ""; args[2] = "y"; args[3] = NULL;
186 check_string (str: g_build_pathv (separator: ":", args), expected: "x:y");
187 args[0] = "x"; args[1] = ":"; args[2] = "y"; args[3] = NULL;
188 check_string (str: g_build_pathv (separator: ":", args), expected: "x:y");
189 args[0] = "x"; args[1] = "::"; args[2] = "y"; args[3] = NULL;
190 check_string (str: g_build_pathv (separator: ":", args), expected: "x:y");
191 args[0] = "x"; args[1] = "y"; args[2] = "z"; args[3] = NULL;
192 check_string (str: g_build_pathv (separator: ":", args), expected: "x:y:z");
193 args[0] = ":x:"; args[1] = ":y:"; args[2] = ":z:"; args[3] = NULL;
194 check_string (str: g_build_pathv (separator: ":", args), expected: ":x:y:z:");
195 args[0] = "::x::"; args[1] = "::y::"; args[2] = "::z::"; args[3] = NULL;
196 check_string (str: g_build_pathv (separator: ":", args), expected: "::x:y:z::");
197
198 args[0] = NULL;
199 check_string (str: g_build_pathv (separator: "::", args), expected: "");
200 args[0] = "::"; args[1] = NULL;
201 check_string (str: g_build_pathv (separator: "::", args), expected: "::");
202 args[0] = ":::"; args[1] = NULL;
203 check_string (str: g_build_pathv (separator: "::", args), expected: ":::");
204 args[0] = "::x"; args[1] = NULL;
205 check_string (str: g_build_pathv (separator: "::", args), expected: "::x");
206 args[0] = "x::"; args[1] = NULL;
207 check_string (str: g_build_pathv (separator: "::", args), expected: "x::");
208 args[0] = ""; args[1] = "x"; args[2] = NULL;
209 check_string (str: g_build_pathv (separator: "::", args), expected: "x");
210 args[0] = ""; args[1] = "::x"; args[2] = NULL;
211 check_string (str: g_build_pathv (separator: "::", args), expected: "::x");
212 args[0] = "::"; args[1] = "x"; args[2] = NULL;
213 check_string (str: g_build_pathv (separator: "::", args), expected: "::x");
214 args[0] = "::::"; args[1] = "x"; args[2] = NULL;
215 check_string (str: g_build_pathv (separator: "::", args), expected: "::::x");
216 args[0] = "x"; args[1] = ""; args[2] = NULL;
217 check_string (str: g_build_pathv (separator: "::", args), expected: "x");
218 args[0] = "x::"; args[1] = ""; args[2] = NULL;
219 check_string (str: g_build_pathv (separator: "::", args), expected: "x::");
220 args[0] = "x"; args[1] = "::"; args[2] = NULL;
221 check_string (str: g_build_pathv (separator: "::", args), expected: "x::");
222 /* This following is weird, but keeps the definition simple */
223 args[0] = "x"; args[1] = ":::"; args[2] = NULL;
224 check_string (str: g_build_pathv (separator: "::", args), expected: "x:::::");
225 args[0] = "x"; args[1] = "::::"; args[2] = NULL;
226 check_string (str: g_build_pathv (separator: "::", args), expected: "x::::");
227 args[0] = "x"; args[1] = "y"; args[2] = NULL;
228 check_string (str: g_build_pathv (separator: "::", args), expected: "x::y");
229 args[0] = "::x"; args[1] = "y"; args[2] = NULL;
230 check_string (str: g_build_pathv (separator: "::", args), expected: "::x::y");
231 args[0] = "x"; args[1] = "y::"; args[2] = NULL;
232 check_string (str: g_build_pathv (separator: "::", args), expected: "x::y::");
233 args[0] = "::x::"; args[1] = "::y::"; args[2] = NULL;
234 check_string (str: g_build_pathv (separator: "::", args), expected: "::x::y::");
235 args[0] = "::x:::"; args[1] = ":::y::"; args[2] = NULL;
236 check_string (str: g_build_pathv (separator: "::", args), expected: "::x::::y::");
237 args[0] = "::x::::"; args[1] = "::::y::"; args[2] = NULL;
238 check_string (str: g_build_pathv (separator: "::", args), expected: "::x::y::");
239 args[0] = "x"; args[1] = ""; args[2] = "y"; args[3] = NULL;
240 check_string (str: g_build_pathv (separator: "::", args), expected: "x::y");
241 args[0] = "x"; args[1] = "::"; args[2] = "y"; args[3] = NULL;
242 check_string (str: g_build_pathv (separator: "::", args), expected: "x::y");
243 args[0] = "x"; args[1] = "::::"; args[2] = "y"; args[3] = NULL;
244 check_string (str: g_build_pathv (separator: "::", args), expected: "x::y");
245 args[0] = "x"; args[1] = "y"; args[2] = "z"; args[3] = NULL;
246 check_string (str: g_build_pathv (separator: "::", args), expected: "x::y::z");
247 args[0] = "::x::"; args[1] = "::y::"; args[2] = "::z::"; args[3] = NULL;
248 check_string (str: g_build_pathv (separator: "::", args), expected: "::x::y::z::");
249 args[0] = ":::x:::"; args[1] = ":::y:::"; args[2] = ":::z:::"; args[3] = NULL;
250 check_string (str: g_build_pathv (separator: "::", args), expected: ":::x::::y::::z:::");
251 args[0] = "::::x::::"; args[1] = "::::y::::"; args[2] = "::::z::::"; args[3] = NULL;
252 check_string (str: g_build_pathv (separator: "::", args), expected: "::::x::y::z::::");
253}
254
255static void
256test_build_filename (void)
257{
258/* check_string (g_build_filename (NULL), "");*/
259 check_string (str: g_build_filename (S, NULL), S);
260 check_string (str: g_build_filename (S"x", NULL), S"x");
261 check_string (str: g_build_filename (first_element: "x"S, NULL), expected: "x"S);
262 check_string (str: g_build_filename (first_element: "", "x", NULL), expected: "x");
263 check_string (str: g_build_filename (first_element: "", S"x", NULL), S"x");
264 check_string (str: g_build_filename (S, "x", NULL), S"x");
265 check_string (str: g_build_filename (S S, "x", NULL), S S"x");
266 check_string (str: g_build_filename (first_element: "x", "", NULL), expected: "x");
267 check_string (str: g_build_filename (first_element: "x"S, "", NULL), expected: "x"S);
268 check_string (str: g_build_filename (first_element: "x", S, NULL), expected: "x"S);
269 check_string (str: g_build_filename (first_element: "x", S S, NULL), expected: "x"S S);
270 check_string (str: g_build_filename (first_element: "x", "y", NULL), expected: "x"S"y");
271 check_string (str: g_build_filename (S"x", "y", NULL), S"x"S"y");
272 check_string (str: g_build_filename (first_element: "x", "y"S, NULL), expected: "x"S"y"S);
273 check_string (str: g_build_filename (S"x"S, S"y"S, NULL), S"x"S"y"S);
274 check_string (str: g_build_filename (S"x"S S, S S"y"S, NULL), S"x"S"y"S);
275 check_string (str: g_build_filename (first_element: "x", "", "y", NULL), expected: "x"S"y");
276 check_string (str: g_build_filename (first_element: "x", S, "y", NULL), expected: "x"S"y");
277 check_string (str: g_build_filename (first_element: "x", S S, "y", NULL), expected: "x"S"y");
278 check_string (str: g_build_filename (first_element: "x", "y", "z", NULL), expected: "x"S"y"S"z");
279 check_string (str: g_build_filename (S"x"S, S"y"S, S"z"S, NULL), S"x"S"y"S"z"S);
280 check_string (str: g_build_filename (S S"x"S S, S S"y"S S, S S"z"S S, NULL), S S"x"S"y"S"z"S S);
281
282#ifdef G_OS_WIN32
283
284 /* Test also using the slash as file name separator */
285#define Z "/"
286 /* check_string (g_build_filename (NULL), ""); */
287 check_string (g_build_filename (Z, NULL), Z);
288 check_string (g_build_filename (Z"x", NULL), Z"x");
289 check_string (g_build_filename ("x"Z, NULL), "x"Z);
290 check_string (g_build_filename ("", Z"x", NULL), Z"x");
291 check_string (g_build_filename ("", Z"x", NULL), Z"x");
292 check_string (g_build_filename (Z, "x", NULL), Z"x");
293 check_string (g_build_filename (Z Z, "x", NULL), Z Z"x");
294 check_string (g_build_filename (Z S, "x", NULL), Z S"x");
295 check_string (g_build_filename ("x"Z, "", NULL), "x"Z);
296 check_string (g_build_filename ("x"S"y", "z"Z"a", NULL), "x"S"y"S"z"Z"a");
297 check_string (g_build_filename ("x", Z, NULL), "x"Z);
298 check_string (g_build_filename ("x", Z Z, NULL), "x"Z Z);
299 check_string (g_build_filename ("x", S Z, NULL), "x"S Z);
300 check_string (g_build_filename (Z"x", "y", NULL), Z"x"Z"y");
301 check_string (g_build_filename ("x", "y"Z, NULL), "x"Z"y"Z);
302 check_string (g_build_filename (Z"x"Z, Z"y"Z, NULL), Z"x"Z"y"Z);
303 check_string (g_build_filename (Z"x"Z Z, Z Z"y"Z, NULL), Z"x"Z"y"Z);
304 check_string (g_build_filename ("x", Z, "y", NULL), "x"Z"y");
305 check_string (g_build_filename ("x", Z Z, "y", NULL), "x"Z"y");
306 check_string (g_build_filename ("x", Z S, "y", NULL), "x"S"y");
307 check_string (g_build_filename ("x", S Z, "y", NULL), "x"Z"y");
308 check_string (g_build_filename ("x", Z "y", "z", NULL), "x"Z"y"Z"z");
309 check_string (g_build_filename ("x", S "y", "z", NULL), "x"S"y"S"z");
310 check_string (g_build_filename ("x", S "y", "z", Z, "a", "b", NULL), "x"S"y"S"z"Z"a"Z"b");
311 check_string (g_build_filename (Z"x"Z, Z"y"Z, Z"z"Z, NULL), Z"x"Z"y"Z"z"Z);
312 check_string (g_build_filename (Z Z"x"Z Z, Z Z"y"Z Z, Z Z"z"Z Z, NULL), Z Z"x"Z"y"Z"z"Z Z);
313
314#undef Z
315
316#endif /* G_OS_WIN32 */
317
318}
319
320static void
321test_build_filenamev (void)
322{
323 gchar *args[10];
324
325 args[0] = NULL;
326 check_string (str: g_build_filenamev (args), expected: "");
327 args[0] = S; args[1] = NULL;
328 check_string (str: g_build_filenamev (args), S);
329 args[0] = S"x"; args[1] = NULL;
330 check_string (str: g_build_filenamev (args), S"x");
331 args[0] = "x"S; args[1] = NULL;
332 check_string (str: g_build_filenamev (args), expected: "x"S);
333 args[0] = ""; args[1] = "x"; args[2] = NULL;
334 check_string (str: g_build_filenamev (args), expected: "x");
335 args[0] = ""; args[1] = S"x"; args[2] = NULL;
336 check_string (str: g_build_filenamev (args), S"x");
337 args[0] = S; args[1] = "x"; args[2] = NULL;
338 check_string (str: g_build_filenamev (args), S"x");
339 args[0] = S S; args[1] = "x"; args[2] = NULL;
340 check_string (str: g_build_filenamev (args), S S"x");
341 args[0] = "x"; args[1] = ""; args[2] = NULL;
342 check_string (str: g_build_filenamev (args), expected: "x");
343 args[0] = "x"S; args[1] = ""; args[2] = NULL;
344 check_string (str: g_build_filenamev (args), expected: "x"S);
345 args[0] = "x"; args[1] = S; args[2] = NULL;
346 check_string (str: g_build_filenamev (args), expected: "x"S);
347 args[0] = "x"; args[1] = S S; args[2] = NULL;
348 check_string (str: g_build_filenamev (args), expected: "x"S S);
349 args[0] = "x"; args[1] = "y"; args[2] = NULL;
350 check_string (str: g_build_filenamev (args), expected: "x"S"y");
351 args[0] = S"x"; args[1] = "y"; args[2] = NULL;
352 check_string (str: g_build_filenamev (args), S"x"S"y");
353 args[0] = "x"; args[1] = "y"S; args[2] = NULL;
354 check_string (str: g_build_filenamev (args), expected: "x"S"y"S);
355 args[0] = S"x"S; args[1] = S"y"S; args[2] = NULL;
356 check_string (str: g_build_filenamev (args), S"x"S"y"S);
357 args[0] = S"x"S S; args[1] = S S"y"S; args[2] = NULL;
358 check_string (str: g_build_filenamev (args), S"x"S"y"S);
359 args[0] = "x"; args[1] = ""; args[2] = "y"; args[3] = NULL;
360 check_string (str: g_build_filenamev (args), expected: "x"S"y");
361 args[0] = "x"; args[1] = S; args[2] = "y"; args[3] = NULL;
362 check_string (str: g_build_filenamev (args), expected: "x"S"y");
363 args[0] = "x"; args[1] = S S; args[2] = "y"; args[3] = NULL;
364 check_string (str: g_build_filenamev (args), expected: "x"S"y");
365 args[0] = "x"; args[1] = "y"; args[2] = "z"; args[3] = NULL;
366 check_string (str: g_build_filenamev (args), expected: "x"S"y"S"z");
367 args[0] = S"x"S; args[1] = S"y"S; args[2] = S"z"S; args[3] = NULL;
368 check_string (str: g_build_filenamev (args), S"x"S"y"S"z"S);
369 args[0] = S S"x"S S; args[1] = S S"y"S S; args[2] = S S"z"S S; args[3] = NULL;
370 check_string (str: g_build_filenamev (args), S S"x"S"y"S"z"S S);
371
372#ifdef G_OS_WIN32
373
374 /* Test also using the slash as file name separator */
375#define Z "/"
376 args[0] = NULL;
377 check_string (g_build_filenamev (args), "");
378 args[0] = Z; args[1] = NULL;
379 check_string (g_build_filenamev (args), Z);
380 args[0] = Z"x"; args[1] = NULL;
381 check_string (g_build_filenamev (args), Z"x");
382 args[0] = "x"Z; args[1] = NULL;
383 check_string (g_build_filenamev (args), "x"Z);
384 args[0] = ""; args[1] = Z"x"; args[2] = NULL;
385 check_string (g_build_filenamev (args), Z"x");
386 args[0] = ""; args[1] = Z"x"; args[2] = NULL;
387 check_string (g_build_filenamev (args), Z"x");
388 args[0] = Z; args[1] = "x"; args[2] = NULL;
389 check_string (g_build_filenamev (args), Z"x");
390 args[0] = Z Z; args[1] = "x"; args[2] = NULL;
391 check_string (g_build_filenamev (args), Z Z"x");
392 args[0] = Z S; args[1] = "x"; args[2] = NULL;
393 check_string (g_build_filenamev (args), Z S"x");
394 args[0] = "x"Z; args[1] = ""; args[2] = NULL;
395 check_string (g_build_filenamev (args), "x"Z);
396 args[0] = "x"S"y"; args[1] = "z"Z"a"; args[2] = NULL;
397 check_string (g_build_filenamev (args), "x"S"y"S"z"Z"a");
398 args[0] = "x"; args[1] = Z; args[2] = NULL;
399 check_string (g_build_filenamev (args), "x"Z);
400 args[0] = "x"; args[1] = Z Z; args[2] = NULL;
401 check_string (g_build_filenamev (args), "x"Z Z);
402 args[0] = "x"; args[1] = S Z; args[2] = NULL;
403 check_string (g_build_filenamev (args), "x"S Z);
404 args[0] = Z"x"; args[1] = "y"; args[2] = NULL;
405 check_string (g_build_filenamev (args), Z"x"Z"y");
406 args[0] = "x"; args[1] = "y"Z; args[2] = NULL;
407 check_string (g_build_filenamev (args), "x"Z"y"Z);
408 args[0] = Z"x"Z; args[1] = Z"y"Z; args[2] = NULL;
409 check_string (g_build_filenamev (args), Z"x"Z"y"Z);
410 args[0] = Z"x"Z Z; args[1] = Z Z"y"Z; args[2] = NULL;
411 check_string (g_build_filenamev (args), Z"x"Z"y"Z);
412 args[0] = "x"; args[1] = Z; args[2] = "y", args[3] = NULL;
413 check_string (g_build_filenamev (args), "x"Z"y");
414 args[0] = "x"; args[1] = Z Z; args[2] = "y", args[3] = NULL;
415 check_string (g_build_filenamev (args), "x"Z"y");
416 args[0] = "x"; args[1] = Z S; args[2] = "y", args[3] = NULL;
417 check_string (g_build_filenamev (args), "x"S"y");
418 args[0] = "x"; args[1] = S Z; args[2] = "y", args[3] = NULL;
419 check_string (g_build_filenamev (args), "x"Z"y");
420 args[0] = "x"; args[1] = Z "y"; args[2] = "z", args[3] = NULL;
421 check_string (g_build_filenamev (args), "x"Z"y"Z"z");
422 args[0] = "x"; args[1] = S "y"; args[2] = "z", args[3] = NULL;
423 check_string (g_build_filenamev (args), "x"S"y"S"z");
424 args[0] = "x"; args[1] = S "y"; args[2] = "z", args[3] = Z;
425 args[4] = "a"; args[5] = "b"; args[6] = NULL;
426 check_string (g_build_filenamev (args), "x"S"y"S"z"Z"a"Z"b");
427 args[0] = Z"x"Z; args[1] = Z"y"Z; args[2] = Z"z"Z, args[3] = NULL;
428 check_string (g_build_filenamev (args), Z"x"Z"y"Z"z"Z);
429 args[0] = Z Z"x"Z Z; args[1] = Z Z"y"Z Z; args[2] = Z Z"z"Z Z, args[3] = NULL;
430 check_string (g_build_filenamev (args), Z Z"x"Z"y"Z"z"Z Z);
431
432#undef Z
433
434#endif /* G_OS_WIN32 */
435}
436
437#undef S
438
439static void
440test_mkdir_with_parents_1 (const gchar *base)
441{
442 char *p0 = g_build_filename (first_element: base, "fum", NULL);
443 char *p1 = g_build_filename (first_element: p0, "tem", NULL);
444 char *p2 = g_build_filename (first_element: p1, "zap", NULL);
445 FILE *f;
446
447 g_remove (filename: p2);
448 g_remove (filename: p1);
449 g_remove (filename: p0);
450
451 if (g_file_test (filename: p0, test: G_FILE_TEST_EXISTS))
452 g_error ("failed, %s exists, cannot test g_mkdir_with_parents", p0);
453
454 if (g_file_test (filename: p1, test: G_FILE_TEST_EXISTS))
455 g_error ("failed, %s exists, cannot test g_mkdir_with_parents", p1);
456
457 if (g_file_test (filename: p2, test: G_FILE_TEST_EXISTS))
458 g_error ("failed, %s exists, cannot test g_mkdir_with_parents", p2);
459
460 if (g_mkdir_with_parents (pathname: p2, mode: 0777) == -1)
461 {
462 int errsv = errno;
463 g_error ("failed, g_mkdir_with_parents(%s) failed: %s", p2, g_strerror (errsv));
464 }
465
466 if (!g_file_test (filename: p2, test: G_FILE_TEST_IS_DIR))
467 g_error ("failed, g_mkdir_with_parents(%s) succeeded, but %s is not a directory", p2, p2);
468
469 if (!g_file_test (filename: p1, test: G_FILE_TEST_IS_DIR))
470 g_error ("failed, g_mkdir_with_parents(%s) succeeded, but %s is not a directory", p2, p1);
471
472 if (!g_file_test (filename: p0, test: G_FILE_TEST_IS_DIR))
473 g_error ("failed, g_mkdir_with_parents(%s) succeeded, but %s is not a directory", p2, p0);
474
475 g_rmdir (filename: p2);
476 if (g_file_test (filename: p2, test: G_FILE_TEST_EXISTS))
477 g_error ("failed, did g_rmdir(%s), but %s is still there", p2, p2);
478
479 g_rmdir (filename: p1);
480 if (g_file_test (filename: p1, test: G_FILE_TEST_EXISTS))
481 g_error ("failed, did g_rmdir(%s), but %s is still there", p1, p1);
482
483 f = g_fopen (filename: p1, mode: "w");
484 if (f == NULL)
485 g_error ("failed, couldn't create file %s", p1);
486 fclose (stream: f);
487
488 if (g_mkdir_with_parents (pathname: p1, mode: 0666) == 0)
489 g_error ("failed, g_mkdir_with_parents(%s) succeeded, even if %s is a file", p1, p1);
490
491 if (g_mkdir_with_parents (pathname: p2, mode: 0666) == 0)
492 g_error("failed, g_mkdir_with_parents(%s) succeeded, even if %s is a file", p2, p1);
493
494 g_remove (filename: p2);
495 g_remove (filename: p1);
496 g_remove (filename: p0);
497
498 g_free (mem: p2);
499 g_free (mem: p1);
500 g_free (mem: p0);
501}
502
503static void
504test_mkdir_with_parents (void)
505{
506 gchar *cwd;
507 if (g_test_verbose())
508 g_printerr (format: "checking g_mkdir_with_parents() in subdir ./hum/");
509 test_mkdir_with_parents_1 (base: "hum");
510 g_remove (filename: "hum");
511 if (g_test_verbose())
512 g_printerr (format: "checking g_mkdir_with_parents() in subdir ./hii///haa/hee/");
513 test_mkdir_with_parents_1 (base: "hii///haa/hee");
514 g_remove (filename: "hii/haa/hee");
515 g_remove (filename: "hii/haa");
516 g_remove (filename: "hii");
517 cwd = g_get_current_dir ();
518 if (g_test_verbose())
519 g_printerr (format: "checking g_mkdir_with_parents() in cwd: %s", cwd);
520 test_mkdir_with_parents_1 (base: cwd);
521 g_free (mem: cwd);
522
523 g_assert_cmpint (g_mkdir_with_parents (NULL, 0), ==, -1);
524 g_assert_cmpint (errno, ==, EINVAL);
525}
526
527/*
528 * check_cap_dac_override:
529 * @tmpdir: (nullable): A temporary directory in which we can create
530 * and delete files. If %NULL, use the g_get_tmp_dir(), safely.
531 *
532 * Check whether the current process can bypass DAC permissions.
533 *
534 * Traditionally, "privileged" processes (those with effective uid 0)
535 * could do this (and bypass many other checks), and "unprivileged"
536 * processes could not.
537 *
538 * In Linux, the special powers of euid 0 are divided into many
539 * capabilities: see `capabilities(7)`. The one we are interested in
540 * here is `CAP_DAC_OVERRIDE`.
541 *
542 * We do this generically instead of actually looking at the capability
543 * bits, so that the right thing will happen on non-Linux Unix
544 * implementations, in particular if they have something equivalent to
545 * but not identical to Linux permissions.
546 *
547 * Returns: %TRUE if we have Linux `CAP_DAC_OVERRIDE` or equivalent
548 * privileges
549 */
550static gboolean
551check_cap_dac_override (const char *tmpdir)
552{
553#ifdef G_OS_UNIX
554 gchar *safe_tmpdir = NULL;
555 gchar *dac_denies_write;
556 gchar *inside;
557 gboolean have_cap;
558
559 if (tmpdir == NULL)
560 {
561 /* It's unsafe to write predictable filenames into g_get_tmp_dir(),
562 * because it's usually a shared directory that can be subject to
563 * symlink attacks, so use a subdirectory for this check. */
564 GError *error = NULL;
565
566 safe_tmpdir = g_dir_make_tmp (NULL, error: &error);
567 g_assert_no_error (error);
568 g_clear_error (err: &error);
569
570 if (safe_tmpdir == NULL)
571 return FALSE;
572
573 tmpdir = safe_tmpdir;
574 }
575
576 dac_denies_write = g_build_filename (first_element: tmpdir, "dac-denies-write", NULL);
577 inside = g_build_filename (first_element: dac_denies_write, "inside", NULL);
578
579 g_assert_no_errno (mkdir (dac_denies_write, S_IRWXU));
580 g_assert_no_errno (chmod (dac_denies_write, 0));
581
582 if (mkdir (path: inside, S_IRWXU) == 0)
583 {
584 g_test_message (format: "Looks like we have CAP_DAC_OVERRIDE or equivalent");
585 g_assert_no_errno (rmdir (inside));
586 have_cap = TRUE;
587 }
588 else
589 {
590 int saved_errno = errno;
591
592 g_test_message (format: "We do not have CAP_DAC_OVERRIDE or equivalent");
593 g_assert_cmpint (saved_errno, ==, EACCES);
594 have_cap = FALSE;
595 }
596
597 g_assert_no_errno (chmod (dac_denies_write, S_IRWXU));
598 g_assert_no_errno (rmdir (dac_denies_write));
599
600 if (safe_tmpdir != NULL)
601 g_assert_no_errno (rmdir (safe_tmpdir));
602
603 g_free (mem: dac_denies_write);
604 g_free (mem: inside);
605 g_free (mem: safe_tmpdir);
606 return have_cap;
607#else
608 return FALSE;
609#endif
610}
611
612/* Reproducer for https://gitlab.gnome.org/GNOME/glib/issues/1852 */
613static void
614test_mkdir_with_parents_permission (void)
615{
616#ifdef G_OS_UNIX
617 gchar *tmpdir;
618 gchar *subdir;
619 gchar *subdir2;
620 gchar *subdir3;
621 GError *error = NULL;
622 int result;
623 int saved_errno;
624 gboolean have_cap_dac_override;
625
626 tmpdir = g_dir_make_tmp (tmpl: "test-fileutils.XXXXXX", error: &error);
627 g_assert_no_error (error);
628 g_assert_nonnull (tmpdir);
629
630 have_cap_dac_override = check_cap_dac_override (tmpdir);
631
632 subdir = g_build_filename (first_element: tmpdir, "sub", NULL);
633 subdir2 = g_build_filename (first_element: subdir, "sub2", NULL);
634 subdir3 = g_build_filename (first_element: subdir2, "sub3", NULL);
635 g_assert_no_errno (g_mkdir (subdir, 0700));
636 g_assert_no_errno (g_chmod (subdir, 0));
637
638 if (have_cap_dac_override)
639 {
640 g_test_skip (msg: "have CAP_DAC_OVERRIDE or equivalent, cannot test");
641 }
642 else
643 {
644 result = g_mkdir_with_parents (pathname: subdir2, mode: 0700);
645 saved_errno = errno;
646 g_assert_cmpint (result, ==, -1);
647 g_assert_cmpint (saved_errno, ==, EACCES);
648
649 result = g_mkdir_with_parents (pathname: subdir3, mode: 0700);
650 saved_errno = errno;
651 g_assert_cmpint (result, ==, -1);
652 g_assert_cmpint (saved_errno, ==, EACCES);
653
654 g_assert_no_errno (g_chmod (subdir, 0700));
655 }
656
657 g_assert_no_errno (g_remove (subdir));
658 g_assert_no_errno (g_remove (tmpdir));
659 g_free (mem: subdir3);
660 g_free (mem: subdir2);
661 g_free (mem: subdir);
662 g_free (mem: tmpdir);
663#else
664 g_test_skip ("cannot test without Unix-style permissions");
665#endif
666}
667
668static void
669test_format_size_for_display (void)
670{
671#ifdef G_OS_WIN32
672 SetThreadLocale (MAKELCID (MAKELANGID (LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT));
673#endif
674 /* nobody called setlocale(), so we should get "C" behaviour... */
675 check_string (str: g_format_size_for_display (size: 0), expected: "0 bytes");
676 check_string (str: g_format_size_for_display (size: 1), expected: "1 byte");
677 check_string (str: g_format_size_for_display (size: 2), expected: "2 bytes");
678 check_string (str: g_format_size_for_display (size: 1024), expected: "1.0 KB");
679 check_string (str: g_format_size_for_display (size: 1024 * 1024), expected: "1.0 MB");
680 check_string (str: g_format_size_for_display (size: 1024 * 1024 * 1024), expected: "1.0 GB");
681 check_string (str: g_format_size_for_display (size: 1024ULL * 1024 * 1024 * 1024), expected: "1.0 TB");
682 check_string (str: g_format_size_for_display (size: 1024ULL * 1024 * 1024 * 1024 * 1024), expected: "1.0 PB");
683 check_string (str: g_format_size_for_display (size: 1024ULL * 1024 * 1024 * 1024 * 1024 * 1024), expected: "1.0 EB");
684
685 check_string (str: g_format_size (size: 0), expected: "0 bytes");
686 check_string (str: g_format_size (size: 1), expected: "1 byte");
687 check_string (str: g_format_size (size: 2), expected: "2 bytes");
688 /* '\302\240' is a no-break space, to keep quantity and unit symbol together at line breaks*/
689 check_string (str: g_format_size (size: 1000ULL), expected: "1.0\302\240kB");
690 check_string (str: g_format_size (size: 1000ULL * 1000), expected: "1.0\302\240MB");
691 check_string (str: g_format_size (size: 1000ULL * 1000 * 1000), expected: "1.0\302\240GB");
692 check_string (str: g_format_size (size: 1000ULL * 1000 * 1000 * 1000), expected: "1.0\302\240TB");
693 check_string (str: g_format_size (size: 1000ULL * 1000 * 1000 * 1000 * 1000), expected: "1.0\302\240PB");
694 check_string (str: g_format_size (size: 1000ULL * 1000 * 1000 * 1000 * 1000 * 1000), expected: "1.0\302\240EB");
695
696 check_string (str: g_format_size_full (size: 0, flags: G_FORMAT_SIZE_IEC_UNITS), expected: "0 bytes");
697 check_string (str: g_format_size_full (size: 1, flags: G_FORMAT_SIZE_IEC_UNITS), expected: "1 byte");
698 check_string (str: g_format_size_full (size: 2, flags: G_FORMAT_SIZE_IEC_UNITS), expected: "2 bytes");
699
700 check_string (str: g_format_size_full (size: 2048ULL, flags: G_FORMAT_SIZE_IEC_UNITS), expected: "2.0\302\240KiB");
701 check_string (str: g_format_size_full (size: 2048ULL * 1024, flags: G_FORMAT_SIZE_IEC_UNITS), expected: "2.0\302\240MiB");
702 check_string (str: g_format_size_full (size: 2048ULL * 1024 * 1024, flags: G_FORMAT_SIZE_IEC_UNITS), expected: "2.0\302\240GiB");
703 check_string (str: g_format_size_full (size: 2048ULL * 1024 * 1024 * 1024, flags: G_FORMAT_SIZE_IEC_UNITS), expected: "2.0\302\240TiB");
704 check_string (str: g_format_size_full (size: 2048ULL * 1024 * 1024 * 1024 * 1024, flags: G_FORMAT_SIZE_IEC_UNITS), expected: "2.0\302\240PiB");
705 check_string (str: g_format_size_full (size: 2048ULL * 1024 * 1024 * 1024 * 1024 * 1024, flags: G_FORMAT_SIZE_IEC_UNITS), expected: "2.0\302\240EiB");
706
707 check_string (str: g_format_size_full (size: 238472938, flags: G_FORMAT_SIZE_IEC_UNITS), expected: "227.4\302\240MiB");
708 check_string (str: g_format_size_full (size: 238472938, flags: G_FORMAT_SIZE_DEFAULT), expected: "238.5\302\240MB");
709 check_string (str: g_format_size_full (size: 238472938, flags: G_FORMAT_SIZE_LONG_FORMAT), expected: "238.5\302\240MB (238472938 bytes)");
710
711
712 check_string (str: g_format_size_full (size: 0, flags: G_FORMAT_SIZE_BITS), expected: "0 bits");
713 check_string (str: g_format_size_full (size: 1, flags: G_FORMAT_SIZE_BITS), expected: "1 bit");
714 check_string (str: g_format_size_full (size: 2, flags: G_FORMAT_SIZE_BITS), expected: "2 bits");
715
716 check_string (str: g_format_size_full (size: 2000ULL, flags: G_FORMAT_SIZE_BITS), expected: "2.0\302\240kb");
717 check_string (str: g_format_size_full (size: 2000ULL * 1000, flags: G_FORMAT_SIZE_BITS), expected: "2.0\302\240Mb");
718 check_string (str: g_format_size_full (size: 2000ULL * 1000 * 1000, flags: G_FORMAT_SIZE_BITS), expected: "2.0\302\240Gb");
719 check_string (str: g_format_size_full (size: 2000ULL * 1000 * 1000 * 1000, flags: G_FORMAT_SIZE_BITS), expected: "2.0\302\240Tb");
720 check_string (str: g_format_size_full (size: 2000ULL * 1000 * 1000 * 1000 * 1000, flags: G_FORMAT_SIZE_BITS), expected: "2.0\302\240Pb");
721 check_string (str: g_format_size_full (size: 2000ULL * 1000 * 1000 * 1000 * 1000 * 1000, flags: G_FORMAT_SIZE_BITS), expected: "2.0\302\240Eb");
722
723 check_string (str: g_format_size_full (size: 238472938, flags: G_FORMAT_SIZE_BITS), expected: "238.5\302\240Mb");
724 check_string (str: g_format_size_full (size: 238472938, flags: G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_LONG_FORMAT), expected: "238.5\302\240Mb (238472938 bits)");
725
726
727 check_string (str: g_format_size_full (size: 0, flags: G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), expected: "0 bits");
728 check_string (str: g_format_size_full (size: 1, flags: G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), expected: "1 bit");
729 check_string (str: g_format_size_full (size: 2, flags: G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), expected: "2 bits");
730
731 check_string (str: g_format_size_full (size: 2048ULL, flags: G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), expected: "2.0\302\240Kib");
732 check_string (str: g_format_size_full (size: 2048ULL * 1024, flags: G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), expected: "2.0\302\240Mib");
733 check_string (str: g_format_size_full (size: 2048ULL * 1024 * 1024, flags: G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), expected: "2.0\302\240Gib");
734 check_string (str: g_format_size_full (size: 2048ULL * 1024 * 1024 * 1024, flags: G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), expected: "2.0\302\240Tib");
735 check_string (str: g_format_size_full (size: 2048ULL * 1024 * 1024 * 1024 * 1024, flags: G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), expected: "2.0\302\240Pib");
736 check_string (str: g_format_size_full (size: 2048ULL * 1024 * 1024 * 1024 * 1024 * 1024, flags: G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), expected: "2.0\302\240Eib");
737
738 check_string (str: g_format_size_full (size: 238472938, flags: G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), expected: "227.4\302\240Mib");
739 check_string (str: g_format_size_full (size: 238472938, flags: G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_LONG_FORMAT), expected: "227.4\302\240Mib (238472938 bits)");
740}
741
742static void
743test_file_errors (void)
744{
745#ifdef EEXIST
746 g_assert_cmpint (g_file_error_from_errno (EEXIST), ==, G_FILE_ERROR_EXIST);
747#endif
748#ifdef EISDIR
749 g_assert_cmpint (g_file_error_from_errno (EISDIR), ==, G_FILE_ERROR_ISDIR);
750#endif
751#ifdef EACCES
752 g_assert_cmpint (g_file_error_from_errno (EACCES), ==, G_FILE_ERROR_ACCES);
753#endif
754#ifdef ENAMETOOLONG
755 g_assert_cmpint (g_file_error_from_errno (ENAMETOOLONG), ==, G_FILE_ERROR_NAMETOOLONG);
756#endif
757#ifdef ENOENT
758 g_assert_cmpint (g_file_error_from_errno (ENOENT), ==, G_FILE_ERROR_NOENT);
759#endif
760#ifdef ENOTDIR
761 g_assert_cmpint (g_file_error_from_errno (ENOTDIR), ==, G_FILE_ERROR_NOTDIR);
762#endif
763#ifdef ENXIO
764 g_assert_cmpint (g_file_error_from_errno (ENXIO), ==, G_FILE_ERROR_NXIO);
765#endif
766#ifdef ENODEV
767 g_assert_cmpint (g_file_error_from_errno (ENODEV), ==, G_FILE_ERROR_NODEV);
768#endif
769#ifdef EROFS
770 g_assert_cmpint (g_file_error_from_errno (EROFS), ==, G_FILE_ERROR_ROFS);
771#endif
772#ifdef ETXTBSY
773 g_assert_cmpint (g_file_error_from_errno (ETXTBSY), ==, G_FILE_ERROR_TXTBSY);
774#endif
775#ifdef EFAULT
776 g_assert_cmpint (g_file_error_from_errno (EFAULT), ==, G_FILE_ERROR_FAULT);
777#endif
778#ifdef ELOOP
779 g_assert_cmpint (g_file_error_from_errno (ELOOP), ==, G_FILE_ERROR_LOOP);
780#endif
781#ifdef ENOSPC
782 g_assert_cmpint (g_file_error_from_errno (ENOSPC), ==, G_FILE_ERROR_NOSPC);
783#endif
784#ifdef ENOMEM
785 g_assert_cmpint (g_file_error_from_errno (ENOMEM), ==, G_FILE_ERROR_NOMEM);
786#endif
787#ifdef EMFILE
788 g_assert_cmpint (g_file_error_from_errno (EMFILE), ==, G_FILE_ERROR_MFILE);
789#endif
790#ifdef ENFILE
791 g_assert_cmpint (g_file_error_from_errno (ENFILE), ==, G_FILE_ERROR_NFILE);
792#endif
793#ifdef EBADF
794 g_assert_cmpint (g_file_error_from_errno (EBADF), ==, G_FILE_ERROR_BADF);
795#endif
796#ifdef EINVAL
797 g_assert_cmpint (g_file_error_from_errno (EINVAL), ==, G_FILE_ERROR_INVAL);
798#endif
799#ifdef EPIPE
800 g_assert_cmpint (g_file_error_from_errno (EPIPE), ==, G_FILE_ERROR_PIPE);
801#endif
802#ifdef EAGAIN
803 g_assert_cmpint (g_file_error_from_errno (EAGAIN), ==, G_FILE_ERROR_AGAIN);
804#endif
805#ifdef EINTR
806 g_assert_cmpint (g_file_error_from_errno (EINTR), ==, G_FILE_ERROR_INTR);
807#endif
808#ifdef EIO
809 g_assert_cmpint (g_file_error_from_errno (EIO), ==, G_FILE_ERROR_IO);
810#endif
811#ifdef EPERM
812 g_assert_cmpint (g_file_error_from_errno (EPERM), ==, G_FILE_ERROR_PERM);
813#endif
814#ifdef ENOSYS
815 g_assert_cmpint (g_file_error_from_errno (ENOSYS), ==, G_FILE_ERROR_NOSYS);
816#endif
817}
818
819static void
820test_basename (void)
821{
822 gchar *b;
823
824 b = g_path_get_basename (file_name: "");
825 g_assert_cmpstr (b, ==, ".");
826 g_free (mem: b);
827
828 b = g_path_get_basename (file_name: "///");
829 g_assert_cmpstr (b, ==, G_DIR_SEPARATOR_S);
830 g_free (mem: b);
831
832 b = g_path_get_basename (file_name: "/a/b/c/d");
833 g_assert_cmpstr (b, ==, "d");
834 g_free (mem: b);
835}
836
837static void
838test_dir_make_tmp (void)
839{
840 gchar *name;
841 GError *error = NULL;
842 gint ret;
843
844 name = g_dir_make_tmp (tmpl: "testXXXXXXtest", error: &error);
845 g_assert_no_error (error);
846 g_assert_true (g_file_test (name, G_FILE_TEST_IS_DIR));
847 ret = g_rmdir (filename: name);
848 g_assert_cmpint (ret, ==, 0);
849 g_free (mem: name);
850
851 name = g_dir_make_tmp (NULL, error: &error);
852 g_assert_no_error (error);
853 g_assert_true (g_file_test (name, G_FILE_TEST_IS_DIR));
854 ret = g_rmdir (filename: name);
855 g_assert_cmpint (ret, ==, 0);
856 g_free (mem: name);
857
858 name = g_dir_make_tmp (tmpl: "test/XXXXXX", error: &error);
859 g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED);
860 g_clear_error (err: &error);
861 g_assert_null (name);
862
863 name = g_dir_make_tmp (tmpl: "XXXXxX", error: &error);
864 g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED);
865 g_clear_error (err: &error);
866 g_assert_null (name);
867}
868
869static void
870test_file_open_tmp (void)
871{
872 gchar *name = NULL;
873 GError *error = NULL;
874 gint fd;
875
876 fd = g_file_open_tmp (tmpl: "testXXXXXXtest", name_used: &name, error: &error);
877 g_assert_cmpint (fd, !=, -1);
878 g_assert_no_error (error);
879 g_assert_nonnull (name);
880 unlink (name: name);
881 g_free (mem: name);
882 close (fd: fd);
883
884 fd = g_file_open_tmp (NULL, name_used: &name, error: &error);
885 g_assert_cmpint (fd, !=, -1);
886 g_assert_no_error (error);
887 g_assert_nonnull (name);
888 g_unlink (filename: name);
889 g_free (mem: name);
890 close (fd: fd);
891
892 name = NULL;
893 fd = g_file_open_tmp (tmpl: "test/XXXXXX", name_used: &name, error: &error);
894 g_assert_cmpint (fd, ==, -1);
895 g_assert_null (name);
896 g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED);
897 g_clear_error (err: &error);
898
899 fd = g_file_open_tmp (tmpl: "XXXXxX", name_used: &name, error: &error);
900 g_assert_cmpint (fd, ==, -1);
901 g_assert_null (name);
902 g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED);
903 g_clear_error (err: &error);
904}
905
906static void
907test_mkstemp (void)
908{
909 gchar *name;
910 gint fd;
911
912 name = g_strdup (str: "testXXXXXXtest"),
913 fd = g_mkstemp (tmpl: name);
914 g_assert_cmpint (fd, !=, -1);
915 g_assert_null (strstr (name, "XXXXXX"));
916 unlink (name: name);
917 close (fd: fd);
918 g_free (mem: name);
919
920 name = g_strdup (str: "testYYYYYYtest"),
921 fd = g_mkstemp (tmpl: name);
922 g_assert_cmpint (fd, ==, -1);
923 g_free (mem: name);
924}
925
926static void
927test_mkdtemp (void)
928{
929 gchar *name;
930 gchar *ret;
931
932 name = g_strdup (str: "testXXXXXXtest"),
933 ret = g_mkdtemp (tmpl: name);
934 g_assert (ret == name);
935 g_assert_null (strstr (name, "XXXXXX"));
936 g_rmdir (filename: name);
937 g_free (mem: name);
938
939 name = g_strdup (str: "testYYYYYYtest"),
940 ret = g_mkdtemp (tmpl: name);
941 g_assert_null (ret);
942 g_free (mem: name);
943}
944
945static void
946test_set_contents (void)
947{
948 GError *error = NULL;
949 gint fd;
950 gchar *name;
951 gchar *buf;
952 gsize len;
953 gboolean ret;
954
955 fd = g_file_open_tmp (NULL, name_used: &name, error: &error);
956 g_assert_no_error (error);
957 write (fd: fd, buf: "a", n: 1);
958 g_assert_cmpint (g_fsync (fd), ==, 0);
959 close (fd: fd);
960
961 ret = g_file_get_contents (filename: name, contents: &buf, length: &len, error: &error);
962 g_assert_true (ret);
963 g_assert_no_error (error);
964 g_assert_cmpstr (buf, ==, "a");
965 g_free (mem: buf);
966
967 ret = g_file_set_contents (filename: name, contents: "b", length: 1, error: &error);
968 g_assert_true (ret);
969 g_assert_no_error (error);
970
971 ret = g_file_get_contents (filename: name, contents: &buf, length: &len, error: &error);
972 g_assert_true (ret);
973 g_assert_no_error (error);
974 g_assert_cmpstr (buf, ==, "b");
975 g_free (mem: buf);
976
977 g_remove (filename: name);
978 g_free (mem: name);
979}
980
981static void
982test_set_contents_full (void)
983{
984 GFileSetContentsFlags flags_mask =
985 G_FILE_SET_CONTENTS_ONLY_EXISTING |
986 G_FILE_SET_CONTENTS_DURABLE |
987 G_FILE_SET_CONTENTS_CONSISTENT;
988 gint flags;
989 const struct
990 {
991 enum
992 {
993 EXISTING_FILE_NONE,
994 EXISTING_FILE_REGULAR,
995#ifndef G_OS_WIN32
996 EXISTING_FILE_SYMLINK,
997#endif
998 EXISTING_FILE_DIRECTORY,
999 }
1000 existing_file;
1001 int new_mode; /* only relevant if @existing_file is %EXISTING_FILE_NONE */
1002 gboolean use_strlen;
1003
1004 gboolean expected_success;
1005 gint expected_error;
1006 }
1007 tests[] =
1008 {
1009 { EXISTING_FILE_NONE, 0644, FALSE, TRUE, 0 },
1010 { EXISTING_FILE_NONE, 0644, TRUE, TRUE, 0 },
1011 { EXISTING_FILE_NONE, 0600, FALSE, TRUE, 0 },
1012 { EXISTING_FILE_REGULAR, 0644, FALSE, TRUE, 0 },
1013#ifndef G_OS_WIN32
1014 { EXISTING_FILE_SYMLINK, 0644, FALSE, TRUE, 0 },
1015#endif
1016 { EXISTING_FILE_DIRECTORY, 0644, FALSE, FALSE, G_FILE_ERROR_ISDIR },
1017 };
1018 gsize i;
1019
1020 g_test_summary (summary: "Test g_file_set_contents_full() with various flags");
1021
1022 for (flags = 0; flags < (gint) flags_mask; flags++)
1023 {
1024 for (i = 0; i < G_N_ELEMENTS (tests); i++)
1025 {
1026 GError *error = NULL;
1027 gchar *file_name = NULL, *link_name = NULL, *dir_name = NULL;
1028 const gchar *set_contents_name;
1029 gchar *buf = NULL;
1030 gsize len;
1031 gboolean ret;
1032 GStatBuf statbuf;
1033
1034 g_test_message (format: "Flags %d and test %" G_GSIZE_FORMAT, flags, i);
1035
1036 switch (tests[i].existing_file)
1037 {
1038 case EXISTING_FILE_REGULAR:
1039#ifndef G_OS_WIN32
1040 case EXISTING_FILE_SYMLINK:
1041#endif
1042 {
1043 gint fd;
1044
1045 fd = g_file_open_tmp (NULL, name_used: &file_name, error: &error);
1046 g_assert_no_error (error);
1047 write (fd: fd, buf: "a", n: 1);
1048 g_assert_no_errno (g_fsync (fd));
1049 close (fd: fd);
1050
1051#ifndef G_OS_WIN32
1052 /* Pass an existing symlink to g_file_set_contents_full() to see
1053 * what it does. */
1054 if (tests[i].existing_file == EXISTING_FILE_SYMLINK)
1055 {
1056 link_name = g_strconcat (string1: file_name, ".link", NULL);
1057 g_assert_no_errno (symlink (file_name, link_name));
1058
1059 set_contents_name = link_name;
1060 }
1061 else
1062#endif /* !G_OS_WIN32 */
1063 {
1064 set_contents_name = file_name;
1065 }
1066 break;
1067 }
1068 case EXISTING_FILE_DIRECTORY:
1069 {
1070 dir_name = g_dir_make_tmp (tmpl: "glib-fileutils-set-contents-full-XXXXXX", error: &error);
1071 g_assert_no_error (error);
1072
1073 set_contents_name = dir_name;
1074 break;
1075 }
1076 case EXISTING_FILE_NONE:
1077 {
1078 file_name = g_build_filename (first_element: g_get_tmp_dir (), "glib-file-set-contents-full-test", NULL);
1079 g_remove (filename: file_name);
1080 g_assert_false (g_file_test (file_name, G_FILE_TEST_EXISTS));
1081
1082 set_contents_name = file_name;
1083 break;
1084 }
1085 default:
1086 {
1087 g_assert_not_reached ();
1088 }
1089 }
1090
1091 /* Set the file contents */
1092 ret = g_file_set_contents_full (filename: set_contents_name, contents: "b",
1093 length: tests[i].use_strlen ? -1 : 1,
1094 flags, mode: tests[i].new_mode, error: &error);
1095
1096 if (!tests[i].expected_success)
1097 {
1098 g_assert_error (error, G_FILE_ERROR, tests[i].expected_error);
1099 g_assert_false (ret);
1100 g_clear_error (err: &error);
1101 }
1102 else
1103 {
1104 g_assert_no_error (error);
1105 g_assert_true (ret);
1106
1107 /* Check the contents and mode were set correctly. The mode isn’t
1108 * changed on existing files. */
1109 ret = g_file_get_contents (filename: set_contents_name, contents: &buf, length: &len, error: &error);
1110 g_assert_no_error (error);
1111 g_assert_true (ret);
1112 g_assert_cmpstr (buf, ==, "b");
1113 g_assert_cmpuint (len, ==, 1);
1114 g_free (mem: buf);
1115
1116 g_assert_no_errno (g_lstat (set_contents_name, &statbuf));
1117
1118 if (tests[i].existing_file == EXISTING_FILE_NONE)
1119 g_assert_cmpint (statbuf.st_mode & ~S_IFMT, ==, tests[i].new_mode);
1120
1121#ifndef G_OS_WIN32
1122 if (tests[i].existing_file == EXISTING_FILE_SYMLINK)
1123 {
1124 gchar *target_contents = NULL;
1125
1126 /* If the @set_contents_name was a symlink, it should now be a
1127 * regular file, and the file it pointed to should not have
1128 * changed. */
1129 g_assert_cmpint (statbuf.st_mode & S_IFMT, ==, S_IFREG);
1130
1131 g_file_get_contents (filename: file_name, contents: &target_contents, NULL, error: &error);
1132 g_assert_no_error (error);
1133 g_assert_cmpstr (target_contents, ==, "a");
1134
1135 g_free (mem: target_contents);
1136 }
1137#endif /* !G_OS_WIN32 */
1138 }
1139
1140 if (dir_name != NULL)
1141 g_rmdir (filename: dir_name);
1142 if (link_name != NULL)
1143 g_remove (filename: link_name);
1144 if (file_name != NULL)
1145 g_remove (filename: file_name);
1146
1147 g_free (mem: dir_name);
1148 g_free (mem: link_name);
1149 g_free (mem: file_name);
1150 }
1151 }
1152}
1153
1154static void
1155test_set_contents_full_read_only_file (void)
1156{
1157 gint fd;
1158 GError *error = NULL;
1159 gchar *file_name = NULL;
1160 gboolean ret;
1161 gboolean can_override_dac = check_cap_dac_override (NULL);
1162
1163 g_test_summary (summary: "Test g_file_set_contents_full() on a read-only file");
1164
1165 /* Can’t test this with different #GFileSetContentsFlags as they all have
1166 * different behaviours wrt replacing the file while noticing/ignoring the
1167 * existing file permissions. */
1168 fd = g_file_open_tmp (NULL, name_used: &file_name, error: &error);
1169 g_assert_no_error (error);
1170 write (fd: fd, buf: "a", n: 1);
1171 g_assert_no_errno (g_fsync (fd));
1172 close (fd: fd);
1173 g_assert_no_errno (chmod (file_name, 0200));
1174
1175 /* Set the file contents */
1176 ret = g_file_set_contents_full (filename: file_name, contents: "b", length: 1, flags: G_FILE_SET_CONTENTS_NONE, mode: 0644, error: &error);
1177
1178 if (can_override_dac)
1179 {
1180 g_assert_no_error (error);
1181 g_assert_true (ret);
1182 }
1183 else
1184 {
1185 g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_ACCES);
1186 g_assert_false (ret);
1187 }
1188
1189 g_clear_error (err: &error);
1190
1191 g_remove (filename: file_name);
1192
1193 g_free (mem: file_name);
1194}
1195
1196static void
1197test_set_contents_full_read_only_directory (void)
1198{
1199 GFileSetContentsFlags flags_mask =
1200 G_FILE_SET_CONTENTS_ONLY_EXISTING |
1201 G_FILE_SET_CONTENTS_DURABLE |
1202 G_FILE_SET_CONTENTS_CONSISTENT;
1203 gint flags;
1204
1205 g_test_summary (summary: "Test g_file_set_contents_full() on a file in a read-only directory");
1206
1207 for (flags = 0; flags < (gint) flags_mask; flags++)
1208 {
1209 gint fd;
1210 GError *error = NULL;
1211 gchar *dir_name = NULL;
1212 gchar *file_name = NULL;
1213 gboolean ret;
1214 gboolean can_override_dac;
1215
1216 g_test_message (format: "Flags %d", flags);
1217
1218 dir_name = g_dir_make_tmp (tmpl: "glib-file-set-contents-full-rodir-XXXXXX", error: &error);
1219 g_assert_no_error (error);
1220 can_override_dac = check_cap_dac_override (tmpdir: dir_name);
1221
1222 file_name = g_build_filename (first_element: dir_name, "file", NULL);
1223 fd = g_open (filename: file_name, O_CREAT | O_RDWR, mode: 0644);
1224 g_assert_cmpint (fd, >=, 0);
1225 write (fd: fd, buf: "a", n: 1);
1226 g_assert_no_errno (g_fsync (fd));
1227 close (fd: fd);
1228
1229 g_assert_no_errno (chmod (dir_name, 0));
1230
1231 /* Set the file contents */
1232 ret = g_file_set_contents_full (filename: file_name, contents: "b", length: 1, flags, mode: 0644, error: &error);
1233
1234 if (can_override_dac)
1235 {
1236 g_assert_no_error (error);
1237 g_assert_true (ret);
1238 }
1239 else
1240 {
1241 g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_ACCES);
1242 g_assert_false (ret);
1243 }
1244
1245 g_clear_error (err: &error);
1246 g_remove (filename: file_name);
1247 g_unlink (filename: dir_name);
1248
1249 g_free (mem: file_name);
1250 g_free (mem: dir_name);
1251 }
1252}
1253
1254static void
1255test_read_link (void)
1256{
1257#ifdef HAVE_READLINK
1258#ifdef G_OS_UNIX
1259 int ret;
1260 const gchar *oldpath;
1261 gchar *cwd;
1262 gchar *newpath;
1263 gchar *badpath;
1264 gchar *path;
1265 GError *error = NULL;
1266
1267 cwd = g_get_current_dir ();
1268
1269 oldpath = g_test_get_filename (file_type: G_TEST_DIST, first_path: "4096-random-bytes", NULL);
1270 newpath = g_build_filename (first_element: cwd, "page-of-junk", NULL);
1271 badpath = g_build_filename (first_element: cwd, "4097-random-bytes", NULL);
1272 remove (filename: newpath);
1273 ret = symlink (from: oldpath, to: newpath);
1274 g_assert_cmpint (ret, ==, 0);
1275 path = g_file_read_link (filename: newpath, error: &error);
1276 g_assert_no_error (error);
1277 g_assert_cmpstr (path, ==, oldpath);
1278 g_free (mem: path);
1279
1280 remove (filename: newpath);
1281 ret = symlink (from: badpath, to: newpath);
1282 g_assert_cmpint (ret, ==, 0);
1283 path = g_file_read_link (filename: newpath, error: &error);
1284 g_assert_no_error (error);
1285 g_assert_cmpstr (path, ==, badpath);
1286 g_free (mem: path);
1287
1288 path = g_file_read_link (filename: oldpath, error: &error);
1289 g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL);
1290 g_assert_null (path);
1291 g_error_free (error);
1292
1293 remove (filename: newpath);
1294 g_free (mem: cwd);
1295 g_free (mem: newpath);
1296 g_free (mem: badpath);
1297
1298#endif
1299#else
1300 g_test_skip ("Symbolic links not supported");
1301#endif
1302}
1303
1304static void
1305test_stdio_wrappers (void)
1306{
1307 GStatBuf buf;
1308 gchar *cwd, *path;
1309 gint ret;
1310 struct utimbuf ut;
1311 GError *error = NULL;
1312 GStatBuf path_statbuf, cwd_statbuf;
1313 time_t now;
1314#ifdef G_OS_UNIX
1315 gboolean have_cap_dac_override;
1316#endif
1317
1318 g_remove (filename: "mkdir-test/test-create");
1319 ret = g_rmdir (filename: "mkdir-test");
1320 g_assert (ret == 0 || errno == ENOENT);
1321
1322 ret = g_stat (filename: "mkdir-test", buf: &buf);
1323 g_assert_cmpint (ret, ==, -1);
1324 ret = g_mkdir (filename: "mkdir-test", mode: 0666);
1325 g_assert_cmpint (ret, ==, 0);
1326 ret = g_stat (filename: "mkdir-test", buf: &buf);
1327 g_assert_cmpint (ret, ==, 0);
1328 g_assert_cmpint (S_ISDIR (buf.st_mode), !=, 0);
1329
1330 cwd = g_get_current_dir ();
1331 path = g_build_filename (first_element: cwd, "mkdir-test", NULL);
1332#ifdef G_OS_UNIX
1333 have_cap_dac_override = check_cap_dac_override (tmpdir: cwd);
1334#endif
1335 g_free (mem: cwd);
1336
1337 /* 0666 on directories means nothing to Windows, it only obeys ACLs.
1338 * It doesn't necessarily mean anything on Unix either: if we have
1339 * Linux CAP_DAC_OVERRIDE or equivalent (in particular if we're root),
1340 * then we ignore filesystem permissions. */
1341#ifdef G_OS_UNIX
1342 if (have_cap_dac_override)
1343 {
1344 g_test_message (format: "Cannot test g_chdir() failing with EACCES: we "
1345 "probably have CAP_DAC_OVERRIDE or equivalent");
1346 }
1347 else
1348 {
1349 ret = g_chdir (path);
1350 g_assert_cmpint (ret == 0 ? 0 : errno, ==, EACCES);
1351 g_assert_cmpint (ret, ==, -1);
1352 }
1353#else
1354 g_test_message ("Cannot test g_chdir() failing with EACCES: "
1355 "it's Unix-specific behaviour");
1356#endif
1357
1358 ret = g_chmod (filename: path, mode: 0777);
1359 g_assert_cmpint (ret, ==, 0);
1360 ret = g_chdir (path);
1361 g_assert_cmpint (ret, ==, 0);
1362 cwd = g_get_current_dir ();
1363 /* We essentially want to check that cwd == path, but we can’t compare the
1364 * paths directly since the tests might be running under a symlink (for
1365 * example, /tmp is sometimes a symlink). Compare the inode numbers instead. */
1366 g_assert_cmpint (g_stat (cwd, &cwd_statbuf), ==, 0);
1367 g_assert_cmpint (g_stat (path, &path_statbuf), ==, 0);
1368 g_assert_true (cwd_statbuf.st_dev == path_statbuf.st_dev &&
1369 cwd_statbuf.st_ino == path_statbuf.st_ino);
1370 g_free (mem: cwd);
1371 g_free (mem: path);
1372
1373 ret = g_creat (filename: "test-creat", G_TEST_DIR_MODE);
1374 g_close (fd: ret, error: &error);
1375 g_assert_no_error (error);
1376
1377 ret = g_access (filename: "test-creat", F_OK);
1378 g_assert_cmpint (ret, ==, 0);
1379
1380 ret = g_rename (oldfilename: "test-creat", newfilename: "test-create");
1381 g_assert_cmpint (ret, ==, 0);
1382
1383 ret = g_open (filename: "test-create", O_RDONLY, mode: 0666);
1384 g_close (fd: ret, error: &error);
1385 g_assert_no_error (error);
1386
1387#ifdef G_OS_WIN32
1388 /* On Windows the 5 permission bit results in a read-only file
1389 * that cannot be modified in any way (attribute changes included).
1390 * Remove the read-only attribute via chmod().
1391 */
1392 ret = g_chmod ("test-create", 0666);
1393 g_assert_cmpint (ret, ==, 0);
1394#endif
1395
1396 now = time (NULL);
1397
1398 ut.actime = ut.modtime = now;
1399 ret = g_utime (filename: "test-create", utb: &ut);
1400 g_assert_cmpint (ret, ==, 0);
1401
1402 ret = g_lstat (filename: "test-create", buf: &buf);
1403 g_assert_cmpint (ret, ==, 0);
1404 g_assert_cmpint (buf.st_atime, ==, now);
1405 g_assert_cmpint (buf.st_mtime, ==, now);
1406
1407 g_chdir (path: "..");
1408 g_remove (filename: "mkdir-test/test-create");
1409 g_rmdir (filename: "mkdir-test");
1410}
1411
1412/* Win32 does not support "wb+", but g_fopen() should automatically
1413 * translate this mode to its alias "w+b".
1414 * Also check various other file open modes for correct support across
1415 * platforms.
1416 * See: https://gitlab.gnome.org/GNOME/glib/merge_requests/119
1417 */
1418static void
1419test_fopen_modes (void)
1420{
1421 char *path = g_build_filename (first_element: "temp-fopen", NULL);
1422 gsize i;
1423 const gchar *modes[] =
1424 {
1425 "w",
1426 "r",
1427 "a",
1428 "w+",
1429 "r+",
1430 "a+",
1431 "wb",
1432 "rb",
1433 "ab",
1434 "w+b",
1435 "r+b",
1436 "a+b",
1437 "wb+",
1438 "rb+",
1439 "ab+"
1440 };
1441
1442 g_test_bug (bug_uri_snippet: "119");
1443
1444 if (g_file_test (filename: path, test: G_FILE_TEST_EXISTS))
1445 g_error ("failed, %s exists, cannot test g_fopen()", path);
1446
1447 for (i = 0; i < G_N_ELEMENTS (modes); i++)
1448 {
1449 FILE *f;
1450
1451 g_test_message (format: "Testing fopen() mode '%s'", modes[i]);
1452
1453 f = g_fopen (filename: path, mode: modes[i]);
1454 g_assert_nonnull (f);
1455 fclose (stream: f);
1456 }
1457
1458 g_remove (filename: path);
1459 g_free (mem: path);
1460}
1461
1462#ifdef G_OS_WIN32
1463#include "../gstdio-private.c"
1464
1465static int
1466g_wcscmp0 (const gunichar2 *str1,
1467 const gunichar2 *str2)
1468{
1469 if (!str1)
1470 return -(str1 != str2);
1471 if (!str2)
1472 return str1 != str2;
1473 return wcscmp (str1, str2);
1474}
1475
1476#define g_assert_cmpwcs(s1, cmp, s2, s1u8, s2u8) \
1477G_STMT_START { \
1478 const gunichar2 *__s1 = (s1), *__s2 = (s2); \
1479 if (g_wcscmp0 (__s1, __s2) cmp 0) ; else \
1480 g_assertion_message_cmpstr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
1481 #s1u8 " " #cmp " " #s2u8, s1u8, #cmp, s2u8); \
1482} G_STMT_END
1483
1484static void
1485test_win32_pathstrip (void)
1486{
1487 gunichar2 *buf;
1488 gsize i;
1489#define IDENTITY_TEST(x) { x, x, FALSE }
1490 struct
1491 {
1492 gunichar2 *in;
1493 gunichar2 *out;
1494 gboolean result;
1495 } testcases[] = {
1496 IDENTITY_TEST (L"\\\\?\\V"),
1497 IDENTITY_TEST (L"\\\\?\\Vo"),
1498 IDENTITY_TEST (L"\\\\?\\Volume{0700f3d3-6d24-11e3-8b2f-806e6f6e6963}\\"),
1499 IDENTITY_TEST (L"\\??\\V"),
1500 IDENTITY_TEST (L"\\??\\Vo"),
1501 IDENTITY_TEST (L"\\??\\Volume{0700f3d3-6d24-11e3-8b2f-806e6f6e6963}\\"),
1502 IDENTITY_TEST (L"\\\\?\\\x0441:\\"),
1503 IDENTITY_TEST (L"\\??\\\x0441:\\"),
1504 IDENTITY_TEST (L"a:\\"),
1505 IDENTITY_TEST (L"a:\\b\\c"),
1506 IDENTITY_TEST (L"x"),
1507#undef IDENTITY_TEST
1508 {
1509 L"\\\\?\\c:\\",
1510 L"c:\\",
1511 TRUE,
1512 },
1513 {
1514 L"\\\\?\\C:\\",
1515 L"C:\\",
1516 TRUE,
1517 },
1518 {
1519 L"\\\\?\\c:\\",
1520 L"c:\\",
1521 TRUE,
1522 },
1523 {
1524 L"\\\\?\\C:\\",
1525 L"C:\\",
1526 TRUE,
1527 },
1528 {
1529 L"\\\\?\\C:\\",
1530 L"C:\\",
1531 TRUE,
1532 },
1533 { 0, }
1534 };
1535
1536 for (i = 0; testcases[i].in; i++)
1537 {
1538 gsize str_len = wcslen (testcases[i].in) + 1;
1539 gchar *in_u8 = g_utf16_to_utf8 (testcases[i].in, -1, NULL, NULL, NULL);
1540 gchar *out_u8 = g_utf16_to_utf8 (testcases[i].out, -1, NULL, NULL, NULL);
1541
1542 g_assert_nonnull (in_u8);
1543 g_assert_nonnull (out_u8);
1544
1545 buf = g_new0 (gunichar2, str_len);
1546 memcpy (buf, testcases[i].in, str_len * sizeof (gunichar2));
1547 _g_win32_strip_extended_ntobjm_prefix (buf, &str_len);
1548 g_assert_cmpwcs (buf, ==, testcases[i].out, in_u8, out_u8);
1549 g_free (buf);
1550 g_free (in_u8);
1551 g_free (out_u8);
1552 }
1553 /* Check for correct behaviour on non-NUL-terminated strings */
1554 for (i = 0; testcases[i].in; i++)
1555 {
1556 gsize str_len = wcslen (testcases[i].in) + 1;
1557 wchar_t old_endchar;
1558 gchar *in_u8 = g_utf16_to_utf8 (testcases[i].in, -1, NULL, NULL, NULL);
1559 gchar *out_u8 = g_utf16_to_utf8 (testcases[i].out, -1, NULL, NULL, NULL);
1560
1561 g_assert_nonnull (in_u8);
1562 g_assert_nonnull (out_u8);
1563
1564 buf = g_new0 (gunichar2, str_len);
1565 memcpy (buf, testcases[i].in, (str_len) * sizeof (gunichar2));
1566
1567 old_endchar = buf[wcslen (testcases[i].out)];
1568 str_len -= 1;
1569
1570 if (testcases[i].result)
1571 {
1572 /* Given "\\\\?\\C:\\" (len 7, unterminated),
1573 * we should get "C:\\" (len 3, unterminated).
1574 * Put a character different from "\\" (4-th character of the buffer)
1575 * at the end of the unterminated source buffer, into a position
1576 * where NUL-terminator would normally be. Then later test that 4-th character
1577 * in the buffer is still the old "\\".
1578 * After that terminate the string and use normal g_wcscmp0().
1579 */
1580 buf[str_len] = old_endchar - 1;
1581 }
1582
1583 _g_win32_strip_extended_ntobjm_prefix (buf, &str_len);
1584 g_assert_cmpuint (old_endchar, ==, buf[wcslen (testcases[i].out)]);
1585 buf[str_len] = L'\0';
1586 g_assert_cmpwcs (buf, ==, testcases[i].out, in_u8, out_u8);
1587 g_free (buf);
1588 g_free (in_u8);
1589 g_free (out_u8);
1590 }
1591}
1592
1593#define g_assert_memcmp(m1, cmp, m2, memlen, m1hex, m2hex, testcase_num) \
1594G_STMT_START { \
1595 if (memcmp (m1, m2, memlen) cmp 0); else \
1596 g_assertion_message_cmpstr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
1597 #m1hex " " #cmp " " #m2hex, m1hex, #cmp, m2hex); \
1598} G_STMT_END
1599
1600static gchar *
1601to_hex (const guchar *buf,
1602 gsize len)
1603{
1604 gsize i;
1605 GString *s = g_string_new (NULL);
1606 if (len > 0)
1607 g_string_append_printf (s, "%02x", buf[0]);
1608 for (i = 1; i < len; i++)
1609 g_string_append_printf (s, " %02x", buf[i]);
1610 return g_string_free (s, FALSE);
1611}
1612
1613static void
1614test_win32_zero_terminate_symlink (void)
1615{
1616 gsize i;
1617#define TESTCASE(data, len_mod, use_buf, buf_size, terminate, reported_len, returned_string) \
1618 { (const guchar *) data, wcslen (data) * 2 + len_mod, use_buf, buf_size, terminate, reported_len, (guchar *) returned_string},
1619
1620 struct
1621 {
1622 const guchar *data;
1623 gsize data_size;
1624 gboolean use_buf;
1625 gsize buf_size;
1626 gboolean terminate;
1627 int reported_len;
1628 const guchar *returned_string;
1629 } testcases[] = {
1630 TESTCASE (L"foobar", +2, TRUE, 12 + 4, FALSE, 12 + 2, "f\0o\0o\0b\0a\0r\0\0\0")
1631 TESTCASE (L"foobar", +2, TRUE, 12 + 3, FALSE, 12 + 2, "f\0o\0o\0b\0a\0r\0\0\0")
1632 TESTCASE (L"foobar", +2, TRUE, 12 + 2, FALSE, 12 + 2, "f\0o\0o\0b\0a\0r\0\0\0")
1633 TESTCASE (L"foobar", +2, TRUE, 12 + 1, FALSE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
1634 TESTCASE (L"foobar", +2, TRUE, 12 + 0, FALSE, 12 + 0, "f\0o\0o\0b\0a\0r\0")
1635 TESTCASE (L"foobar", +2, TRUE, 12 - 1, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
1636 TESTCASE (L"foobar", +2, TRUE, 12 - 2, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
1637 TESTCASE (L"foobar", +2, TRUE, 12 - 3, FALSE, 12 - 3, "f\0o\0o\0b\0a")
1638 TESTCASE (L"foobar", +1, TRUE, 12 + 4, FALSE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
1639 TESTCASE (L"foobar", +1, TRUE, 12 + 3, FALSE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
1640 TESTCASE (L"foobar", +1, TRUE, 12 + 2, FALSE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
1641 TESTCASE (L"foobar", +1, TRUE, 12 + 1, FALSE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
1642 TESTCASE (L"foobar", +1, TRUE, 12 + 0, FALSE, 12 + 0, "f\0o\0o\0b\0a\0r\0")
1643 TESTCASE (L"foobar", +1, TRUE, 12 - 1, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
1644 TESTCASE (L"foobar", +1, TRUE, 12 - 2, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
1645 TESTCASE (L"foobar", +1, TRUE, 12 - 3, FALSE, 12 - 3, "f\0o\0o\0b\0a")
1646 TESTCASE (L"foobar", +0, TRUE, 12 + 4, FALSE, 12 + 0, "f\0o\0o\0b\0a\0r\0")
1647 TESTCASE (L"foobar", +0, TRUE, 12 + 3, FALSE, 12 + 0, "f\0o\0o\0b\0a\0r\0")
1648 TESTCASE (L"foobar", +0, TRUE, 12 + 2, FALSE, 12 + 0, "f\0o\0o\0b\0a\0r\0")
1649 TESTCASE (L"foobar", +0, TRUE, 12 + 1, FALSE, 12 + 0, "f\0o\0o\0b\0a\0r\0")
1650 TESTCASE (L"foobar", +0, TRUE, 12 + 0, FALSE, 12 + 0, "f\0o\0o\0b\0a\0r\0")
1651 TESTCASE (L"foobar", +0, TRUE, 12 - 1, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
1652 TESTCASE (L"foobar", +0, TRUE, 12 - 2, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
1653 TESTCASE (L"foobar", +0, TRUE, 12 - 3, FALSE, 12 - 3, "f\0o\0o\0b\0a")
1654 TESTCASE (L"foobar", -1, TRUE, 12 + 3, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
1655 TESTCASE (L"foobar", -1, TRUE, 12 + 2, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
1656 TESTCASE (L"foobar", -1, TRUE, 12 + 1, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
1657 TESTCASE (L"foobar", -1, TRUE, 12 + 0, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
1658 TESTCASE (L"foobar", -1, TRUE, 12 - 1, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
1659 TESTCASE (L"foobar", -1, TRUE, 12 - 2, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
1660 TESTCASE (L"foobar", -1, TRUE, 12 - 3, FALSE, 12 - 3, "f\0o\0o\0b\0a")
1661 TESTCASE (L"foobar", -1, TRUE, 12 - 4, FALSE, 12 - 4, "f\0o\0o\0b\0")
1662 TESTCASE (L"foobar", -2, TRUE, 12 + 2, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
1663 TESTCASE (L"foobar", -2, TRUE, 12 + 1, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
1664 TESTCASE (L"foobar", -2, TRUE, 12 + 0, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
1665 TESTCASE (L"foobar", -2, TRUE, 12 - 1, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
1666 TESTCASE (L"foobar", -2, TRUE, 12 - 2, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
1667 TESTCASE (L"foobar", -2, TRUE, 12 - 3, FALSE, 12 - 3, "f\0o\0o\0b\0a")
1668 TESTCASE (L"foobar", -2, TRUE, 12 - 4, FALSE, 12 - 4, "f\0o\0o\0b\0")
1669 TESTCASE (L"foobar", -2, TRUE, 12 - 5, FALSE, 12 - 5, "f\0o\0o\0b")
1670 TESTCASE (L"foobar", +2, TRUE, 12 + 4, TRUE, 12 + 2, "f\0o\0o\0b\0a\0r\0\0\0")
1671 TESTCASE (L"foobar", +2, TRUE, 12 + 3, TRUE, 12 + 2, "f\0o\0o\0b\0a\0r\0\0\0")
1672 TESTCASE (L"foobar", +2, TRUE, 12 + 2, TRUE, 12 + 2, "f\0o\0o\0b\0a\0r\0\0\0")
1673 TESTCASE (L"foobar", +2, TRUE, 12 + 1, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
1674 TESTCASE (L"foobar", +2, TRUE, 12 + 0, TRUE, 12 + 0, "f\0o\0o\0b\0a\0\0\0")
1675 TESTCASE (L"foobar", +2, TRUE, 12 - 1, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
1676 TESTCASE (L"foobar", +2, TRUE, 12 - 2, TRUE, 12 - 2, "f\0o\0o\0b\0\0\0")
1677 TESTCASE (L"foobar", +2, TRUE, 12 - 3, TRUE, 12 - 3, "f\0o\0o\0b\0\0")
1678 TESTCASE (L"foobar", +1, TRUE, 12 + 4, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
1679 TESTCASE (L"foobar", +1, TRUE, 12 + 3, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
1680 TESTCASE (L"foobar", +1, TRUE, 12 + 2, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
1681 TESTCASE (L"foobar", +1, TRUE, 12 + 1, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
1682 TESTCASE (L"foobar", +1, TRUE, 12 + 0, TRUE, 12 + 0, "f\0o\0o\0b\0a\0\0\0")
1683 TESTCASE (L"foobar", +1, TRUE, 12 - 1, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
1684 TESTCASE (L"foobar", +1, TRUE, 12 - 2, TRUE, 12 - 2, "f\0o\0o\0b\0\0\0")
1685 TESTCASE (L"foobar", +1, TRUE, 12 - 3, TRUE, 12 - 3, "f\0o\0o\0b\0\0")
1686 TESTCASE (L"foobar", +0, TRUE, 12 + 4, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
1687 TESTCASE (L"foobar", +0, TRUE, 12 + 3, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
1688 TESTCASE (L"foobar", +0, TRUE, 12 + 2, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
1689 TESTCASE (L"foobar", +0, TRUE, 12 + 1, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
1690 TESTCASE (L"foobar", +0, TRUE, 12 + 0, TRUE, 12 + 0, "f\0o\0o\0b\0a\0\0\0")
1691 TESTCASE (L"foobar", +0, TRUE, 12 - 1, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
1692 TESTCASE (L"foobar", +0, TRUE, 12 - 2, TRUE, 12 - 2, "f\0o\0o\0b\0\0\0")
1693 TESTCASE (L"foobar", +0, TRUE, 12 - 3, TRUE, 12 - 3, "f\0o\0o\0b\0\0")
1694 TESTCASE (L"foobar", -1, TRUE, 12 + 3, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
1695 TESTCASE (L"foobar", -1, TRUE, 12 + 2, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
1696 TESTCASE (L"foobar", -1, TRUE, 12 + 1, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
1697 TESTCASE (L"foobar", -1, TRUE, 12 + 0, TRUE, 12 + 0, "f\0o\0o\0b\0a\0\0\0")
1698 TESTCASE (L"foobar", -1, TRUE, 12 - 1, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
1699 TESTCASE (L"foobar", -1, TRUE, 12 - 2, TRUE, 12 - 2, "f\0o\0o\0b\0\0\0")
1700 TESTCASE (L"foobar", -1, TRUE, 12 - 3, TRUE, 12 - 3, "f\0o\0o\0b\0\0")
1701 TESTCASE (L"foobar", -1, TRUE, 12 - 4, TRUE, 12 - 4, "f\0o\0o\0\0\0")
1702 TESTCASE (L"foobar", -2, TRUE, 12 + 2, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
1703 TESTCASE (L"foobar", -2, TRUE, 12 + 1, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
1704 TESTCASE (L"foobar", -2, TRUE, 12 + 0, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
1705 TESTCASE (L"foobar", -2, TRUE, 12 - 1, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
1706 TESTCASE (L"foobar", -2, TRUE, 12 - 2, TRUE, 12 - 2, "f\0o\0o\0b\0\0\0")
1707 TESTCASE (L"foobar", -2, TRUE, 12 - 3, TRUE, 12 - 3, "f\0o\0o\0b\0\0")
1708 TESTCASE (L"foobar", -2, TRUE, 12 - 4, TRUE, 12 - 4, "f\0o\0o\0\0\0")
1709 TESTCASE (L"foobar", -2, TRUE, 12 - 5, TRUE, 12 - 5, "f\0o\0o\0\0")
1710 TESTCASE (L"foobar", +2, FALSE, 0, FALSE, 12 + 2, "f\0o\0o\0b\0a\0r\0\0\0")
1711 TESTCASE (L"foobar", +1, FALSE, 0, FALSE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
1712 TESTCASE (L"foobar", +0, FALSE, 0, FALSE, 12 + 0, "f\0o\0o\0b\0a\0r\0")
1713 TESTCASE (L"foobar", -1, FALSE, 0, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
1714 TESTCASE (L"foobar", -2, FALSE, 0, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
1715 TESTCASE (L"foobar", +2, FALSE, 0, TRUE, 12 + 2, "f\0o\0o\0b\0a\0r\0\0\0")
1716 TESTCASE (L"foobar", +1, FALSE, 0, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
1717 TESTCASE (L"foobar", +0, FALSE, 0, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
1718 TESTCASE (L"foobar", -1, FALSE, 0, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
1719 TESTCASE (L"foobar", -2, FALSE, 0, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
1720 TESTCASE (L"x", +2, TRUE, 2 + 4, FALSE, 2 + 2, "x\0\0\0")
1721 TESTCASE (L"x", +2, TRUE, 2 + 3, FALSE, 2 + 2, "x\0\0\0")
1722 TESTCASE (L"x", +2, TRUE, 2 + 2, FALSE, 2 + 2, "x\0\0\0")
1723 TESTCASE (L"x", +2, TRUE, 2 + 1, FALSE, 2 + 1, "x\0\0")
1724 TESTCASE (L"x", +2, TRUE, 2 + 0, FALSE, 2 + 0, "x\0")
1725 TESTCASE (L"x", +2, TRUE, 2 - 1, FALSE, 2 - 1, "x")
1726 TESTCASE (L"x", +2, TRUE, 2 - 2, FALSE, 2 - 2, "")
1727 TESTCASE (L"x", +1, TRUE, 2 + 3, FALSE, 2 + 1, "x\0\0")
1728 TESTCASE (L"x", +1, TRUE, 2 + 2, FALSE, 2 + 1, "x\0\0")
1729 TESTCASE (L"x", +1, TRUE, 2 + 1, FALSE, 2 + 1, "x\0\0")
1730 TESTCASE (L"x", +1, TRUE, 2 + 0, FALSE, 2 + 0, "x\0")
1731 TESTCASE (L"x", +1, TRUE, 2 - 1, FALSE, 2 - 1, "x")
1732 TESTCASE (L"x", +1, TRUE, 2 - 2, FALSE, 2 - 2, "")
1733 TESTCASE (L"x", +0, TRUE, 2 + 2, FALSE, 2 + 0, "x\0")
1734 TESTCASE (L"x", +0, TRUE, 2 + 1, FALSE, 2 + 0, "x\0")
1735 TESTCASE (L"x", +0, TRUE, 2 + 0, FALSE, 2 + 0, "x\0")
1736 TESTCASE (L"x", +0, TRUE, 2 - 1, FALSE, 2 - 1, "x")
1737 TESTCASE (L"x", +0, TRUE, 2 - 2, FALSE, 2 - 2, "")
1738 TESTCASE (L"x", -1, TRUE, 2 + 1, FALSE, 2 - 1, "x")
1739 TESTCASE (L"x", -1, TRUE, 2 + 0, FALSE, 2 - 1, "x")
1740 TESTCASE (L"x", -1, TRUE, 2 - 1, FALSE, 2 - 1, "x")
1741 TESTCASE (L"x", -1, TRUE, 2 - 2, FALSE, 2 - 2, "")
1742 TESTCASE (L"x", -2, TRUE, 2 + 0, FALSE, 2 - 2, "")
1743 TESTCASE (L"x", -2, TRUE, 2 - 1, FALSE, 2 - 2, "")
1744 TESTCASE (L"x", -2, TRUE, 2 - 2, FALSE, 2 - 2, "")
1745 TESTCASE (L"x", +2, TRUE, 2 + 4, TRUE, 2 + 2, "x\0\0\0")
1746 TESTCASE (L"x", +2, TRUE, 2 + 3, TRUE, 2 + 2, "x\0\0\0")
1747 TESTCASE (L"x", +2, TRUE, 2 + 2, TRUE, 2 + 2, "x\0\0\0")
1748 TESTCASE (L"x", +2, TRUE, 2 + 1, TRUE, 2 + 1, "x\0\0")
1749 TESTCASE (L"x", +2, TRUE, 2 + 0, TRUE, 2 + 0, "\0\0")
1750 TESTCASE (L"x", +2, TRUE, 2 - 1, TRUE, 2 - 1, "\0")
1751 TESTCASE (L"x", +2, TRUE, 2 - 2, TRUE, 2 - 2, "")
1752 TESTCASE (L"x", +1, TRUE, 2 + 3, TRUE, 2 + 1, "x\0\0")
1753 TESTCASE (L"x", +1, TRUE, 2 + 2, TRUE, 2 + 1, "x\0\0")
1754 TESTCASE (L"x", +1, TRUE, 2 + 1, TRUE, 2 + 1, "x\0\0")
1755 TESTCASE (L"x", +1, TRUE, 2 + 0, TRUE, 2 + 0, "\0\0")
1756 TESTCASE (L"x", +1, TRUE, 2 - 1, TRUE, 2 - 1, "\0")
1757 TESTCASE (L"x", +1, TRUE, 2 - 2, TRUE, 2 - 2, "")
1758 TESTCASE (L"x", +0, TRUE, 2 + 2, TRUE, 2 + 1, "x\0\0")
1759 TESTCASE (L"x", +0, TRUE, 2 + 1, TRUE, 2 + 1, "x\0\0")
1760 TESTCASE (L"x", +0, TRUE, 2 + 0, TRUE, 2 + 0, "\0\0")
1761 TESTCASE (L"x", +0, TRUE, 2 - 1, TRUE, 2 - 1, "\0")
1762 TESTCASE (L"x", +0, TRUE, 2 - 2, TRUE, 2 - 2, "")
1763 TESTCASE (L"x", -1, TRUE, 2 + 1, TRUE, 2 + 1, "x\0\0")
1764 TESTCASE (L"x", -1, TRUE, 2 + 0, TRUE, 2 + 0, "\0\0")
1765 TESTCASE (L"x", -1, TRUE, 2 - 1, TRUE, 2 - 1, "\0")
1766 TESTCASE (L"x", -1, TRUE, 2 - 2, TRUE, 2 - 2, "")
1767 TESTCASE (L"x", -2, TRUE, 2 + 0, TRUE, 2 - 2, "")
1768 TESTCASE (L"x", -2, TRUE, 2 - 1, TRUE, 2 - 2, "")
1769 TESTCASE (L"x", -2, TRUE, 2 - 2, TRUE, 2 - 2, "")
1770 TESTCASE (L"x", +2, FALSE, 0, FALSE, 2 + 2, "x\0\0\0")
1771 TESTCASE (L"x", +1, FALSE, 0, FALSE, 2 + 1, "x\0\0")
1772 TESTCASE (L"x", +0, FALSE, 0, FALSE, 2 + 0, "x\0")
1773 TESTCASE (L"x", -1, FALSE, 0, FALSE, 2 - 1, "x")
1774 TESTCASE (L"x", -2, FALSE, 0, FALSE, 2 - 2, "")
1775 TESTCASE (L"x", +2, FALSE, 0, TRUE, 2 + 2, "x\0\0\0")
1776 TESTCASE (L"x", +1, FALSE, 0, TRUE, 2 + 1, "x\0\0")
1777 TESTCASE (L"x", +0, FALSE, 0, TRUE, 2 + 1, "x\0\0")
1778 TESTCASE (L"x", -1, FALSE, 0, TRUE, 2 + 1, "x\0\0")
1779 TESTCASE (L"x", -2, FALSE, 0, TRUE, 2 - 2, "")
1780 { 0, },
1781 };
1782#undef TESTCASE
1783
1784 for (i = 0; testcases[i].data != NULL; i++)
1785 {
1786 gunichar2 *buf;
1787 int result;
1788 gchar *buf_hex, *expected_hex;
1789 if (testcases[i].use_buf)
1790 buf = g_malloc0 (testcases[i].buf_size + 1); /* +1 to ensure it succeeds with buf_size == 0 */
1791 else
1792 buf = NULL;
1793 result = _g_win32_copy_and_maybe_terminate (testcases[i].data,
1794 testcases[i].data_size,
1795 testcases[i].use_buf ? buf : NULL,
1796 testcases[i].buf_size,
1797 testcases[i].use_buf ? NULL : &buf,
1798 testcases[i].terminate);
1799 if (testcases[i].reported_len != result)
1800 g_error ("Test %" G_GSIZE_FORMAT " failed, result %d != %d", i, result, testcases[i].reported_len);
1801 if (buf == NULL && testcases[i].buf_size != 0)
1802 g_error ("Test %" G_GSIZE_FORMAT " failed, buf == NULL", i);
1803 g_assert_cmpint (testcases[i].reported_len, ==, result);
1804 if ((testcases[i].use_buf && testcases[i].buf_size != 0) ||
1805 (!testcases[i].use_buf && testcases[i].reported_len != 0))
1806 {
1807 g_assert_nonnull (buf);
1808 buf_hex = to_hex ((const guchar *) buf, result);
1809 expected_hex = to_hex (testcases[i].returned_string, testcases[i].reported_len);
1810 if (memcmp (buf, testcases[i].returned_string, result) != 0)
1811 g_error ("Test %" G_GSIZE_FORMAT " failed:\n%s !=\n%s", i, buf_hex, expected_hex);
1812 g_assert_memcmp (buf, ==, testcases[i].returned_string, testcases[i].reported_len, buf_hex, expected_hex, testcases[i].line);
1813 g_free (buf_hex);
1814 g_free (expected_hex);
1815 }
1816 g_free (buf);
1817 }
1818}
1819
1820#endif
1821
1822int
1823main (int argc,
1824 char *argv[])
1825{
1826 g_setenv (variable: "LC_ALL", value: "C", TRUE);
1827 g_test_init (argc: &argc, argv: &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL);
1828
1829 g_test_bug_base (uri_pattern: "https://gitlab.gnome.org/GNOME/glib/merge_requests/");
1830
1831#ifdef G_OS_WIN32
1832 g_test_add_func ("/fileutils/stdio-win32-pathstrip", test_win32_pathstrip);
1833 g_test_add_func ("/fileutils/stdio-win32-zero-terminate-symlink", test_win32_zero_terminate_symlink);
1834#endif
1835 g_test_add_func (testpath: "/fileutils/build-path", test_func: test_build_path);
1836 g_test_add_func (testpath: "/fileutils/build-pathv", test_func: test_build_pathv);
1837 g_test_add_func (testpath: "/fileutils/build-filename", test_func: test_build_filename);
1838 g_test_add_func (testpath: "/fileutils/build-filenamev", test_func: test_build_filenamev);
1839 g_test_add_func (testpath: "/fileutils/mkdir-with-parents", test_func: test_mkdir_with_parents);
1840 g_test_add_func (testpath: "/fileutils/mkdir-with-parents-permission", test_func: test_mkdir_with_parents_permission);
1841 g_test_add_func (testpath: "/fileutils/format-size-for-display", test_func: test_format_size_for_display);
1842 g_test_add_func (testpath: "/fileutils/errors", test_func: test_file_errors);
1843 g_test_add_func (testpath: "/fileutils/basename", test_func: test_basename);
1844 g_test_add_func (testpath: "/fileutils/dir-make-tmp", test_func: test_dir_make_tmp);
1845 g_test_add_func (testpath: "/fileutils/file-open-tmp", test_func: test_file_open_tmp);
1846 g_test_add_func (testpath: "/fileutils/mkstemp", test_func: test_mkstemp);
1847 g_test_add_func (testpath: "/fileutils/mkdtemp", test_func: test_mkdtemp);
1848 g_test_add_func (testpath: "/fileutils/set-contents", test_func: test_set_contents);
1849 g_test_add_func (testpath: "/fileutils/set-contents-full", test_func: test_set_contents_full);
1850 g_test_add_func (testpath: "/fileutils/set-contents-full/read-only-file", test_func: test_set_contents_full_read_only_file);
1851 g_test_add_func (testpath: "/fileutils/set-contents-full/read-only-directory", test_func: test_set_contents_full_read_only_directory);
1852 g_test_add_func (testpath: "/fileutils/read-link", test_func: test_read_link);
1853 g_test_add_func (testpath: "/fileutils/stdio-wrappers", test_func: test_stdio_wrappers);
1854 g_test_add_func (testpath: "/fileutils/fopen-modes", test_func: test_fopen_modes);
1855
1856 return g_test_run ();
1857}
1858

source code of gtk/subprojects/glib/glib/tests/fileutils.c