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