Branch data Line data Source code
1 : : /* Unit tests for gfileutils
2 : : * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 : : *
4 : : * SPDX-License-Identifier: LicenseRef-old-glib-tests
5 : : *
6 : : * This work is provided "as is"; redistribution and modification
7 : : * in whole or in part, in any medium, physical or electronic is
8 : : * permitted without restriction.
9 : : *
10 : : * This work is distributed in the hope that it will be useful,
11 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 : : *
14 : : * In no event shall the authors or contributors be liable for any
15 : : * direct, indirect, incidental, special, exemplary, or consequential
16 : : * damages (including, but not limited to, procurement of substitute
17 : : * goods or services; loss of use, data, or profits; or business
18 : : * interruption) however caused and on any theory of liability, whether
19 : : * in contract, strict liability, or tort (including negligence or
20 : : * otherwise) arising in any way out of the use of this software, even
21 : : * if advised of the possibility of such damage.
22 : : */
23 : :
24 : : #include "config.h"
25 : : #include <string.h>
26 : : #include <errno.h>
27 : :
28 : : /* We are testing some deprecated APIs here */
29 : : #ifndef GLIB_DISABLE_DEPRECATION_WARNINGS
30 : : #define GLIB_DISABLE_DEPRECATION_WARNINGS
31 : : #endif
32 : :
33 : : #include <glib.h>
34 : :
35 : : /* Test our stdio wrappers here; this disables redefining (e.g.) g_open() to open() */
36 : : #define G_STDIO_WRAP_ON_UNIX
37 : : #include <glib/gstdio.h>
38 : : #include "glib-private.h"
39 : :
40 : : #ifdef G_OS_UNIX
41 : : #include <unistd.h>
42 : : #include <sys/types.h>
43 : : #include <sys/stat.h>
44 : : #include <utime.h>
45 : :
46 : : #define G_TEST_DIR_MODE 0555
47 : : #endif
48 : : #include <fcntl.h>
49 : : #ifdef G_OS_WIN32
50 : : #include <windows.h>
51 : : #include <sys/utime.h>
52 : : #include <io.h>
53 : : #ifndef S_ISDIR
54 : : #define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR)
55 : : #endif
56 : : #ifndef F_OK
57 : : #define F_OK 0
58 : : #endif
59 : :
60 : : #define G_TEST_DIR_MODE (S_IWRITE | S_IREAD)
61 : : #endif
62 : :
63 : : #include "testutils.h"
64 : :
65 : : #define S G_DIR_SEPARATOR_S
66 : :
67 : : static void
68 : 228 : check_string (gchar *str, const gchar *expected)
69 : : {
70 : 228 : g_assert_nonnull (str);
71 : 228 : g_assert_cmpstr (str, ==, expected);
72 : 228 : g_free (str);
73 : 228 : }
74 : :
75 : : static void
76 : 1 : test_paths (void)
77 : : {
78 : : struct
79 : : {
80 : : gchar *filename;
81 : : gchar *dirname;
82 : 1 : } dirname_checks[] = {
83 : : { "/", "/" },
84 : : { "////", "/" },
85 : : { ".////", "." },
86 : : { "../", ".." },
87 : : { "..////", ".." },
88 : : { "a/b", "a" },
89 : : { "a/b/", "a/b" },
90 : : { "c///", "c" },
91 : : #ifdef G_OS_WIN32
92 : : { "\\", "\\" },
93 : : { ".\\\\\\\\", "." },
94 : : { "..\\", ".." },
95 : : { "..\\\\\\\\", ".." },
96 : : { "a\\b", "a" },
97 : : { "a\\b/", "a\\b" },
98 : : { "a/b\\", "a/b" },
99 : : { "c\\\\/", "c" },
100 : : { "//\\", "/" },
101 : : #endif
102 : : #ifdef G_WITH_CYGWIN
103 : : { "//server/share///x", "//server/share" },
104 : : #endif
105 : : { ".", "." },
106 : : { "..", "." },
107 : : { "", "." },
108 : : };
109 : 1 : const guint n_dirname_checks = G_N_ELEMENTS (dirname_checks);
110 : : struct
111 : : {
112 : : gchar *filename;
113 : : gchar *without_root;
114 : 1 : } skip_root_checks[] = {
115 : : { "/", "" },
116 : : { "//", "" },
117 : : { "/foo", "foo" },
118 : : { "//foo", "foo" },
119 : : { "a/b", NULL },
120 : : #ifdef G_OS_WIN32
121 : : { "\\", "" },
122 : : { "\\foo", "foo" },
123 : : { "\\\\server\\foo", "" },
124 : : { "\\\\server\\foo\\bar", "bar" },
125 : : { "a\\b", NULL },
126 : : #endif
127 : : #ifdef G_WITH_CYGWIN
128 : : { "//server/share///x", "//x" },
129 : : #endif
130 : : { ".", NULL },
131 : : { "", NULL },
132 : : };
133 : 1 : const guint n_skip_root_checks = G_N_ELEMENTS (skip_root_checks);
134 : : struct
135 : : {
136 : : gchar *cwd;
137 : : gchar *relative_path;
138 : : gchar *canonical_path;
139 : 1 : } canonicalize_filename_checks[] = {
140 : : #ifndef G_OS_WIN32
141 : : { "/etc", "../usr/share", "/usr/share" },
142 : : { "/", "/foo/bar", "/foo/bar" },
143 : : { "/usr/bin", "../../foo/bar", "/foo/bar" },
144 : : { "/", "../../foo/bar", "/foo/bar" },
145 : : { "/double//dash", "../../foo/bar", "/foo/bar" },
146 : : { "/usr/share/foo", ".././././bar", "/usr/share/bar" },
147 : : { "/foo/bar", "../bar/./.././bar", "/foo/bar" },
148 : : { "/test///dir", "../../././foo/bar", "/foo/bar" },
149 : : { "/test///dir", "../../././/foo///bar", "/foo/bar" },
150 : : { "/etc", "///triple/slash", "/triple/slash" },
151 : : { "/etc", "//double/slash", "//double/slash" },
152 : : { "///triple/slash", ".", "/triple/slash" },
153 : : { "//double/slash", ".", "//double/slash" },
154 : : { "/cwd/../with/./complexities/", "./hello", "/with/complexities/hello" },
155 : : { "/", ".dot-dir", "/.dot-dir" },
156 : : { "/cwd", "..", "/" },
157 : : { "/etc", "hello/..", "/etc" },
158 : : { "/etc", "hello/../", "/etc" },
159 : : { "/", "..", "/" },
160 : : { "/", "../", "/" },
161 : : { "/", "/..", "/" },
162 : : { "/", "/../", "/" },
163 : : { "/", ".", "/" },
164 : : { "/", "./", "/" },
165 : : { "/", "/.", "/" },
166 : : { "/", "/./", "/" },
167 : : { "/", "///usr/../usr", "/usr" },
168 : : #else
169 : : { "/etc", "../usr/share", "\\usr\\share" },
170 : : { "/", "/foo/bar", "\\foo\\bar" },
171 : : { "/usr/bin", "../../foo/bar", "\\foo\\bar" },
172 : : { "/", "../../foo/bar", "\\foo\\bar" },
173 : : { "/double//dash", "../../foo/bar", "\\foo\\bar" },
174 : : { "/usr/share/foo", ".././././bar", "\\usr\\share\\bar" },
175 : : { "/foo/bar", "../bar/./.././bar", "\\foo\\bar" },
176 : : { "/test///dir", "../../././foo/bar", "\\foo\\bar" },
177 : : { "/test///dir", "../../././/foo///bar", "\\foo\\bar" },
178 : : { "/etc", "///triple/slash", "\\triple\\slash" },
179 : : { "/etc", "//double/slash", "//double/slash" },
180 : : { "///triple/slash", ".", "\\triple\\slash" },
181 : : { "//double/slash", ".", "//double/slash\\" },
182 : : { "/cwd/../with/./complexities/", "./hello", "\\with\\complexities\\hello" },
183 : : { "/", ".dot-dir", "\\.dot-dir" },
184 : : { "/cwd", "..", "\\" },
185 : : { "/etc", "hello/..", "\\etc" },
186 : : { "/etc", "hello/../", "\\etc" },
187 : : { "/", "..", "\\" },
188 : : { "/", "../", "\\" },
189 : : { "/", "/..", "\\" },
190 : : { "/", "/../", "\\" },
191 : : { "/", ".", "\\" },
192 : : { "/", "./", "\\" },
193 : : { "/", "/.", "\\" },
194 : : { "/", "/./", "\\" },
195 : : { "/", "///usr/../usr", "\\usr" },
196 : :
197 : : { "\\etc", "..\\usr\\share", "\\usr\\share" },
198 : : { "\\", "\\foo\\bar", "\\foo\\bar" },
199 : : { "\\usr\\bin", "..\\..\\foo\\bar", "\\foo\\bar" },
200 : : { "\\", "..\\..\\foo\\bar", "\\foo\\bar" },
201 : : { "\\double\\\\dash", "..\\..\\foo\\bar", "\\foo\\bar" },
202 : : { "\\usr\\share\\foo", "..\\.\\.\\.\\bar", "\\usr\\share\\bar" },
203 : : { "\\foo\\bar", "..\\bar\\.\\..\\.\\bar", "\\foo\\bar" },
204 : : { "\\test\\\\\\dir", "..\\..\\.\\.\\foo\\bar", "\\foo\\bar" },
205 : : { "\\test\\\\\\dir", "..\\..\\.\\.\\\\foo\\\\\\bar", "\\foo\\bar" },
206 : : { "\\etc", "\\\\\\triple\\slash", "\\triple\\slash" },
207 : : { "\\etc", "\\\\double\\slash", "\\\\double\\slash" },
208 : : { "\\\\\\triple\\slash", ".", "\\triple\\slash" },
209 : : { "\\\\double\\slash", ".", "\\\\double\\slash\\" },
210 : : { "\\cwd\\..\\with\\.\\complexities\\", ".\\hello", "\\with\\complexities\\hello" },
211 : : { "\\", ".dot-dir", "\\.dot-dir" },
212 : : { "\\cwd", "..", "\\" },
213 : : { "\\etc", "hello\\..", "\\etc" },
214 : : { "\\etc", "hello\\..\\", "\\etc" },
215 : : { "\\", "..", "\\" },
216 : : { "\\", "..\\", "\\" },
217 : : { "\\", "\\..", "\\" },
218 : : { "\\", "\\..\\", "\\" },
219 : : { "\\", ".", "\\" },
220 : : { "\\", ".\\", "\\" },
221 : : { "\\", "\\.", "\\" },
222 : : { "\\", "\\.\\", "\\" },
223 : : { "\\", "\\\\\\usr\\..\\usr", "\\usr" },
224 : : #endif
225 : : };
226 : 1 : const guint n_canonicalize_filename_checks = G_N_ELEMENTS (canonicalize_filename_checks);
227 : : gchar *string;
228 : : guint i;
229 : :
230 : 1 : string = g_path_get_basename (G_DIR_SEPARATOR_S "foo" G_DIR_SEPARATOR_S "dir" G_DIR_SEPARATOR_S);
231 : 1 : g_assert_cmpstr (string, ==, "dir");
232 : 1 : g_free (string);
233 : 1 : string = g_path_get_basename (G_DIR_SEPARATOR_S "foo" G_DIR_SEPARATOR_S "file");
234 : 1 : g_assert_cmpstr (string, ==, "file");
235 : 1 : g_free (string);
236 : :
237 : : #ifdef G_OS_WIN32
238 : : string = g_path_get_basename ("/foo/dir/");
239 : : g_assert_cmpstr (string, ==, "dir");
240 : : g_free (string);
241 : : string = g_path_get_basename ("/foo/file");
242 : : g_assert_cmpstr (string, ==, "file");
243 : : g_free (string);
244 : : #endif
245 : :
246 [ + + ]: 12 : for (i = 0; i < n_dirname_checks; i++)
247 : : {
248 : 11 : gchar *dirname = g_path_get_dirname (dirname_checks[i].filename);
249 : 11 : g_assert_cmpstr (dirname, ==, dirname_checks[i].dirname);
250 : 11 : g_free (dirname);
251 : : }
252 : :
253 [ + + ]: 8 : for (i = 0; i < n_skip_root_checks; i++)
254 : : {
255 : 7 : const gchar *skipped = g_path_skip_root (skip_root_checks[i].filename);
256 [ + + + - : 7 : if ((skipped && !skip_root_checks[i].without_root) ||
+ + ]
257 [ + - + + ]: 7 : (!skipped && skip_root_checks[i].without_root) ||
258 [ + - ]: 4 : ((skipped && skip_root_checks[i].without_root) &&
259 [ - + ]: 4 : strcmp (skipped, skip_root_checks[i].without_root)))
260 : : {
261 [ # # # # ]: 0 : g_error ("failed for \"%s\"==\"%s\" (returned: \"%s\")",
262 : : skip_root_checks[i].filename,
263 : : (skip_root_checks[i].without_root ? skip_root_checks[i].without_root : "<NULL>"),
264 : : (skipped ? skipped : "<NULL>"));
265 : : }
266 : : }
267 : :
268 [ + + ]: 28 : for (i = 0; i < n_canonicalize_filename_checks; i++)
269 : : {
270 : : gchar *canonical_path =
271 : 27 : g_canonicalize_filename (canonicalize_filename_checks[i].relative_path,
272 : 27 : canonicalize_filename_checks[i].cwd);
273 : 27 : g_assert_cmpstr (canonical_path, ==,
274 : : canonicalize_filename_checks[i].canonical_path);
275 : 27 : g_free (canonical_path);
276 : : }
277 : :
278 : : {
279 : 1 : const gchar *relative_path = "./";
280 : 1 : gchar *canonical_path = g_canonicalize_filename (relative_path, NULL);
281 : 1 : gchar *cwd = g_get_current_dir ();
282 : 1 : g_assert_cmpstr (canonical_path, ==, cwd);
283 : 1 : g_free (cwd);
284 : 1 : g_free (canonical_path);
285 : : }
286 : 1 : }
287 : :
288 : : static void
289 : 1 : test_build_path (void)
290 : : {
291 [ + - ]: 1 : if (g_test_undefined ())
292 : : {
293 : 1 : g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
294 : : "*assertion*!= NULL*");
295 : 1 : g_assert_null (g_build_path (NULL, "x", "y", NULL));
296 : 1 : g_test_assert_expected_messages ();
297 : : }
298 : :
299 : : /* check_string (g_build_path ("", NULL), "");*/
300 : 1 : check_string (g_build_path ("", "", NULL), "");
301 : 1 : check_string (g_build_path ("", "x", NULL), "x");
302 : 1 : check_string (g_build_path ("", "x", "y", NULL), "xy");
303 : 1 : check_string (g_build_path ("", "x", "y", "z", NULL), "xyz");
304 : :
305 : : /* check_string (g_build_path (":", NULL), "");*/
306 : 1 : check_string (g_build_path (":", ":", NULL), ":");
307 : 1 : check_string (g_build_path (":", ":x", NULL), ":x");
308 : 1 : check_string (g_build_path (":", "x:", NULL), "x:");
309 : 1 : check_string (g_build_path (":", "", "x", NULL), "x");
310 : 1 : check_string (g_build_path (":", "", ":x", NULL), ":x");
311 : 1 : check_string (g_build_path (":", ":", "x", NULL), ":x");
312 : 1 : check_string (g_build_path (":", "::", "x", NULL), "::x");
313 : 1 : check_string (g_build_path (":", "x", "", NULL), "x");
314 : 1 : check_string (g_build_path (":", "x:", "", NULL), "x:");
315 : 1 : check_string (g_build_path (":", "x", ":", NULL), "x:");
316 : 1 : check_string (g_build_path (":", "x", "::", NULL), "x::");
317 : 1 : check_string (g_build_path (":", "x", "y", NULL), "x:y");
318 : 1 : check_string (g_build_path (":", ":x", "y", NULL), ":x:y");
319 : 1 : check_string (g_build_path (":", "x", "y:", NULL), "x:y:");
320 : 1 : check_string (g_build_path (":", ":x:", ":y:", NULL), ":x:y:");
321 : 1 : check_string (g_build_path (":", ":x::", "::y:", NULL), ":x:y:");
322 : 1 : check_string (g_build_path (":", "x", "","y", NULL), "x:y");
323 : 1 : check_string (g_build_path (":", "x", ":", "y", NULL), "x:y");
324 : 1 : check_string (g_build_path (":", "x", "::", "y", NULL), "x:y");
325 : 1 : check_string (g_build_path (":", "x", "y", "z", NULL), "x:y:z");
326 : 1 : check_string (g_build_path (":", ":x:", ":y:", ":z:", NULL), ":x:y:z:");
327 : 1 : check_string (g_build_path (":", "::x::", "::y::", "::z::", NULL), "::x:y:z::");
328 : :
329 : : /* check_string (g_build_path ("::", NULL), "");*/
330 : 1 : check_string (g_build_path ("::", "::", NULL), "::");
331 : 1 : check_string (g_build_path ("::", ":::", NULL), ":::");
332 : 1 : check_string (g_build_path ("::", "::x", NULL), "::x");
333 : 1 : check_string (g_build_path ("::", "x::", NULL), "x::");
334 : 1 : check_string (g_build_path ("::", "", "x", NULL), "x");
335 : 1 : check_string (g_build_path ("::", "", "::x", NULL), "::x");
336 : 1 : check_string (g_build_path ("::", "::", "x", NULL), "::x");
337 : 1 : check_string (g_build_path ("::", "::::", "x", NULL), "::::x");
338 : 1 : check_string (g_build_path ("::", "x", "", NULL), "x");
339 : 1 : check_string (g_build_path ("::", "x::", "", NULL), "x::");
340 : 1 : check_string (g_build_path ("::", "x", "::", NULL), "x::");
341 : :
342 : : /* This following is weird, but keeps the definition simple */
343 : 1 : check_string (g_build_path ("::", "x", ":::", NULL), "x:::::");
344 : 1 : check_string (g_build_path ("::", "x", "::::", NULL), "x::::");
345 : 1 : check_string (g_build_path ("::", "x", "y", NULL), "x::y");
346 : 1 : check_string (g_build_path ("::", "::x", "y", NULL), "::x::y");
347 : 1 : check_string (g_build_path ("::", "x", "y::", NULL), "x::y::");
348 : 1 : check_string (g_build_path ("::", "::x::", "::y::", NULL), "::x::y::");
349 : 1 : check_string (g_build_path ("::", "::x:::", ":::y::", NULL), "::x::::y::");
350 : 1 : check_string (g_build_path ("::", "::x::::", "::::y::", NULL), "::x::y::");
351 : 1 : check_string (g_build_path ("::", "x", "", "y", NULL), "x::y");
352 : 1 : check_string (g_build_path ("::", "x", "::", "y", NULL), "x::y");
353 : 1 : check_string (g_build_path ("::", "x", "::::", "y", NULL), "x::y");
354 : 1 : check_string (g_build_path ("::", "x", "y", "z", NULL), "x::y::z");
355 : 1 : check_string (g_build_path ("::", "::x::", "::y::", "::z::", NULL), "::x::y::z::");
356 : 1 : check_string (g_build_path ("::", ":::x:::", ":::y:::", ":::z:::", NULL), ":::x::::y::::z:::");
357 : 1 : check_string (g_build_path ("::", "::::x::::", "::::y::::", "::::z::::", NULL), "::::x::y::z::::");
358 : 1 : }
359 : :
360 : : static void
361 : 1 : test_build_pathv (void)
362 : : {
363 : : gchar *args[10];
364 : :
365 : 1 : g_assert_null (g_build_pathv ("", NULL));
366 : 1 : args[0] = NULL;
367 : 1 : check_string (g_build_pathv ("", args), "");
368 : 1 : args[0] = ""; args[1] = NULL;
369 : 1 : check_string (g_build_pathv ("", args), "");
370 : 1 : args[0] = "x"; args[1] = NULL;
371 : 1 : check_string (g_build_pathv ("", args), "x");
372 : 1 : args[0] = "x"; args[1] = "y"; args[2] = NULL;
373 : 1 : check_string (g_build_pathv ("", args), "xy");
374 : 1 : args[0] = "x"; args[1] = "y"; args[2] = "z", args[3] = NULL;
375 : 1 : check_string (g_build_pathv ("", args), "xyz");
376 : :
377 : 1 : args[0] = NULL;
378 : 1 : check_string (g_build_pathv (":", args), "");
379 : 1 : args[0] = ":"; args[1] = NULL;
380 : 1 : check_string (g_build_pathv (":", args), ":");
381 : 1 : args[0] = ":x"; args[1] = NULL;
382 : 1 : check_string (g_build_pathv (":", args), ":x");
383 : 1 : args[0] = "x:"; args[1] = NULL;
384 : 1 : check_string (g_build_pathv (":", args), "x:");
385 : 1 : args[0] = ""; args[1] = "x"; args[2] = NULL;
386 : 1 : check_string (g_build_pathv (":", args), "x");
387 : 1 : args[0] = ""; args[1] = ":x"; args[2] = NULL;
388 : 1 : check_string (g_build_pathv (":", args), ":x");
389 : 1 : args[0] = ":"; args[1] = "x"; args[2] = NULL;
390 : 1 : check_string (g_build_pathv (":", args), ":x");
391 : 1 : args[0] = "::"; args[1] = "x"; args[2] = NULL;
392 : 1 : check_string (g_build_pathv (":", args), "::x");
393 : 1 : args[0] = "x"; args[1] = ""; args[2] = NULL;
394 : 1 : check_string (g_build_pathv (":", args), "x");
395 : 1 : args[0] = "x:"; args[1] = ""; args[2] = NULL;
396 : 1 : check_string (g_build_pathv (":", args), "x:");
397 : 1 : args[0] = "x"; args[1] = ":"; args[2] = NULL;
398 : 1 : check_string (g_build_pathv (":", args), "x:");
399 : 1 : args[0] = "x"; args[1] = "::"; args[2] = NULL;
400 : 1 : check_string (g_build_pathv (":", args), "x::");
401 : 1 : args[0] = "x"; args[1] = "y"; args[2] = NULL;
402 : 1 : check_string (g_build_pathv (":", args), "x:y");
403 : 1 : args[0] = ":x"; args[1] = "y"; args[2] = NULL;
404 : 1 : check_string (g_build_pathv (":", args), ":x:y");
405 : 1 : args[0] = "x"; args[1] = "y:"; args[2] = NULL;
406 : 1 : check_string (g_build_pathv (":", args), "x:y:");
407 : 1 : args[0] = ":x:"; args[1] = ":y:"; args[2] = NULL;
408 : 1 : check_string (g_build_pathv (":", args), ":x:y:");
409 : 1 : args[0] = ":x::"; args[1] = "::y:"; args[2] = NULL;
410 : 1 : check_string (g_build_pathv (":", args), ":x:y:");
411 : 1 : args[0] = "x"; args[1] = ""; args[2] = "y"; args[3] = NULL;
412 : 1 : check_string (g_build_pathv (":", args), "x:y");
413 : 1 : args[0] = "x"; args[1] = ":"; args[2] = "y"; args[3] = NULL;
414 : 1 : check_string (g_build_pathv (":", args), "x:y");
415 : 1 : args[0] = "x"; args[1] = "::"; args[2] = "y"; args[3] = NULL;
416 : 1 : check_string (g_build_pathv (":", args), "x:y");
417 : 1 : args[0] = "x"; args[1] = "y"; args[2] = "z"; args[3] = NULL;
418 : 1 : check_string (g_build_pathv (":", args), "x:y:z");
419 : 1 : args[0] = ":x:"; args[1] = ":y:"; args[2] = ":z:"; args[3] = NULL;
420 : 1 : check_string (g_build_pathv (":", args), ":x:y:z:");
421 : 1 : args[0] = "::x::"; args[1] = "::y::"; args[2] = "::z::"; args[3] = NULL;
422 : 1 : check_string (g_build_pathv (":", args), "::x:y:z::");
423 : :
424 : 1 : args[0] = NULL;
425 : 1 : check_string (g_build_pathv ("::", args), "");
426 : 1 : args[0] = "::"; args[1] = NULL;
427 : 1 : check_string (g_build_pathv ("::", args), "::");
428 : 1 : args[0] = ":::"; args[1] = NULL;
429 : 1 : check_string (g_build_pathv ("::", args), ":::");
430 : 1 : args[0] = "::x"; args[1] = NULL;
431 : 1 : check_string (g_build_pathv ("::", args), "::x");
432 : 1 : args[0] = "x::"; args[1] = NULL;
433 : 1 : check_string (g_build_pathv ("::", args), "x::");
434 : 1 : args[0] = ""; args[1] = "x"; args[2] = NULL;
435 : 1 : check_string (g_build_pathv ("::", args), "x");
436 : 1 : args[0] = ""; args[1] = "::x"; args[2] = NULL;
437 : 1 : check_string (g_build_pathv ("::", args), "::x");
438 : 1 : args[0] = "::"; args[1] = "x"; args[2] = NULL;
439 : 1 : check_string (g_build_pathv ("::", args), "::x");
440 : 1 : args[0] = "::::"; args[1] = "x"; args[2] = NULL;
441 : 1 : check_string (g_build_pathv ("::", args), "::::x");
442 : 1 : args[0] = "x"; args[1] = ""; args[2] = NULL;
443 : 1 : check_string (g_build_pathv ("::", args), "x");
444 : 1 : args[0] = "x::"; args[1] = ""; args[2] = NULL;
445 : 1 : check_string (g_build_pathv ("::", args), "x::");
446 : 1 : args[0] = "x"; args[1] = "::"; args[2] = NULL;
447 : 1 : check_string (g_build_pathv ("::", args), "x::");
448 : : /* This following is weird, but keeps the definition simple */
449 : 1 : args[0] = "x"; args[1] = ":::"; args[2] = NULL;
450 : 1 : check_string (g_build_pathv ("::", args), "x:::::");
451 : 1 : args[0] = "x"; args[1] = "::::"; args[2] = NULL;
452 : 1 : check_string (g_build_pathv ("::", args), "x::::");
453 : 1 : args[0] = "x"; args[1] = "y"; args[2] = NULL;
454 : 1 : check_string (g_build_pathv ("::", args), "x::y");
455 : 1 : args[0] = "::x"; args[1] = "y"; args[2] = NULL;
456 : 1 : check_string (g_build_pathv ("::", args), "::x::y");
457 : 1 : args[0] = "x"; args[1] = "y::"; args[2] = NULL;
458 : 1 : check_string (g_build_pathv ("::", args), "x::y::");
459 : 1 : args[0] = "::x::"; args[1] = "::y::"; args[2] = NULL;
460 : 1 : check_string (g_build_pathv ("::", args), "::x::y::");
461 : 1 : args[0] = "::x:::"; args[1] = ":::y::"; args[2] = NULL;
462 : 1 : check_string (g_build_pathv ("::", args), "::x::::y::");
463 : 1 : args[0] = "::x::::"; args[1] = "::::y::"; args[2] = NULL;
464 : 1 : check_string (g_build_pathv ("::", args), "::x::y::");
465 : 1 : args[0] = "x"; args[1] = ""; args[2] = "y"; args[3] = NULL;
466 : 1 : check_string (g_build_pathv ("::", args), "x::y");
467 : 1 : args[0] = "x"; args[1] = "::"; args[2] = "y"; args[3] = NULL;
468 : 1 : check_string (g_build_pathv ("::", args), "x::y");
469 : 1 : args[0] = "x"; args[1] = "::::"; args[2] = "y"; args[3] = NULL;
470 : 1 : check_string (g_build_pathv ("::", args), "x::y");
471 : 1 : args[0] = "x"; args[1] = "y"; args[2] = "z"; args[3] = NULL;
472 : 1 : check_string (g_build_pathv ("::", args), "x::y::z");
473 : 1 : args[0] = "::x::"; args[1] = "::y::"; args[2] = "::z::"; args[3] = NULL;
474 : 1 : check_string (g_build_pathv ("::", args), "::x::y::z::");
475 : 1 : args[0] = ":::x:::"; args[1] = ":::y:::"; args[2] = ":::z:::"; args[3] = NULL;
476 : 1 : check_string (g_build_pathv ("::", args), ":::x::::y::::z:::");
477 : 1 : args[0] = "::::x::::"; args[1] = "::::y::::"; args[2] = "::::z::::"; args[3] = NULL;
478 : 1 : check_string (g_build_pathv ("::", args), "::::x::y::z::::");
479 : 1 : }
480 : :
481 : : static void
482 : 1 : test_build_filename (void)
483 : : {
484 : 1 : check_string (g_build_filename (S, NULL), S);
485 : 1 : check_string (g_build_filename (S"x", NULL), S"x");
486 : 1 : check_string (g_build_filename ("x"S, NULL), "x"S);
487 : 1 : check_string (g_build_filename ("", "x", NULL), "x");
488 : 1 : check_string (g_build_filename ("", S"x", NULL), S"x");
489 : 1 : check_string (g_build_filename (S, "x", NULL), S"x");
490 : 1 : check_string (g_build_filename (S S, "x", NULL), S S"x");
491 : 1 : check_string (g_build_filename ("x", "", NULL), "x");
492 : 1 : check_string (g_build_filename ("x"S, "", NULL), "x"S);
493 : 1 : check_string (g_build_filename ("x", S, NULL), "x"S);
494 : 1 : check_string (g_build_filename ("x", S S, NULL), "x"S S);
495 : 1 : check_string (g_build_filename ("x", "y", NULL), "x"S"y");
496 : 1 : check_string (g_build_filename (S"x", "y", NULL), S"x"S"y");
497 : 1 : check_string (g_build_filename ("x", "y"S, NULL), "x"S"y"S);
498 : 1 : check_string (g_build_filename (S"x"S, S"y"S, NULL), S"x"S"y"S);
499 : 1 : check_string (g_build_filename (S"x"S S, S S"y"S, NULL), S"x"S"y"S);
500 : 1 : check_string (g_build_filename ("x", "", "y", NULL), "x"S"y");
501 : 1 : check_string (g_build_filename ("x", S, "y", NULL), "x"S"y");
502 : 1 : check_string (g_build_filename ("x", S S, "y", NULL), "x"S"y");
503 : 1 : check_string (g_build_filename ("x", "y", "z", NULL), "x"S"y"S"z");
504 : 1 : check_string (g_build_filename (S"x"S, S"y"S, S"z"S, NULL), S"x"S"y"S"z"S);
505 : 1 : 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);
506 : :
507 : : #ifdef G_OS_WIN32
508 : :
509 : : /* Test also using the slash as file name separator */
510 : : #define Z "/"
511 : : /* check_string (g_build_filename (NULL), ""); */
512 : : check_string (g_build_filename (Z, NULL), Z);
513 : : check_string (g_build_filename (Z"x", NULL), Z"x");
514 : : check_string (g_build_filename ("x"Z, NULL), "x"Z);
515 : : check_string (g_build_filename ("", Z"x", NULL), Z"x");
516 : : check_string (g_build_filename ("", Z"x", NULL), Z"x");
517 : : check_string (g_build_filename (Z, "x", NULL), Z"x");
518 : : check_string (g_build_filename (Z Z, "x", NULL), Z Z"x");
519 : : check_string (g_build_filename (Z S, "x", NULL), Z S"x");
520 : : check_string (g_build_filename ("x"Z, "", NULL), "x"Z);
521 : : check_string (g_build_filename ("x"S"y", "z"Z"a", NULL), "x"S"y"S"z"Z"a");
522 : : check_string (g_build_filename ("x", Z, NULL), "x"Z);
523 : : check_string (g_build_filename ("x", Z Z, NULL), "x"Z Z);
524 : : check_string (g_build_filename ("x", S Z, NULL), "x"S Z);
525 : : check_string (g_build_filename (Z"x", "y", NULL), Z"x"Z"y");
526 : : check_string (g_build_filename ("x", "y"Z, NULL), "x"Z"y"Z);
527 : : check_string (g_build_filename (Z"x"Z, Z"y"Z, NULL), Z"x"Z"y"Z);
528 : : check_string (g_build_filename (Z"x"Z Z, Z Z"y"Z, NULL), Z"x"Z"y"Z);
529 : : check_string (g_build_filename ("x", Z, "y", NULL), "x"Z"y");
530 : : check_string (g_build_filename ("x", Z Z, "y", NULL), "x"Z"y");
531 : : check_string (g_build_filename ("x", Z S, "y", NULL), "x"S"y");
532 : : check_string (g_build_filename ("x", S Z, "y", NULL), "x"Z"y");
533 : : check_string (g_build_filename ("x", Z "y", "z", NULL), "x"Z"y"Z"z");
534 : : check_string (g_build_filename ("x", S "y", "z", NULL), "x"S"y"S"z");
535 : : check_string (g_build_filename ("x", S "y", "z", Z, "a", "b", NULL), "x"S"y"S"z"Z"a"Z"b");
536 : : check_string (g_build_filename (Z"x"Z, Z"y"Z, Z"z"Z, NULL), Z"x"Z"y"Z"z"Z);
537 : : 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);
538 : :
539 : : #undef Z
540 : :
541 : : #endif /* G_OS_WIN32 */
542 : :
543 : 1 : }
544 : :
545 : : static void
546 : 1 : test_build_filenamev (void)
547 : : {
548 : : gchar *args[10];
549 : :
550 : 1 : args[0] = NULL;
551 : 1 : check_string (g_build_filenamev (args), "");
552 : 1 : args[0] = S; args[1] = NULL;
553 : 1 : check_string (g_build_filenamev (args), S);
554 : 1 : args[0] = S"x"; args[1] = NULL;
555 : 1 : check_string (g_build_filenamev (args), S"x");
556 : 1 : args[0] = "x"S; args[1] = NULL;
557 : 1 : check_string (g_build_filenamev (args), "x"S);
558 : 1 : args[0] = ""; args[1] = "x"; args[2] = NULL;
559 : 1 : check_string (g_build_filenamev (args), "x");
560 : 1 : args[0] = ""; args[1] = S"x"; args[2] = NULL;
561 : 1 : check_string (g_build_filenamev (args), S"x");
562 : 1 : args[0] = S; args[1] = "x"; args[2] = NULL;
563 : 1 : check_string (g_build_filenamev (args), S"x");
564 : 1 : args[0] = S S; args[1] = "x"; args[2] = NULL;
565 : 1 : check_string (g_build_filenamev (args), S S"x");
566 : 1 : args[0] = "x"; args[1] = ""; args[2] = NULL;
567 : 1 : check_string (g_build_filenamev (args), "x");
568 : 1 : args[0] = "x"S; args[1] = ""; args[2] = NULL;
569 : 1 : check_string (g_build_filenamev (args), "x"S);
570 : 1 : args[0] = "x"; args[1] = S; args[2] = NULL;
571 : 1 : check_string (g_build_filenamev (args), "x"S);
572 : 1 : args[0] = "x"; args[1] = S S; args[2] = NULL;
573 : 1 : check_string (g_build_filenamev (args), "x"S S);
574 : 1 : args[0] = "x"; args[1] = "y"; args[2] = NULL;
575 : 1 : check_string (g_build_filenamev (args), "x"S"y");
576 : 1 : args[0] = S"x"; args[1] = "y"; args[2] = NULL;
577 : 1 : check_string (g_build_filenamev (args), S"x"S"y");
578 : 1 : args[0] = "x"; args[1] = "y"S; args[2] = NULL;
579 : 1 : check_string (g_build_filenamev (args), "x"S"y"S);
580 : 1 : args[0] = S"x"S; args[1] = S"y"S; args[2] = NULL;
581 : 1 : check_string (g_build_filenamev (args), S"x"S"y"S);
582 : 1 : args[0] = S"x"S S; args[1] = S S"y"S; args[2] = NULL;
583 : 1 : check_string (g_build_filenamev (args), S"x"S"y"S);
584 : 1 : args[0] = "x"; args[1] = ""; args[2] = "y"; args[3] = NULL;
585 : 1 : check_string (g_build_filenamev (args), "x"S"y");
586 : 1 : args[0] = "x"; args[1] = S; args[2] = "y"; args[3] = NULL;
587 : 1 : check_string (g_build_filenamev (args), "x"S"y");
588 : 1 : args[0] = "x"; args[1] = S S; args[2] = "y"; args[3] = NULL;
589 : 1 : check_string (g_build_filenamev (args), "x"S"y");
590 : 1 : args[0] = "x"; args[1] = "y"; args[2] = "z"; args[3] = NULL;
591 : 1 : check_string (g_build_filenamev (args), "x"S"y"S"z");
592 : 1 : args[0] = S"x"S; args[1] = S"y"S; args[2] = S"z"S; args[3] = NULL;
593 : 1 : check_string (g_build_filenamev (args), S"x"S"y"S"z"S);
594 : 1 : args[0] = S S"x"S S; args[1] = S S"y"S S; args[2] = S S"z"S S; args[3] = NULL;
595 : 1 : check_string (g_build_filenamev (args), S S"x"S"y"S"z"S S);
596 : :
597 : : #ifdef G_OS_WIN32
598 : :
599 : : /* Test also using the slash as file name separator */
600 : : #define Z "/"
601 : : args[0] = NULL;
602 : : check_string (g_build_filenamev (args), "");
603 : : args[0] = Z; args[1] = NULL;
604 : : check_string (g_build_filenamev (args), Z);
605 : : args[0] = Z"x"; args[1] = NULL;
606 : : check_string (g_build_filenamev (args), Z"x");
607 : : args[0] = "x"Z; args[1] = NULL;
608 : : check_string (g_build_filenamev (args), "x"Z);
609 : : args[0] = ""; args[1] = Z"x"; args[2] = NULL;
610 : : check_string (g_build_filenamev (args), Z"x");
611 : : args[0] = ""; args[1] = Z"x"; args[2] = NULL;
612 : : check_string (g_build_filenamev (args), Z"x");
613 : : args[0] = Z; args[1] = "x"; args[2] = NULL;
614 : : check_string (g_build_filenamev (args), Z"x");
615 : : args[0] = Z Z; args[1] = "x"; args[2] = NULL;
616 : : check_string (g_build_filenamev (args), Z Z"x");
617 : : args[0] = Z S; args[1] = "x"; args[2] = NULL;
618 : : check_string (g_build_filenamev (args), Z S"x");
619 : : args[0] = "x"Z; args[1] = ""; args[2] = NULL;
620 : : check_string (g_build_filenamev (args), "x"Z);
621 : : args[0] = "x"S"y"; args[1] = "z"Z"a"; args[2] = NULL;
622 : : check_string (g_build_filenamev (args), "x"S"y"S"z"Z"a");
623 : : args[0] = "x"; args[1] = Z; args[2] = NULL;
624 : : check_string (g_build_filenamev (args), "x"Z);
625 : : args[0] = "x"; args[1] = Z Z; args[2] = NULL;
626 : : check_string (g_build_filenamev (args), "x"Z Z);
627 : : args[0] = "x"; args[1] = S Z; args[2] = NULL;
628 : : check_string (g_build_filenamev (args), "x"S Z);
629 : : args[0] = Z"x"; args[1] = "y"; args[2] = NULL;
630 : : check_string (g_build_filenamev (args), Z"x"Z"y");
631 : : args[0] = "x"; args[1] = "y"Z; args[2] = NULL;
632 : : check_string (g_build_filenamev (args), "x"Z"y"Z);
633 : : args[0] = Z"x"Z; args[1] = Z"y"Z; args[2] = NULL;
634 : : check_string (g_build_filenamev (args), Z"x"Z"y"Z);
635 : : args[0] = Z"x"Z Z; args[1] = Z Z"y"Z; args[2] = NULL;
636 : : check_string (g_build_filenamev (args), Z"x"Z"y"Z);
637 : : args[0] = "x"; args[1] = Z; args[2] = "y", args[3] = NULL;
638 : : check_string (g_build_filenamev (args), "x"Z"y");
639 : : args[0] = "x"; args[1] = Z Z; args[2] = "y", args[3] = NULL;
640 : : check_string (g_build_filenamev (args), "x"Z"y");
641 : : args[0] = "x"; args[1] = Z S; args[2] = "y", args[3] = NULL;
642 : : check_string (g_build_filenamev (args), "x"S"y");
643 : : args[0] = "x"; args[1] = S Z; args[2] = "y", args[3] = NULL;
644 : : check_string (g_build_filenamev (args), "x"Z"y");
645 : : args[0] = "x"; args[1] = Z "y"; args[2] = "z", args[3] = NULL;
646 : : check_string (g_build_filenamev (args), "x"Z"y"Z"z");
647 : : args[0] = "x"; args[1] = S "y"; args[2] = "z", args[3] = NULL;
648 : : check_string (g_build_filenamev (args), "x"S"y"S"z");
649 : : args[0] = "x"; args[1] = S "y"; args[2] = "z", args[3] = Z;
650 : : args[4] = "a"; args[5] = "b"; args[6] = NULL;
651 : : check_string (g_build_filenamev (args), "x"S"y"S"z"Z"a"Z"b");
652 : : args[0] = Z"x"Z; args[1] = Z"y"Z; args[2] = Z"z"Z, args[3] = NULL;
653 : : check_string (g_build_filenamev (args), Z"x"Z"y"Z"z"Z);
654 : : args[0] = Z Z"x"Z Z; args[1] = Z Z"y"Z Z; args[2] = Z Z"z"Z Z, args[3] = NULL;
655 : : check_string (g_build_filenamev (args), Z Z"x"Z"y"Z"z"Z Z);
656 : :
657 : : #undef Z
658 : :
659 : : #endif /* G_OS_WIN32 */
660 : 1 : }
661 : :
662 : : #undef S
663 : :
664 : : static void
665 : 3 : test_mkdir_with_parents_1 (const gchar *base)
666 : : {
667 : 3 : char *p0 = g_build_filename (base, "fum", NULL);
668 : 3 : char *p1 = g_build_filename (p0, "tem", NULL);
669 : 3 : char *p2 = g_build_filename (p1, "zap", NULL);
670 : : FILE *f;
671 : :
672 : 3 : g_remove (p2);
673 : 3 : g_remove (p1);
674 : 3 : g_remove (p0);
675 : :
676 [ - + ]: 3 : if (g_file_test (p0, G_FILE_TEST_EXISTS))
677 : 0 : g_error ("failed, %s exists, cannot test g_mkdir_with_parents", p0);
678 : :
679 [ - + ]: 3 : if (g_file_test (p1, G_FILE_TEST_EXISTS))
680 : 0 : g_error ("failed, %s exists, cannot test g_mkdir_with_parents", p1);
681 : :
682 [ - + ]: 3 : if (g_file_test (p2, G_FILE_TEST_EXISTS))
683 : 0 : g_error ("failed, %s exists, cannot test g_mkdir_with_parents", p2);
684 : :
685 [ - + ]: 3 : if (g_mkdir_with_parents (p2, 0777) == -1)
686 : : {
687 : 0 : int errsv = errno;
688 : 0 : g_error ("failed, g_mkdir_with_parents(%s) failed: %s", p2, g_strerror (errsv));
689 : : }
690 : :
691 [ - + ]: 3 : if (!g_file_test (p2, G_FILE_TEST_IS_DIR))
692 : 0 : g_error ("failed, g_mkdir_with_parents(%s) succeeded, but %s is not a directory", p2, p2);
693 : :
694 [ - + ]: 3 : if (!g_file_test (p1, G_FILE_TEST_IS_DIR))
695 : 0 : g_error ("failed, g_mkdir_with_parents(%s) succeeded, but %s is not a directory", p2, p1);
696 : :
697 [ - + ]: 3 : if (!g_file_test (p0, G_FILE_TEST_IS_DIR))
698 : 0 : g_error ("failed, g_mkdir_with_parents(%s) succeeded, but %s is not a directory", p2, p0);
699 : :
700 : 3 : g_rmdir (p2);
701 [ - + ]: 3 : if (g_file_test (p2, G_FILE_TEST_EXISTS))
702 : 0 : g_error ("failed, did g_rmdir(%s), but %s is still there", p2, p2);
703 : :
704 : 3 : g_rmdir (p1);
705 [ - + ]: 3 : if (g_file_test (p1, G_FILE_TEST_EXISTS))
706 : 0 : g_error ("failed, did g_rmdir(%s), but %s is still there", p1, p1);
707 : :
708 : 3 : f = g_fopen (p1, "w");
709 [ - + ]: 3 : if (f == NULL)
710 : 0 : g_error ("failed, couldn't create file %s", p1);
711 : 3 : fclose (f);
712 : :
713 [ - + ]: 3 : if (g_mkdir_with_parents (p1, 0666) == 0)
714 : 0 : g_error ("failed, g_mkdir_with_parents(%s) succeeded, even if %s is a file", p1, p1);
715 : :
716 [ - + ]: 3 : if (g_mkdir_with_parents (p2, 0666) == 0)
717 : 0 : g_error("failed, g_mkdir_with_parents(%s) succeeded, even if %s is a file", p2, p1);
718 : :
719 : 3 : g_remove (p2);
720 : 3 : g_remove (p1);
721 : 3 : g_remove (p0);
722 : :
723 : 3 : g_free (p2);
724 : 3 : g_free (p1);
725 : 3 : g_free (p0);
726 : 3 : }
727 : :
728 : : /*
729 : : * check_cap_dac_override:
730 : : * @tmpdir: (nullable): A temporary directory in which we can create
731 : : * and delete files. If %NULL, use the g_get_tmp_dir(), safely.
732 : : *
733 : : * Check whether the current process can bypass DAC permissions.
734 : : *
735 : : * Traditionally, "privileged" processes (those with effective uid 0)
736 : : * could do this (and bypass many other checks), and "unprivileged"
737 : : * processes could not.
738 : : *
739 : : * In Linux, the special powers of euid 0 are divided into many
740 : : * capabilities: see `capabilities(7)`. The one we are interested in
741 : : * here is `CAP_DAC_OVERRIDE`.
742 : : *
743 : : * We do this generically instead of actually looking at the capability
744 : : * bits, so that the right thing will happen on non-Linux Unix
745 : : * implementations, in particular if they have something equivalent to
746 : : * but not identical to Linux permissions.
747 : : *
748 : : * Returns: %TRUE if we have Linux `CAP_DAC_OVERRIDE` or equivalent
749 : : * privileges
750 : : */
751 : : static gboolean
752 : 11 : check_cap_dac_override (const char *tmpdir)
753 : : {
754 : : #ifdef G_OS_UNIX
755 : 11 : gchar *safe_tmpdir = NULL;
756 : : gchar *dac_denies_write;
757 : : gchar *inside;
758 : : gboolean have_cap;
759 : :
760 [ + + ]: 11 : if (tmpdir == NULL)
761 : : {
762 : : /* It's unsafe to write predictable filenames into g_get_tmp_dir(),
763 : : * because it's usually a shared directory that can be subject to
764 : : * symlink attacks, so use a subdirectory for this check. */
765 : 2 : GError *error = NULL;
766 : :
767 : 2 : safe_tmpdir = g_dir_make_tmp (NULL, &error);
768 : 2 : g_assert_no_error (error);
769 : 2 : g_clear_error (&error);
770 : :
771 [ - + ]: 2 : if (safe_tmpdir == NULL)
772 : 0 : return FALSE;
773 : :
774 : 2 : tmpdir = safe_tmpdir;
775 : : }
776 : :
777 : 11 : dac_denies_write = g_build_filename (tmpdir, "dac-denies-write", NULL);
778 : 11 : inside = g_build_filename (dac_denies_write, "inside", NULL);
779 : :
780 : 11 : g_assert_no_errno (mkdir (dac_denies_write, S_IRWXU));
781 : 11 : g_assert_no_errno (g_chmod (dac_denies_write, 0));
782 : :
783 [ - + ]: 11 : if (mkdir (inside, S_IRWXU) == 0)
784 : : {
785 : 0 : g_test_message ("Looks like we have CAP_DAC_OVERRIDE or equivalent");
786 : 0 : g_assert_no_errno (rmdir (inside));
787 : 0 : have_cap = TRUE;
788 : : }
789 : : else
790 : : {
791 : 11 : int saved_errno = errno;
792 : :
793 : 11 : g_test_message ("We do not have CAP_DAC_OVERRIDE or equivalent");
794 : 11 : g_assert_cmpint (saved_errno, ==, EACCES);
795 : 11 : have_cap = FALSE;
796 : : }
797 : :
798 : 11 : g_assert_no_errno (g_chmod (dac_denies_write, S_IRWXU));
799 : 11 : g_assert_no_errno (rmdir (dac_denies_write));
800 : :
801 [ + + ]: 11 : if (safe_tmpdir != NULL)
802 : 2 : g_assert_no_errno (rmdir (safe_tmpdir));
803 : :
804 : 11 : g_free (dac_denies_write);
805 : 11 : g_free (inside);
806 : 11 : g_free (safe_tmpdir);
807 : 11 : return have_cap;
808 : : #else
809 : : return FALSE;
810 : : #endif
811 : : }
812 : :
813 : : static void
814 : 1 : test_mkdir_with_parents (void)
815 : : {
816 : : gchar *cwd, *new_path;
817 : : #ifndef G_OS_WIN32
818 : 1 : gboolean can_override_dac = check_cap_dac_override (NULL);
819 : : #endif
820 [ - + ]: 1 : if (g_test_verbose())
821 : 0 : g_printerr ("checking g_mkdir_with_parents() in subdir ./hum/");
822 : 1 : test_mkdir_with_parents_1 ("hum");
823 : 1 : g_remove ("hum");
824 [ - + ]: 1 : if (g_test_verbose())
825 : 0 : g_printerr ("checking g_mkdir_with_parents() in subdir ./hii///haa/hee/");
826 : 1 : test_mkdir_with_parents_1 ("./hii///haa/hee///");
827 : 1 : g_remove ("hii/haa/hee");
828 : 1 : g_remove ("hii/haa");
829 : 1 : g_remove ("hii");
830 : 1 : cwd = g_get_current_dir ();
831 [ - + ]: 1 : if (g_test_verbose())
832 : 0 : g_printerr ("checking g_mkdir_with_parents() in cwd: %s", cwd);
833 : 1 : test_mkdir_with_parents_1 (cwd);
834 : :
835 : 1 : new_path = g_build_filename (cwd, "new", NULL);
836 : 1 : g_assert_cmpint (g_mkdir_with_parents (new_path, 0), ==, 0);
837 : 1 : g_assert_cmpint (g_rmdir (new_path), ==, 0);
838 : 1 : g_free (new_path);
839 : 1 : g_free (cwd);
840 : :
841 : 1 : g_assert_cmpint (g_mkdir_with_parents ("./test", 0), ==, 0);
842 : 1 : g_assert_cmpint (g_mkdir_with_parents ("./test", 0), ==, 0);
843 : 1 : g_remove ("./test");
844 : :
845 : : #ifndef G_OS_WIN32
846 [ - + ]: 1 : if (can_override_dac)
847 : : {
848 : 0 : g_assert_cmpint (g_mkdir_with_parents ("/usr/b/c", 0), ==, 0);
849 : 0 : g_remove ("/usr/b/c");
850 : 0 : g_remove ("/usr/b");
851 : : }
852 : : else
853 : : {
854 : 1 : g_assert_cmpint (g_mkdir_with_parents ("/usr/b/c", 0), ==, -1);
855 : : /* EPERM or EROFS may be returned if the filesystem as a whole is read-only */
856 [ + - + - ]: 1 : if (errno != EPERM && errno != EROFS)
857 : 1 : g_assert_cmpint (errno, ==, EACCES);
858 : : }
859 : :
860 : : #endif
861 : :
862 : 1 : g_assert_cmpint (g_mkdir_with_parents (NULL, 0), ==, -1);
863 : 1 : g_assert_cmpint (errno, ==, EINVAL);
864 : 1 : }
865 : :
866 : : /* Reproducer for https://gitlab.gnome.org/GNOME/glib/issues/1852 */
867 : : static void
868 : 1 : test_mkdir_with_parents_permission (void)
869 : : {
870 : : #ifdef G_OS_UNIX
871 : : gchar *tmpdir;
872 : : gchar *subdir;
873 : : gchar *subdir2;
874 : : gchar *subdir3;
875 : 1 : GError *error = NULL;
876 : : int result;
877 : : int saved_errno;
878 : : gboolean have_cap_dac_override;
879 : :
880 : 1 : tmpdir = g_dir_make_tmp ("test-fileutils.XXXXXX", &error);
881 : 1 : g_assert_no_error (error);
882 : 1 : g_assert_nonnull (tmpdir);
883 : :
884 : 1 : have_cap_dac_override = check_cap_dac_override (tmpdir);
885 : :
886 : 1 : subdir = g_build_filename (tmpdir, "sub", NULL);
887 : 1 : subdir2 = g_build_filename (subdir, "sub2", NULL);
888 : 1 : subdir3 = g_build_filename (subdir2, "sub3", NULL);
889 : 1 : g_assert_no_errno (g_mkdir (subdir, 0700));
890 : 1 : g_assert_no_errno (g_chmod (subdir, 0));
891 : :
892 [ - + ]: 1 : if (have_cap_dac_override)
893 : : {
894 : 0 : g_test_skip ("have CAP_DAC_OVERRIDE or equivalent, cannot test");
895 : : }
896 : : else
897 : : {
898 : 1 : result = g_mkdir_with_parents (subdir2, 0700);
899 : 1 : saved_errno = errno;
900 : 1 : g_assert_cmpint (result, ==, -1);
901 : 1 : g_assert_cmpint (saved_errno, ==, EACCES);
902 : :
903 : 1 : result = g_mkdir_with_parents (subdir3, 0700);
904 : 1 : saved_errno = errno;
905 : 1 : g_assert_cmpint (result, ==, -1);
906 : 1 : g_assert_cmpint (saved_errno, ==, EACCES);
907 : :
908 : 1 : g_assert_no_errno (g_chmod (subdir, 0700));
909 : : }
910 : :
911 : 1 : g_assert_no_errno (g_remove (subdir));
912 : 1 : g_assert_no_errno (g_remove (tmpdir));
913 : 1 : g_free (subdir3);
914 : 1 : g_free (subdir2);
915 : 1 : g_free (subdir);
916 : 1 : g_free (tmpdir);
917 : : #else
918 : : g_test_skip ("cannot test without Unix-style permissions");
919 : : #endif
920 : 1 : }
921 : :
922 : : static void
923 : 1 : test_format_size_for_display (void)
924 : : {
925 : : #ifdef G_OS_WIN32
926 : : SetThreadLocale (MAKELCID (MAKELANGID (LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT));
927 : : #endif
928 : : /* nobody called setlocale(), so we should get "C" behaviour... */
929 : 1 : check_string (g_format_size_for_display (0), "0 bytes");
930 : 1 : check_string (g_format_size_for_display (1), "1 byte");
931 : 1 : check_string (g_format_size_for_display (2), "2 bytes");
932 : 1 : check_string (g_format_size_for_display (1024), "1.0 KB");
933 : 1 : check_string (g_format_size_for_display (1024 * 1024), "1.0 MB");
934 : 1 : check_string (g_format_size_for_display (1024 * 1024 * 1024), "1.0 GB");
935 : 1 : check_string (g_format_size_for_display (1024ULL * 1024 * 1024 * 1024), "1.0 TB");
936 : 1 : check_string (g_format_size_for_display (1024ULL * 1024 * 1024 * 1024 * 1024), "1.0 PB");
937 : 1 : check_string (g_format_size_for_display (1024ULL * 1024 * 1024 * 1024 * 1024 * 1024), "1.0 EB");
938 : :
939 : 1 : check_string (g_format_size (0), "0 bytes");
940 : 1 : check_string (g_format_size (1), "1 byte");
941 : 1 : check_string (g_format_size (2), "2 bytes");
942 : : /* '\302\240' is a no-break space, to keep quantity and unit symbol together at line breaks*/
943 : 1 : check_string (g_format_size (1000ULL), "1.0\302\240kB");
944 : 1 : check_string (g_format_size (1000ULL * 1000), "1.0\302\240MB");
945 : 1 : check_string (g_format_size (1000ULL * 1000 * 1000), "1.0\302\240GB");
946 : 1 : check_string (g_format_size (1000ULL * 1000 * 1000 * 1000), "1.0\302\240TB");
947 : 1 : check_string (g_format_size (1000ULL * 1000 * 1000 * 1000 * 1000), "1.0\302\240PB");
948 : 1 : check_string (g_format_size (1000ULL * 1000 * 1000 * 1000 * 1000 * 1000), "1.0\302\240EB");
949 : :
950 : 1 : check_string (g_format_size_full (0, G_FORMAT_SIZE_IEC_UNITS), "0 bytes");
951 : 1 : check_string (g_format_size_full (0, G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_ONLY_VALUE), "0");
952 : 1 : check_string (g_format_size_full (0, G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_ONLY_UNIT), "bytes");
953 : 1 : check_string (g_format_size_full (1, G_FORMAT_SIZE_IEC_UNITS), "1 byte");
954 : 1 : check_string (g_format_size_full (1, G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_ONLY_VALUE), "1");
955 : 1 : check_string (g_format_size_full (1, G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_ONLY_UNIT), "byte");
956 : 1 : check_string (g_format_size_full (2, G_FORMAT_SIZE_IEC_UNITS), "2 bytes");
957 : 1 : check_string (g_format_size_full (2, G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_ONLY_VALUE), "2");
958 : 1 : check_string (g_format_size_full (2, G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_ONLY_UNIT), "bytes");
959 : :
960 : 1 : check_string (g_format_size_full (2048ULL, G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240KiB");
961 : 1 : check_string (g_format_size_full (2048ULL * 1024, G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240MiB");
962 : 1 : check_string (g_format_size_full (2048ULL * 1024 * 1024, G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240GiB");
963 : 1 : check_string (g_format_size_full (2048ULL * 1024 * 1024 * 1024, G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240TiB");
964 : 1 : check_string (g_format_size_full (2048ULL * 1024 * 1024 * 1024 * 1024, G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240PiB");
965 : 1 : check_string (g_format_size_full (2048ULL * 1024 * 1024 * 1024 * 1024 * 1024, G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240EiB");
966 : :
967 : 1 : check_string (g_format_size_full (238472938, G_FORMAT_SIZE_IEC_UNITS), "227.4\302\240MiB");
968 : 1 : check_string (g_format_size_full (238472938, G_FORMAT_SIZE_DEFAULT), "238.5\302\240MB");
969 : 1 : check_string (g_format_size_full (238472938, G_FORMAT_SIZE_LONG_FORMAT), "238.5\302\240MB (238472938 bytes)");
970 : 1 : check_string (g_format_size_full (238472938, G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_ONLY_VALUE), "227.4");
971 : 1 : check_string (g_format_size_full (238472938, G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_ONLY_UNIT), "MiB");
972 : :
973 : :
974 : 1 : check_string (g_format_size_full (0, G_FORMAT_SIZE_BITS), "0 bits");
975 : 1 : check_string (g_format_size_full (0, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_ONLY_VALUE), "0");
976 : 1 : check_string (g_format_size_full (0, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_ONLY_UNIT), "bits");
977 : 1 : check_string (g_format_size_full (1, G_FORMAT_SIZE_BITS), "1 bit");
978 : 1 : check_string (g_format_size_full (1, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_ONLY_VALUE), "1");
979 : 1 : check_string (g_format_size_full (1, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_ONLY_UNIT), "bit");
980 : 1 : check_string (g_format_size_full (2, G_FORMAT_SIZE_BITS), "2 bits");
981 : 1 : check_string (g_format_size_full (2, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_ONLY_VALUE), "2");
982 : 1 : check_string (g_format_size_full (2, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_ONLY_UNIT), "bits");
983 : :
984 : 1 : check_string (g_format_size_full (2000ULL, G_FORMAT_SIZE_BITS), "2.0\302\240kbit");
985 : 1 : check_string (g_format_size_full (2000ULL * 1000, G_FORMAT_SIZE_BITS), "2.0\302\240Mbit");
986 : 1 : check_string (g_format_size_full (2000ULL * 1000 * 1000, G_FORMAT_SIZE_BITS), "2.0\302\240Gbit");
987 : 1 : check_string (g_format_size_full (2000ULL * 1000 * 1000 * 1000, G_FORMAT_SIZE_BITS), "2.0\302\240Tbit");
988 : 1 : check_string (g_format_size_full (2000ULL * 1000 * 1000 * 1000 * 1000, G_FORMAT_SIZE_BITS), "2.0\302\240Pbit");
989 : 1 : check_string (g_format_size_full (2000ULL * 1000 * 1000 * 1000 * 1000 * 1000, G_FORMAT_SIZE_BITS), "2.0\302\240Ebit");
990 : :
991 : 1 : check_string (g_format_size_full (238472938, G_FORMAT_SIZE_BITS), "238.5\302\240Mbit");
992 : 1 : check_string (g_format_size_full (238472938, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_LONG_FORMAT), "238.5\302\240Mbit (238472938 bits)");
993 : 1 : check_string (g_format_size_full (238472938, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_ONLY_VALUE), "238.5");
994 : 1 : check_string (g_format_size_full (238472938, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_ONLY_UNIT), "Mbit");
995 : :
996 : :
997 : 1 : check_string (g_format_size_full (0, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "0 bits");
998 : 1 : check_string (g_format_size_full (0, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_ONLY_VALUE), "0");
999 : 1 : check_string (g_format_size_full (0, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_ONLY_UNIT), "bits");
1000 : 1 : check_string (g_format_size_full (1, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "1 bit");
1001 : 1 : check_string (g_format_size_full (1, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_ONLY_VALUE), "1");
1002 : 1 : check_string (g_format_size_full (1, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_ONLY_UNIT), "bit");
1003 : 1 : check_string (g_format_size_full (2, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "2 bits");
1004 : 1 : check_string (g_format_size_full (2, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_ONLY_VALUE), "2");
1005 : 1 : check_string (g_format_size_full (2, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_ONLY_UNIT), "bits");
1006 : :
1007 : 1 : check_string (g_format_size_full (2048ULL, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240Kibit");
1008 : 1 : check_string (g_format_size_full (2048ULL * 1024, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240Mibit");
1009 : 1 : check_string (g_format_size_full (2048ULL * 1024 * 1024, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240Gibit");
1010 : 1 : check_string (g_format_size_full (2048ULL * 1024 * 1024 * 1024, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240Tibit");
1011 : 1 : check_string (g_format_size_full (2048ULL * 1024 * 1024 * 1024 * 1024, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240Pibit");
1012 : 1 : check_string (g_format_size_full (2048ULL * 1024 * 1024 * 1024 * 1024 * 1024, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "2.0\302\240Eibit");
1013 : :
1014 : 1 : check_string (g_format_size_full (238472938, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS), "227.4\302\240Mibit");
1015 : 1 : check_string (g_format_size_full (238472938, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_LONG_FORMAT), "227.4\302\240Mibit (238472938 bits)");
1016 : 1 : check_string (g_format_size_full (238472938, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_ONLY_VALUE), "227.4");
1017 : 1 : check_string (g_format_size_full (238472938, G_FORMAT_SIZE_BITS | G_FORMAT_SIZE_IEC_UNITS | G_FORMAT_SIZE_ONLY_UNIT), "Mibit");
1018 : 1 : }
1019 : :
1020 : : static void
1021 : 1 : test_file_errors (void)
1022 : : {
1023 : 1 : g_assert_cmpint (g_file_error_from_errno (-1), ==, G_FILE_ERROR_FAILED);
1024 : :
1025 : : #ifdef EEXIST
1026 : 1 : g_assert_cmpint (g_file_error_from_errno (EEXIST), ==, G_FILE_ERROR_EXIST);
1027 : : #endif
1028 : : #ifdef EISDIR
1029 : 1 : g_assert_cmpint (g_file_error_from_errno (EISDIR), ==, G_FILE_ERROR_ISDIR);
1030 : : #endif
1031 : : #ifdef EACCES
1032 : 1 : g_assert_cmpint (g_file_error_from_errno (EACCES), ==, G_FILE_ERROR_ACCES);
1033 : : #endif
1034 : : #ifdef ENAMETOOLONG
1035 : 1 : g_assert_cmpint (g_file_error_from_errno (ENAMETOOLONG), ==, G_FILE_ERROR_NAMETOOLONG);
1036 : : #endif
1037 : : #ifdef ENOENT
1038 : 1 : g_assert_cmpint (g_file_error_from_errno (ENOENT), ==, G_FILE_ERROR_NOENT);
1039 : : #endif
1040 : : #ifdef ENOTDIR
1041 : 1 : g_assert_cmpint (g_file_error_from_errno (ENOTDIR), ==, G_FILE_ERROR_NOTDIR);
1042 : : #endif
1043 : : #ifdef ENXIO
1044 : 1 : g_assert_cmpint (g_file_error_from_errno (ENXIO), ==, G_FILE_ERROR_NXIO);
1045 : : #endif
1046 : : #ifdef ENODEV
1047 : 1 : g_assert_cmpint (g_file_error_from_errno (ENODEV), ==, G_FILE_ERROR_NODEV);
1048 : : #endif
1049 : : #ifdef EROFS
1050 : 1 : g_assert_cmpint (g_file_error_from_errno (EROFS), ==, G_FILE_ERROR_ROFS);
1051 : : #endif
1052 : : #ifdef ETXTBSY
1053 : 1 : g_assert_cmpint (g_file_error_from_errno (ETXTBSY), ==, G_FILE_ERROR_TXTBSY);
1054 : : #endif
1055 : : #ifdef EFAULT
1056 : 1 : g_assert_cmpint (g_file_error_from_errno (EFAULT), ==, G_FILE_ERROR_FAULT);
1057 : : #endif
1058 : : #ifdef ELOOP
1059 : 1 : g_assert_cmpint (g_file_error_from_errno (ELOOP), ==, G_FILE_ERROR_LOOP);
1060 : : #endif
1061 : : #ifdef ENOSPC
1062 : 1 : g_assert_cmpint (g_file_error_from_errno (ENOSPC), ==, G_FILE_ERROR_NOSPC);
1063 : : #endif
1064 : : #ifdef ENOMEM
1065 : 1 : g_assert_cmpint (g_file_error_from_errno (ENOMEM), ==, G_FILE_ERROR_NOMEM);
1066 : : #endif
1067 : : #ifdef EMFILE
1068 : 1 : g_assert_cmpint (g_file_error_from_errno (EMFILE), ==, G_FILE_ERROR_MFILE);
1069 : : #endif
1070 : : #ifdef ENFILE
1071 : 1 : g_assert_cmpint (g_file_error_from_errno (ENFILE), ==, G_FILE_ERROR_NFILE);
1072 : : #endif
1073 : : #ifdef EBADF
1074 : 1 : g_assert_cmpint (g_file_error_from_errno (EBADF), ==, G_FILE_ERROR_BADF);
1075 : : #endif
1076 : : #ifdef EINVAL
1077 : 1 : g_assert_cmpint (g_file_error_from_errno (EINVAL), ==, G_FILE_ERROR_INVAL);
1078 : : #endif
1079 : : #ifdef EPIPE
1080 : 1 : g_assert_cmpint (g_file_error_from_errno (EPIPE), ==, G_FILE_ERROR_PIPE);
1081 : : #endif
1082 : : #ifdef EAGAIN
1083 : 1 : g_assert_cmpint (g_file_error_from_errno (EAGAIN), ==, G_FILE_ERROR_AGAIN);
1084 : : #endif
1085 : : #ifdef EINTR
1086 : 1 : g_assert_cmpint (g_file_error_from_errno (EINTR), ==, G_FILE_ERROR_INTR);
1087 : : #endif
1088 : : #ifdef EIO
1089 : 1 : g_assert_cmpint (g_file_error_from_errno (EIO), ==, G_FILE_ERROR_IO);
1090 : : #endif
1091 : : #ifdef EPERM
1092 : 1 : g_assert_cmpint (g_file_error_from_errno (EPERM), ==, G_FILE_ERROR_PERM);
1093 : : #endif
1094 : : #ifdef ENOSYS
1095 : 1 : g_assert_cmpint (g_file_error_from_errno (ENOSYS), ==, G_FILE_ERROR_NOSYS);
1096 : : #endif
1097 : 1 : }
1098 : :
1099 : : static void
1100 : 1 : test_basename (void)
1101 : : {
1102 : 1 : const gchar *path = "/path/to/a/file/deep/down.sh";
1103 : : const gchar *b;
1104 : :
1105 [ + - ]: 1 : if (g_test_undefined ())
1106 : : {
1107 : 1 : g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
1108 : : "*assertion*!= NULL*");
1109 : 1 : g_assert_null (g_basename (NULL));
1110 : 1 : g_test_assert_expected_messages ();
1111 : : }
1112 : :
1113 : 1 : b = g_basename (path);
1114 : :
1115 : 1 : g_assert_cmpstr (b, ==, "down.sh");
1116 : 1 : }
1117 : :
1118 : : static void
1119 : 1 : test_get_basename (void)
1120 : : {
1121 : : gchar *b;
1122 : :
1123 [ + - ]: 1 : if (g_test_undefined ())
1124 : : {
1125 : 1 : g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
1126 : : "*assertion*!= NULL*");
1127 : 1 : g_assert_null (g_path_get_basename (NULL));
1128 : 1 : g_test_assert_expected_messages ();
1129 : : }
1130 : :
1131 : 1 : b = g_path_get_basename ("");
1132 : 1 : g_assert_cmpstr (b, ==, ".");
1133 : 1 : g_free (b);
1134 : :
1135 : 1 : b = g_path_get_basename ("///");
1136 : 1 : g_assert_cmpstr (b, ==, G_DIR_SEPARATOR_S);
1137 : 1 : g_free (b);
1138 : :
1139 : 1 : b = g_path_get_basename ("/a/b/c/d");
1140 : 1 : g_assert_cmpstr (b, ==, "d");
1141 : 1 : g_free (b);
1142 : 1 : }
1143 : :
1144 : : static void
1145 : 1 : test_dirname (void)
1146 : : {
1147 : : gsize i;
1148 : : struct {
1149 : : const gchar *filename;
1150 : : const gchar *dirname;
1151 : 1 : } dirname_checks[] = {
1152 : : { "/", "/" },
1153 : : { "////", "/" },
1154 : : { ".////", "." },
1155 : : { ".", "." },
1156 : : { "..", "." },
1157 : : { "../", ".." },
1158 : : { "..////", ".." },
1159 : : { "", "." },
1160 : : { "a/b", "a" },
1161 : : { "a/b/", "a/b" },
1162 : : { "c///", "c" },
1163 : : { "/a/b", "/a" },
1164 : : { "/a/b/", "/a/b" },
1165 : : #ifdef G_OS_WIN32
1166 : : { "\\", "\\" },
1167 : : { ".\\\\\\\\", "." },
1168 : : { ".\\/\\/", "." },
1169 : : { ".", "." },
1170 : : { "..", "." },
1171 : : { "..\\", ".." },
1172 : : { "..\\\\\\\\", ".." },
1173 : : { "..\\//\\", ".." },
1174 : : { "", "." },
1175 : : { "a\\b", "a" },
1176 : : { "a\\b\\", "a\\b" },
1177 : : { "\\a\\b", "\\a" },
1178 : : { "\\a\\b\\", "\\a\\b" },
1179 : : { "c\\\\\\", "c" },
1180 : : { "c/\\\\", "c" },
1181 : : { "a:", "a:." },
1182 : : { "a:foo", "a:." },
1183 : : { "a:foo\\bar", "a:foo" },
1184 : : { "a:/foo", "a:/" },
1185 : : { "a:/foo/bar", "a:/foo" },
1186 : : { "a:/", "a:/" },
1187 : : { "a://", "a:/" },
1188 : : { "a:\\foo", "a:\\" },
1189 : : { "a:\\", "a:\\" },
1190 : : { "a:\\\\", "a:\\" },
1191 : : { "a:\\/", "a:\\" },
1192 : : #endif
1193 : : };
1194 : :
1195 [ + - ]: 1 : if (g_test_undefined ())
1196 : : {
1197 : 1 : g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
1198 : : "*assertion*!= NULL*");
1199 : 1 : g_assert_null (g_path_get_dirname (NULL));
1200 : 1 : g_test_assert_expected_messages ();
1201 : : }
1202 : :
1203 [ + + ]: 14 : for (i = 0; i < G_N_ELEMENTS (dirname_checks); i++)
1204 : : {
1205 : : gchar *dirname;
1206 : :
1207 : 13 : dirname = g_path_get_dirname (dirname_checks[i].filename);
1208 : 13 : g_assert_cmpstr (dirname, ==, dirname_checks[i].dirname);
1209 : 13 : g_free (dirname);
1210 : : }
1211 : 1 : }
1212 : :
1213 : : static void
1214 : 1 : test_dir_make_tmp (void)
1215 : : {
1216 : : gchar *name;
1217 : 1 : GError *error = NULL;
1218 : : gint ret;
1219 : :
1220 : 1 : name = g_dir_make_tmp ("testXXXXXXtest", &error);
1221 : 1 : g_assert_no_error (error);
1222 : 1 : g_assert_true (g_file_test (name, G_FILE_TEST_IS_DIR));
1223 : 1 : g_assert_true (g_str_has_prefix (name, g_getenv ("G_TEST_TMPDIR")));
1224 : 1 : ret = g_rmdir (name);
1225 : 1 : g_assert_cmpint (ret, ==, 0);
1226 : 1 : g_free (name);
1227 : :
1228 : 1 : name = g_dir_make_tmp (NULL, &error);
1229 : 1 : g_assert_no_error (error);
1230 : 1 : g_assert_true (g_file_test (name, G_FILE_TEST_IS_DIR));
1231 : 1 : g_assert_true (g_str_has_prefix (name, g_getenv ("G_TEST_TMPDIR")));
1232 : 1 : ret = g_rmdir (name);
1233 : 1 : g_assert_cmpint (ret, ==, 0);
1234 : 1 : g_free (name);
1235 : :
1236 : 1 : name = g_dir_make_tmp ("test/XXXXXX", &error);
1237 : 1 : g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED);
1238 : 1 : g_clear_error (&error);
1239 : 1 : g_assert_null (name);
1240 : :
1241 : 1 : name = g_dir_make_tmp ("XXXXxX", &error);
1242 : 1 : g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED);
1243 : 1 : g_clear_error (&error);
1244 : 1 : g_assert_null (name);
1245 : 1 : }
1246 : :
1247 : : static void
1248 : 1 : test_file_open_tmp (void)
1249 : : {
1250 : 1 : gchar *name = NULL;
1251 : 1 : GError *error = NULL;
1252 : : gint fd;
1253 : :
1254 : 1 : fd = g_file_open_tmp ("testXXXXXXtest", &name, &error);
1255 : 1 : g_assert_cmpint (fd, !=, -1);
1256 : 1 : g_assert_no_error (error);
1257 : 1 : g_assert_nonnull (name);
1258 : 1 : g_assert_true (g_str_has_prefix (name, g_getenv ("G_TEST_TMPDIR")));
1259 : 1 : unlink (name);
1260 : 1 : g_free (name);
1261 : 1 : close (fd);
1262 : :
1263 : 1 : fd = g_file_open_tmp (NULL, &name, &error);
1264 : 1 : g_assert_cmpint (fd, !=, -1);
1265 : 1 : g_assert_no_error (error);
1266 : 1 : g_assert_nonnull (name);
1267 : 1 : g_assert_true (g_str_has_prefix (name, g_getenv ("G_TEST_TMPDIR")));
1268 : 1 : g_unlink (name);
1269 : 1 : g_free (name);
1270 : 1 : close (fd);
1271 : :
1272 : 1 : name = NULL;
1273 : 1 : fd = g_file_open_tmp ("test/XXXXXX", &name, &error);
1274 : 1 : g_assert_cmpint (fd, ==, -1);
1275 : 1 : g_assert_null (name);
1276 : 1 : g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED);
1277 : 1 : g_clear_error (&error);
1278 : :
1279 : 1 : fd = g_file_open_tmp ("XXXXxX", &name, &error);
1280 : 1 : g_assert_cmpint (fd, ==, -1);
1281 : 1 : g_assert_null (name);
1282 : 1 : g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED);
1283 : 1 : g_clear_error (&error);
1284 : :
1285 : 1 : error = NULL;
1286 : 1 : name = NULL;
1287 : 1 : fd = g_file_open_tmp ("zap" G_DIR_SEPARATOR_S "barXXXXXX", &name, &error);
1288 : 1 : g_assert_cmpint (fd, ==, -1);
1289 : :
1290 : 1 : g_clear_error (&error);
1291 : 1 : g_free (name);
1292 : :
1293 : : #ifdef G_OS_WIN32
1294 : : name = NULL;
1295 : : fd = g_file_open_tmp ("zap/barXXXXXX", &name, &error);
1296 : : g_assert_cmpint (fd, ==, -1);
1297 : :
1298 : : g_clear_error (&error);
1299 : : g_free (name);
1300 : : #endif
1301 : :
1302 : 1 : name = NULL;
1303 : 1 : fd = g_file_open_tmp ("zapXXXXXX", &name, &error);
1304 : 1 : g_assert_cmpint (fd, !=, -1);
1305 : :
1306 : 1 : close (fd);
1307 : 1 : g_clear_error (&error);
1308 : 1 : remove (name);
1309 : 1 : g_free (name);
1310 : :
1311 : 1 : name = NULL;
1312 : 1 : fd = g_file_open_tmp (NULL, &name, &error);
1313 : 1 : g_assert_cmpint (fd, !=, -1);
1314 : :
1315 : 1 : close (fd);
1316 : 1 : g_clear_error (&error);
1317 : 1 : remove (name);
1318 : 1 : g_free (name);
1319 : 1 : }
1320 : :
1321 : : static void
1322 : 1 : test_mkstemp (void)
1323 : : {
1324 : : gint fd;
1325 : : gint result;
1326 : : gchar *name;
1327 : : char chars[62];
1328 : : char template[32];
1329 : 1 : const char hello[] = "Hello, World";
1330 : 1 : const gsize hellolen = sizeof (hello) - 1;
1331 : :
1332 [ + - ]: 1 : if (g_test_undefined ())
1333 : : {
1334 : 1 : g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
1335 : : "*assertion*!= NULL*");
1336 : 1 : g_assert_cmpint (g_mkstemp (NULL), ==, -1);
1337 : 1 : g_test_assert_expected_messages ();
1338 : : }
1339 : :
1340 : : /* Expect to fail if no 'XXXXXX' is given */
1341 : 1 : name = g_strdup ("test");
1342 : 1 : g_assert_cmpint (g_mkstemp (name), ==, -1);
1343 : 1 : g_free (name);
1344 : :
1345 : : /* Test normal case */
1346 : 1 : name = g_strdup ("testXXXXXXtest"),
1347 : 1 : fd = g_mkstemp (name);
1348 : 1 : g_assert_cmpint (fd, !=, -1);
1349 : 1 : g_assert_null (strstr (name, "XXXXXX"));
1350 : 1 : unlink (name);
1351 : 1 : close (fd);
1352 : 1 : g_free (name);
1353 : :
1354 : : /* g_mkstemp() must not work if template doesn't contain XXXXXX */
1355 : 1 : strcpy (template, "foobar");
1356 : 1 : g_assert_cmpint (g_mkstemp (template), ==, -1);
1357 : :
1358 : : /* g_mkstemp() must not work if template doesn't contain six X */
1359 : 1 : strcpy (template, "foobarXXX");
1360 : 1 : g_assert_cmpint (g_mkstemp (template), ==, -1);
1361 : :
1362 : 1 : strcpy (template, "fooXXXXXX");
1363 : 1 : fd = g_mkstemp (template);
1364 : 1 : g_assert_cmpint (fd, !=, -1);
1365 : 1 : result = write (fd, hello, hellolen);
1366 : 1 : g_assert_cmpint (result, !=, -1);
1367 : 1 : g_assert_cmpint (result, ==, hellolen);
1368 : :
1369 : 1 : lseek (fd, 0, 0);
1370 : 1 : result = read (fd, chars, sizeof (chars));
1371 : 1 : g_assert_cmpint (result, !=, -1);
1372 : 1 : g_assert_cmpint (result, ==, hellolen);
1373 : :
1374 : 1 : chars[result] = '\0';
1375 : 1 : g_assert_cmpstr (chars, ==, hello);
1376 : :
1377 : 1 : close (fd);
1378 : 1 : remove (template);
1379 : :
1380 : : /* Check that is does not work for "fooXXXXXX.pdf" */
1381 : 1 : strcpy (template, "fooXXXXXX.pdf");
1382 : 1 : fd = g_mkstemp (template);
1383 : 1 : g_assert_cmpint (fd, !=, -1);
1384 : :
1385 : 1 : close (fd);
1386 : 1 : remove (template);
1387 : 1 : }
1388 : :
1389 : : static void
1390 : 1 : test_mkdtemp (void)
1391 : : {
1392 : : gint fd;
1393 : : gchar *ret;
1394 : : gchar *name;
1395 : : char template[32];
1396 : :
1397 : 1 : name = g_strdup ("testXXXXXXtest"),
1398 : 1 : ret = g_mkdtemp (name);
1399 : 1 : g_assert (ret == name);
1400 : 1 : g_assert_null (strstr (name, "XXXXXX"));
1401 : 1 : g_rmdir (name);
1402 : 1 : g_free (name);
1403 : :
1404 : 1 : name = g_strdup ("testYYYYYYtest"),
1405 : 1 : ret = g_mkdtemp (name);
1406 : 1 : g_assert_null (ret);
1407 : 1 : g_free (name);
1408 : :
1409 : 1 : strcpy (template, "foodir");
1410 : 1 : g_assert_null (g_mkdtemp (template));
1411 : :
1412 : 1 : strcpy (template, "foodir");
1413 : 1 : g_assert_null (g_mkdtemp (template));
1414 : :
1415 : 1 : strcpy (template, "fooXXXXXX");
1416 : 1 : ret = g_mkdtemp (template);
1417 : 1 : g_assert_nonnull (ret);
1418 : 1 : g_assert_true (ret == template);
1419 : 1 : g_assert_false (g_file_test (template, G_FILE_TEST_IS_REGULAR));
1420 : 1 : g_assert_true (g_file_test (template, G_FILE_TEST_IS_DIR));
1421 : :
1422 : 1 : strcat (template, "/abc");
1423 : 1 : fd = g_open (template, O_WRONLY | O_CREAT, 0600);
1424 : 1 : g_assert_cmpint (fd, !=, -1);
1425 : 1 : close (fd);
1426 : 1 : g_assert_true (g_file_test (template, G_FILE_TEST_IS_REGULAR));
1427 : 1 : g_assert_cmpint (g_unlink (template), !=, -1);
1428 : :
1429 : 1 : template[9] = '\0';
1430 : 1 : g_assert_cmpint (g_rmdir (template), !=, -1);
1431 : :
1432 : 1 : strcpy (template, "fooXXXXXX.dir");
1433 : 1 : g_assert_nonnull (g_mkdtemp (template));
1434 : 1 : g_assert_true (g_file_test (template, G_FILE_TEST_IS_DIR));
1435 : 1 : g_rmdir (template);
1436 : 1 : }
1437 : :
1438 : : static void
1439 : 1 : test_get_contents (void)
1440 : : {
1441 : : FILE *f;
1442 : : gsize len;
1443 : : gchar *contents;
1444 : 1 : GError *error = NULL;
1445 : 1 : const gchar *text = "abcdefghijklmnopqrstuvwxyz";
1446 : 1 : const gchar *filename = "file-test-get-contents";
1447 : : gsize bytes_written;
1448 : :
1449 : 1 : f = g_fopen (filename, "w");
1450 : 1 : bytes_written = fwrite (text, 1, strlen (text), f);
1451 : 1 : g_assert_cmpint (bytes_written, ==, strlen (text));
1452 : 1 : fclose (f);
1453 : :
1454 [ + - ]: 1 : if (g_test_undefined ())
1455 : : {
1456 : 1 : g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
1457 : : "*assertion*!= NULL*");
1458 : 1 : g_assert_false (g_file_get_contents (NULL, &contents, &len, &error));
1459 : 1 : g_test_assert_expected_messages ();
1460 : :
1461 : 1 : g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
1462 : : "*assertion*!= NULL*");
1463 : 1 : g_assert_false (g_file_get_contents (filename, NULL, &len, &error));
1464 : 1 : g_test_assert_expected_messages ();
1465 : : }
1466 : :
1467 : 1 : g_assert_true (g_file_test (filename, G_FILE_TEST_IS_REGULAR));
1468 : :
1469 : 1 : g_assert_true (g_file_get_contents (filename, &contents, &len, &error));
1470 : 1 : g_assert_cmpstr (text, ==, contents);
1471 : 1 : g_assert_no_error (error);
1472 : :
1473 : 1 : g_free (contents);
1474 : 1 : g_remove (filename);
1475 : 1 : }
1476 : :
1477 : : static gboolean
1478 : 0 : resize_file (const gchar *filename,
1479 : : gint64 size)
1480 : : {
1481 : : int fd;
1482 : : int retval;
1483 : :
1484 : 0 : fd = g_open (filename, O_CREAT | O_RDWR | O_TRUNC, 0666);
1485 : 0 : g_assert_cmpint (fd, >=, 0);
1486 : :
1487 : : #ifdef G_OS_WIN32
1488 : : retval = _chsize_s (fd, size);
1489 : : #elif HAVE_FTRUNCATE64
1490 : 0 : retval = ftruncate64 (fd, size);
1491 : : #else
1492 : : errno = ENOSYS;
1493 : : retval = -1;
1494 : : #endif
1495 [ # # ]: 0 : if (retval != 0)
1496 : : {
1497 : 0 : g_test_message ("Error trying to resize file (%s)", strerror (errno));
1498 : 0 : close (fd);
1499 : 0 : return FALSE;
1500 : : }
1501 : :
1502 : 0 : close (fd);
1503 : 0 : return TRUE;
1504 : : }
1505 : :
1506 : : static gboolean
1507 : 0 : is_error_in_list (GFileError error_code,
1508 : : const GFileError ok_list[],
1509 : : size_t ok_count)
1510 : : {
1511 [ # # ]: 0 : for (size_t i = 0; i < ok_count; i++)
1512 : : {
1513 [ # # ]: 0 : if (ok_list[i] == error_code)
1514 : 0 : return TRUE;
1515 : : }
1516 : 0 : return FALSE;
1517 : : }
1518 : :
1519 : : static void
1520 : 0 : get_largefile_check_len (const gchar *filename,
1521 : : gint64 large_len,
1522 : : const GFileError ok_list[],
1523 : : size_t ok_count)
1524 : : {
1525 : : gboolean get_ok;
1526 : : gsize len;
1527 : : gchar *contents;
1528 : 0 : GError *error = NULL;
1529 : :
1530 : 0 : get_ok = g_file_get_contents (filename, &contents, &len, &error);
1531 [ # # ]: 0 : if (get_ok)
1532 : : {
1533 : 0 : g_assert_cmpint ((gint64) len, ==, large_len);
1534 : 0 : g_free (contents);
1535 : : }
1536 : : else
1537 : : {
1538 : 0 : g_assert_cmpint (error->domain, ==, G_FILE_ERROR);
1539 [ # # ]: 0 : if (is_error_in_list ((GFileError)error->code, ok_list, ok_count))
1540 : : {
1541 : 0 : g_test_message ("Error reading file of size 0x%" G_GINT64_MODIFIER "x, but with acceptable error type (%s)", large_len, error->message);
1542 : : }
1543 : : else
1544 : : {
1545 : : /* fail for other errors */
1546 : 0 : g_assert_no_error (error);
1547 : : }
1548 : 0 : g_clear_error (&error);
1549 : : }
1550 : 0 : }
1551 : :
1552 : : static void
1553 : 1 : test_get_contents_largefile (void)
1554 : : {
1555 [ + - ]: 1 : if (!g_test_slow ())
1556 : : {
1557 : 1 : g_test_skip ("Skipping slow largefile test");
1558 : 1 : return;
1559 : : }
1560 : :
1561 : 0 : const gchar *filename = "file-test-get-contents-large";
1562 : : gint64 large_len;
1563 : :
1564 : : /* error OK if couldn't allocate large buffer, or if file is too large */
1565 : 0 : const GFileError too_large_errors[] = { G_FILE_ERROR_NOMEM, G_FILE_ERROR_FAILED };
1566 : : /* error OK if couldn't allocate large buffer */
1567 : 0 : const GFileError nomem_errors[] = { G_FILE_ERROR_NOMEM };
1568 : :
1569 : : /* OK to fail to read this, but don't silently under-read */
1570 : 0 : large_len = (G_GINT64_CONSTANT (1) << 32) + 16;
1571 [ # # ]: 0 : if (!resize_file (filename, large_len))
1572 : 0 : goto failed_resize;
1573 : 0 : get_largefile_check_len (filename, large_len, too_large_errors, G_N_ELEMENTS (too_large_errors));
1574 : :
1575 : : /* OK to fail to read this size, but don't silently under-read */
1576 : 0 : large_len = (G_GINT64_CONSTANT (1) << 32) - 1;
1577 [ # # ]: 0 : if (!resize_file (filename, large_len))
1578 : 0 : goto failed_resize;
1579 : 0 : get_largefile_check_len (filename, large_len, too_large_errors, G_N_ELEMENTS (too_large_errors));
1580 : :
1581 : : /* OK to fail memory allocation, but don't otherwise fail this size */
1582 : 0 : large_len = (G_GINT64_CONSTANT (1) << 31) - 1;
1583 [ # # ]: 0 : if (!resize_file (filename, large_len))
1584 : 0 : goto failed_resize;
1585 : 0 : get_largefile_check_len (filename, large_len, nomem_errors, G_N_ELEMENTS (nomem_errors));
1586 : :
1587 : 0 : g_remove (filename);
1588 : 0 : return;
1589 : :
1590 : 0 : failed_resize:
1591 : 0 : g_test_incomplete ("Failed to resize large file, unable to complete large file tests.");
1592 : 0 : g_remove (filename);
1593 : : }
1594 : :
1595 : : static void
1596 : 1 : test_file_test (void)
1597 : : {
1598 : 1 : GError *error = NULL;
1599 : : gboolean result;
1600 : : gchar *name;
1601 : : gint fd;
1602 : :
1603 [ + - ]: 1 : if (g_test_undefined ())
1604 : : {
1605 : 1 : g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
1606 : : "*assertion*!= NULL*");
1607 : 1 : result = g_file_test (NULL, G_FILE_TEST_EXISTS);
1608 : 1 : g_assert_false (result);
1609 : 1 : g_test_assert_expected_messages ();
1610 : : }
1611 : :
1612 : 1 : fd = g_file_open_tmp (NULL, &name, &error);
1613 : 1 : g_assert_no_error (error);
1614 : 1 : g_assert_cmpint (write (fd, "a", 1), ==, 1);
1615 : 1 : g_assert_cmpint (g_fsync (fd), ==, 0);
1616 : 1 : close (fd);
1617 : :
1618 : : #ifndef G_OS_WIN32
1619 : 1 : result = g_file_test (name, G_FILE_TEST_IS_SYMLINK);
1620 : 1 : g_assert_false (result);
1621 : :
1622 : 1 : g_assert_no_errno (symlink (name, "symlink"));
1623 : 1 : result = g_file_test ("symlink", G_FILE_TEST_IS_SYMLINK);
1624 : 1 : g_assert_true (result);
1625 : 1 : unlink ("symlink");
1626 : : #endif
1627 : :
1628 : : /* Cleaning */
1629 : 1 : g_remove (name);
1630 : 1 : g_free (name);
1631 : 1 : }
1632 : :
1633 : : static void
1634 : 1 : test_set_contents (void)
1635 : : {
1636 : 1 : GError *error = NULL;
1637 : : gint fd;
1638 : : gchar *name;
1639 : : gchar *buf;
1640 : : gsize len;
1641 : : gboolean ret;
1642 : :
1643 : 1 : fd = g_file_open_tmp (NULL, &name, &error);
1644 : 1 : g_assert_no_error (error);
1645 : 1 : g_assert_cmpint (write (fd, "a", 1), ==, 1);
1646 : 1 : g_assert_cmpint (g_fsync (fd), ==, 0);
1647 : 1 : close (fd);
1648 : :
1649 : 1 : ret = g_file_get_contents (name, &buf, &len, &error);
1650 : 1 : g_assert_true (ret);
1651 : 1 : g_assert_no_error (error);
1652 : 1 : g_assert_cmpstr (buf, ==, "a");
1653 : 1 : g_free (buf);
1654 : :
1655 : 1 : ret = g_file_set_contents (name, "b", 1, &error);
1656 : 1 : g_assert_true (ret);
1657 : 1 : g_assert_no_error (error);
1658 : :
1659 : 1 : ret = g_file_get_contents (name, &buf, &len, &error);
1660 : 1 : g_assert_true (ret);
1661 : 1 : g_assert_no_error (error);
1662 : 1 : g_assert_cmpstr (buf, ==, "b");
1663 : 1 : g_free (buf);
1664 : :
1665 : 1 : g_remove (name);
1666 : 1 : g_free (name);
1667 : 1 : }
1668 : :
1669 : : static void
1670 : 1 : test_set_contents_full (void)
1671 : : {
1672 : 1 : GFileSetContentsFlags flags_mask =
1673 : : G_FILE_SET_CONTENTS_ONLY_EXISTING |
1674 : : G_FILE_SET_CONTENTS_DURABLE |
1675 : : G_FILE_SET_CONTENTS_CONSISTENT;
1676 : : gint flags;
1677 : : const struct
1678 : : {
1679 : : enum
1680 : : {
1681 : : EXISTING_FILE_NONE,
1682 : : EXISTING_FILE_REGULAR,
1683 : : #ifndef G_OS_WIN32
1684 : : EXISTING_FILE_SYMLINK,
1685 : : #endif
1686 : : EXISTING_FILE_DIRECTORY,
1687 : : }
1688 : : existing_file;
1689 : : int new_mode; /* only relevant if @existing_file is %EXISTING_FILE_NONE */
1690 : : gboolean use_strlen;
1691 : :
1692 : : gboolean expected_success;
1693 : : gint expected_error;
1694 : : }
1695 : 1 : tests[] =
1696 : : {
1697 : : { EXISTING_FILE_NONE, 0644, FALSE, TRUE, 0 },
1698 : : { EXISTING_FILE_NONE, 0644, TRUE, TRUE, 0 },
1699 : : { EXISTING_FILE_NONE, 0600, FALSE, TRUE, 0 },
1700 : : { EXISTING_FILE_REGULAR, 0644, FALSE, TRUE, 0 },
1701 : : #ifndef G_OS_WIN32
1702 : : { EXISTING_FILE_SYMLINK, 0644, FALSE, TRUE, 0 },
1703 : : { EXISTING_FILE_DIRECTORY, 0644, FALSE, FALSE, G_FILE_ERROR_ISDIR },
1704 : : #else
1705 : : /* on win32, _wopen returns EACCES if path is a directory */
1706 : : { EXISTING_FILE_DIRECTORY, 0644, FALSE, FALSE, G_FILE_ERROR_ACCES },
1707 : : #endif
1708 : : };
1709 : : gsize i;
1710 : :
1711 : 1 : g_test_summary ("Test g_file_set_contents_full() with various flags");
1712 : :
1713 [ + + ]: 8 : for (flags = 0; flags < (gint) flags_mask; flags++)
1714 : : {
1715 [ + + ]: 49 : for (i = 0; i < G_N_ELEMENTS (tests); i++)
1716 : : {
1717 : 42 : GError *error = NULL;
1718 : 42 : gchar *file_name = NULL, *link_name = NULL, *dir_name = NULL;
1719 : : const gchar *set_contents_name;
1720 : 42 : gchar *buf = NULL;
1721 : : gsize len;
1722 : : gboolean ret;
1723 : : GStatBuf statbuf;
1724 : 42 : const gchar *original_contents = "a string which is longer than what will be overwritten on it";
1725 : 42 : size_t original_contents_len = strlen (original_contents);
1726 : :
1727 : 42 : g_test_message ("Flags %d and test %" G_GSIZE_FORMAT, flags, i);
1728 : :
1729 [ + + + - ]: 42 : switch (tests[i].existing_file)
1730 : : {
1731 : 14 : case EXISTING_FILE_REGULAR:
1732 : : #ifndef G_OS_WIN32
1733 : : case EXISTING_FILE_SYMLINK:
1734 : : #endif
1735 : : {
1736 : : gint fd;
1737 : :
1738 : 14 : fd = g_file_open_tmp (NULL, &file_name, &error);
1739 : 14 : g_assert_no_error (error);
1740 : 14 : g_assert_cmpint (write (fd, original_contents, original_contents_len), ==, original_contents_len);
1741 : 14 : g_assert_no_errno (g_fsync (fd));
1742 : 14 : close (fd);
1743 : :
1744 : : #ifndef G_OS_WIN32
1745 : : /* Pass an existing symlink to g_file_set_contents_full() to see
1746 : : * what it does. */
1747 [ + + ]: 14 : if (tests[i].existing_file == EXISTING_FILE_SYMLINK)
1748 : : {
1749 : 7 : link_name = g_strconcat (file_name, ".link", NULL);
1750 : 7 : g_assert_no_errno (symlink (file_name, link_name));
1751 : :
1752 : 7 : set_contents_name = link_name;
1753 : : }
1754 : : else
1755 : : #endif /* !G_OS_WIN32 */
1756 : : {
1757 : 7 : set_contents_name = file_name;
1758 : : }
1759 : 14 : break;
1760 : : }
1761 : 7 : case EXISTING_FILE_DIRECTORY:
1762 : : {
1763 : 7 : dir_name = g_dir_make_tmp ("glib-fileutils-set-contents-full-XXXXXX", &error);
1764 : 7 : g_assert_no_error (error);
1765 : :
1766 : 7 : set_contents_name = dir_name;
1767 : 7 : break;
1768 : : }
1769 : 21 : case EXISTING_FILE_NONE:
1770 : : {
1771 : 21 : file_name = g_build_filename (g_get_tmp_dir (), "glib-file-set-contents-full-test", NULL);
1772 : 21 : g_remove (file_name);
1773 : 21 : g_assert_false (g_file_test (file_name, G_FILE_TEST_EXISTS));
1774 : :
1775 : 21 : set_contents_name = file_name;
1776 : 21 : break;
1777 : : }
1778 : 0 : default:
1779 : : {
1780 : : g_assert_not_reached ();
1781 : : }
1782 : : }
1783 : :
1784 : : /* Set the file contents */
1785 : 42 : ret = g_file_set_contents_full (set_contents_name, "b",
1786 : 42 : tests[i].use_strlen ? -1 : 1,
1787 [ + + ]: 42 : flags, tests[i].new_mode, &error);
1788 : :
1789 [ + + ]: 42 : if (!tests[i].expected_success)
1790 : : {
1791 : 7 : g_assert_error (error, G_FILE_ERROR, tests[i].expected_error);
1792 : 7 : g_assert_false (ret);
1793 : 7 : g_clear_error (&error);
1794 : : }
1795 : : else
1796 : : {
1797 : 35 : g_assert_no_error (error);
1798 : 35 : g_assert_true (ret);
1799 : :
1800 : : /* Check the contents and mode were set correctly. The mode isn’t
1801 : : * changed on existing files. */
1802 : 35 : ret = g_file_get_contents (set_contents_name, &buf, &len, &error);
1803 : 35 : g_assert_no_error (error);
1804 : 35 : g_assert_true (ret);
1805 : 35 : g_assert_cmpstr (buf, ==, "b");
1806 : 35 : g_assert_cmpuint (len, ==, 1);
1807 : 35 : g_free (buf);
1808 : :
1809 : 35 : g_assert_no_errno (g_lstat (set_contents_name, &statbuf));
1810 : :
1811 [ + + ]: 35 : if (tests[i].existing_file == EXISTING_FILE_NONE)
1812 : : {
1813 : 21 : int mode = statbuf.st_mode & ~S_IFMT;
1814 : 21 : int new_mode = tests[i].new_mode;
1815 : : #ifdef G_OS_WIN32
1816 : : /* on windows, group and others perms handling is different */
1817 : : /* only check the rwx user permissions */
1818 : : mode &= (_S_IREAD|_S_IWRITE|_S_IEXEC);
1819 : : new_mode &= (_S_IREAD|_S_IWRITE|_S_IEXEC);
1820 : : #endif
1821 : 21 : g_assert_cmpint (mode, ==, new_mode);
1822 : : }
1823 : :
1824 : : #ifndef G_OS_WIN32
1825 [ + + ]: 35 : if (tests[i].existing_file == EXISTING_FILE_SYMLINK)
1826 : : {
1827 : 7 : gchar *target_contents = NULL;
1828 : :
1829 : : /* If the @set_contents_name was a symlink, it should now be a
1830 : : * regular file, and the file it pointed to should not have
1831 : : * changed. */
1832 : 7 : g_assert_cmpint (statbuf.st_mode & S_IFMT, ==, S_IFREG);
1833 : :
1834 : 7 : g_file_get_contents (file_name, &target_contents, NULL, &error);
1835 : 7 : g_assert_no_error (error);
1836 : 7 : g_assert_cmpstr (target_contents, ==, original_contents);
1837 : :
1838 : 7 : g_free (target_contents);
1839 : : }
1840 : : #endif /* !G_OS_WIN32 */
1841 : : }
1842 : :
1843 [ + + ]: 42 : if (dir_name != NULL)
1844 : 7 : g_rmdir (dir_name);
1845 [ + + ]: 42 : if (link_name != NULL)
1846 : 7 : g_remove (link_name);
1847 [ + + ]: 42 : if (file_name != NULL)
1848 : 35 : g_remove (file_name);
1849 : :
1850 : 42 : g_free (dir_name);
1851 : 42 : g_free (link_name);
1852 : 42 : g_free (file_name);
1853 : : }
1854 : : }
1855 : 1 : }
1856 : :
1857 : : static void
1858 : 1 : test_set_contents_full_read_only_file (void)
1859 : : {
1860 : : gint fd;
1861 : 1 : GError *error = NULL;
1862 : 1 : gchar *file_name = NULL;
1863 : : gboolean ret;
1864 : 1 : gboolean can_override_dac = check_cap_dac_override (NULL);
1865 : :
1866 : 1 : g_test_summary ("Test g_file_set_contents_full() on a read-only file");
1867 : :
1868 : : /* Can’t test this with different #GFileSetContentsFlags as they all have
1869 : : * different behaviours wrt replacing the file while noticing/ignoring the
1870 : : * existing file permissions. */
1871 : 1 : fd = g_file_open_tmp (NULL, &file_name, &error);
1872 : 1 : g_assert_no_error (error);
1873 : 1 : g_assert_cmpint (write (fd, "a", 1), ==, 1);
1874 : 1 : g_assert_no_errno (g_fsync (fd));
1875 : 1 : close (fd);
1876 : 1 : g_assert_no_errno (g_chmod (file_name, 0400)); /* S_IREAD */
1877 : :
1878 [ + - ]: 1 : if (g_test_undefined ())
1879 : : {
1880 : 1 : g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
1881 : : "*assertion*!= NULL*");
1882 : 1 : ret = g_file_set_contents_full (NULL, "b", 1,
1883 : : G_FILE_SET_CONTENTS_NONE, 0644, &error);
1884 : 1 : g_assert_false (ret);
1885 : 1 : g_test_assert_expected_messages ();
1886 : :
1887 : 1 : g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
1888 : : "*assertion*!= NULL*");
1889 : 1 : ret = g_file_set_contents_full (file_name, NULL, 1,
1890 : : G_FILE_SET_CONTENTS_NONE, 0644, &error);
1891 : 1 : g_assert_false (ret);
1892 : 1 : g_test_assert_expected_messages ();
1893 : : }
1894 : :
1895 : : /* Set the file contents */
1896 : 1 : ret = g_file_set_contents_full (file_name, "b", 1, G_FILE_SET_CONTENTS_NONE, 0644, &error);
1897 : :
1898 [ - + ]: 1 : if (can_override_dac)
1899 : : {
1900 : 0 : g_assert_no_error (error);
1901 : 0 : g_assert_true (ret);
1902 : : }
1903 : : else
1904 : : {
1905 : 1 : g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_ACCES);
1906 : 1 : g_assert_false (ret);
1907 : : }
1908 : :
1909 : 1 : g_clear_error (&error);
1910 : :
1911 : 1 : g_remove (file_name);
1912 : :
1913 : 1 : g_free (file_name);
1914 : 1 : }
1915 : :
1916 : : static void
1917 : 1 : test_set_contents_full_read_only_directory (void)
1918 : : {
1919 : : #ifndef G_OS_WIN32
1920 : : /* windows mostly ignores read-only flagged directories, chmod doesn't work */
1921 : 1 : GFileSetContentsFlags flags_mask =
1922 : : G_FILE_SET_CONTENTS_ONLY_EXISTING |
1923 : : G_FILE_SET_CONTENTS_DURABLE |
1924 : : G_FILE_SET_CONTENTS_CONSISTENT;
1925 : : gint flags;
1926 : :
1927 : 1 : g_test_summary ("Test g_file_set_contents_full() on a file in a read-only directory");
1928 : :
1929 [ + + ]: 8 : for (flags = 0; flags < (gint) flags_mask; flags++)
1930 : : {
1931 : : gint fd;
1932 : 7 : GError *error = NULL;
1933 : 7 : gchar *dir_name = NULL;
1934 : 7 : gchar *file_name = NULL;
1935 : : gboolean ret;
1936 : : gboolean can_override_dac;
1937 : :
1938 : 7 : g_test_message ("Flags %d", flags);
1939 : :
1940 : 7 : dir_name = g_dir_make_tmp ("glib-file-set-contents-full-rodir-XXXXXX", &error);
1941 : 7 : g_assert_no_error (error);
1942 : 7 : can_override_dac = check_cap_dac_override (dir_name);
1943 : :
1944 : 7 : file_name = g_build_filename (dir_name, "file", NULL);
1945 : 7 : fd = g_open (file_name, O_CREAT | O_RDWR, 0644);
1946 : 7 : g_assert_cmpint (fd, >=, 0);
1947 : 7 : g_assert_cmpint (write (fd, "a", 1), ==, 1);
1948 : 7 : g_assert_no_errno (g_fsync (fd));
1949 : 7 : close (fd);
1950 : :
1951 : 7 : g_assert_no_errno (g_chmod (dir_name, 0));
1952 : :
1953 : : /* Set the file contents */
1954 : 7 : ret = g_file_set_contents_full (file_name, "b", 1, flags, 0644, &error);
1955 : :
1956 [ - + ]: 7 : if (can_override_dac)
1957 : : {
1958 : 0 : g_assert_no_error (error);
1959 : 0 : g_assert_true (ret);
1960 : : }
1961 : : else
1962 : : {
1963 : 7 : g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_ACCES);
1964 : 7 : g_assert_false (ret);
1965 : : }
1966 : :
1967 : 7 : g_clear_error (&error);
1968 : 7 : g_remove (file_name);
1969 : 7 : g_unlink (dir_name);
1970 : :
1971 : 7 : g_free (file_name);
1972 : 7 : g_free (dir_name);
1973 : : }
1974 : : #else
1975 : : g_test_skip ("Windows doesn’t support read-only directories in the same way as Unix");
1976 : : #endif
1977 : 1 : }
1978 : :
1979 : : static void
1980 : 1 : test_read_link (void)
1981 : : {
1982 : : #ifdef HAVE_READLINK
1983 : : #ifdef G_OS_UNIX
1984 : : int ret;
1985 : : FILE *file;
1986 : : gchar *cwd;
1987 : : gchar *data;
1988 : : gchar *newpath;
1989 : : gchar *badpath;
1990 : : gchar *path;
1991 : 1 : GError *error = NULL;
1992 : : const gchar *oldpath;
1993 : 1 : const gchar *filename = "file-test-data";
1994 : 1 : const gchar *link1 = "file-test-link1";
1995 : 1 : const gchar *link2 = "file-test-link2";
1996 : 1 : const gchar *link3 = "file-test-link3";
1997 : :
1998 [ + - ]: 1 : if (g_test_undefined ())
1999 : : {
2000 : 1 : g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
2001 : : "*assertion*!= NULL*");
2002 : 1 : newpath = g_file_read_link (NULL, &error);
2003 : 1 : g_assert_null (newpath);
2004 : 1 : g_test_assert_expected_messages ();
2005 : : }
2006 : :
2007 : 1 : cwd = g_get_current_dir ();
2008 : :
2009 : 1 : oldpath = g_test_get_filename (G_TEST_DIST, "4096-random-bytes", NULL);
2010 : 1 : newpath = g_build_filename (cwd, "page-of-junk", NULL);
2011 : 1 : badpath = g_build_filename (cwd, "4097-random-bytes", NULL);
2012 : 1 : remove (newpath);
2013 : 1 : ret = symlink (oldpath, newpath);
2014 : 1 : g_assert_cmpint (ret, ==, 0);
2015 : 1 : path = g_file_read_link (newpath, &error);
2016 : 1 : g_assert_no_error (error);
2017 : 1 : g_assert_cmpstr (path, ==, oldpath);
2018 : 1 : g_free (path);
2019 : :
2020 : 1 : remove (newpath);
2021 : 1 : ret = symlink (badpath, newpath);
2022 : 1 : g_assert_cmpint (ret, ==, 0);
2023 : 1 : path = g_file_read_link (newpath, &error);
2024 : 1 : g_assert_no_error (error);
2025 : 1 : g_assert_cmpstr (path, ==, badpath);
2026 : 1 : g_free (path);
2027 : :
2028 : 1 : path = g_file_read_link (oldpath, &error);
2029 : 1 : g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL);
2030 : 1 : g_assert_null (path);
2031 : 1 : g_error_free (error);
2032 : :
2033 : 1 : remove (newpath);
2034 : 1 : g_free (cwd);
2035 : 1 : g_free (newpath);
2036 : 1 : g_free (badpath);
2037 : :
2038 : 1 : file = fopen (filename, "w");
2039 : 1 : g_assert_nonnull (file);
2040 : 1 : fclose (file);
2041 : :
2042 : 1 : g_assert_no_errno (symlink (filename, link1));
2043 : 1 : g_assert_no_errno (symlink (link1, link2));
2044 : :
2045 : 1 : error = NULL;
2046 : 1 : data = g_file_read_link (link1, &error);
2047 : 1 : g_assert_nonnull (data);
2048 : 1 : g_assert_cmpstr (data, ==, filename);
2049 : 1 : g_assert_no_error (error);
2050 : 1 : g_free (data);
2051 : :
2052 : 1 : error = NULL;
2053 : 1 : data = g_file_read_link (link2, &error);
2054 : 1 : g_assert_nonnull (data);
2055 : 1 : g_assert_cmpstr (data, ==, link1);
2056 : 1 : g_assert_no_error (error);
2057 : 1 : g_free (data);
2058 : :
2059 : 1 : error = NULL;
2060 : 1 : data = g_file_read_link (link3, &error);
2061 : 1 : g_assert_null (data);
2062 : 1 : g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_NOENT);
2063 : 1 : g_error_free (error);
2064 : :
2065 : 1 : error = NULL;
2066 : 1 : data = g_file_read_link (filename, &error);
2067 : 1 : g_assert_null (data);
2068 : 1 : g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL);
2069 : 1 : g_error_free (error);
2070 : :
2071 : 1 : remove (filename);
2072 : 1 : remove (link1);
2073 : 1 : remove (link2);
2074 : : #endif
2075 : : #else
2076 : : g_test_skip ("Symbolic links not supported");
2077 : : #endif
2078 : 1 : }
2079 : :
2080 : : static void
2081 : 1 : test_stdio_wrappers (void)
2082 : : {
2083 : : GStatBuf buf;
2084 : : gchar *cwd, *path;
2085 : : gint ret;
2086 : : struct utimbuf ut;
2087 : 1 : GError *error = NULL;
2088 : : GStatBuf path_statbuf, cwd_statbuf;
2089 : : time_t now;
2090 : : #ifdef G_OS_UNIX
2091 : : gboolean have_cap_dac_override;
2092 : : #endif
2093 : :
2094 : 1 : g_remove ("mkdir-test/test-create");
2095 : 1 : ret = g_rmdir ("mkdir-test");
2096 : 1 : g_assert (ret == 0 || errno == ENOENT);
2097 : :
2098 : 1 : ret = g_stat ("mkdir-test", &buf);
2099 : 1 : g_assert_cmpint (ret, ==, -1);
2100 : 1 : ret = g_mkdir ("mkdir-test", 0666);
2101 : 1 : g_assert_cmpint (ret, ==, 0);
2102 : 1 : ret = g_stat ("mkdir-test", &buf);
2103 : 1 : g_assert_cmpint (ret, ==, 0);
2104 : 1 : g_assert_cmpint (S_ISDIR (buf.st_mode), !=, 0);
2105 : :
2106 : 1 : cwd = g_get_current_dir ();
2107 : 1 : path = g_build_filename (cwd, "mkdir-test", NULL);
2108 : : #ifdef G_OS_UNIX
2109 : 1 : have_cap_dac_override = check_cap_dac_override (cwd);
2110 : : #endif
2111 : 1 : g_free (cwd);
2112 : :
2113 : : /* 0666 on directories means nothing to Windows, it only obeys ACLs.
2114 : : * It doesn't necessarily mean anything on Unix either: if we have
2115 : : * Linux CAP_DAC_OVERRIDE or equivalent (in particular if we're root),
2116 : : * then we ignore filesystem permissions. */
2117 : : #ifdef G_OS_UNIX
2118 [ - + ]: 1 : if (have_cap_dac_override)
2119 : : {
2120 : 0 : g_test_message ("Cannot test g_chdir() failing with EACCES: we "
2121 : : "probably have CAP_DAC_OVERRIDE or equivalent");
2122 : : }
2123 : : else
2124 : : {
2125 : 1 : ret = g_chdir (path);
2126 : 1 : g_assert_cmpint (ret == 0 ? 0 : errno, ==, EACCES);
2127 : 1 : g_assert_cmpint (ret, ==, -1);
2128 : : }
2129 : : #else
2130 : : g_test_message ("Cannot test g_chdir() failing with EACCES: "
2131 : : "it's Unix-specific behaviour");
2132 : : #endif
2133 : :
2134 : 1 : ret = g_chmod (path, 0777);
2135 : 1 : g_assert_cmpint (ret, ==, 0);
2136 : 1 : ret = g_chdir (path);
2137 : 1 : g_assert_cmpint (ret, ==, 0);
2138 : 1 : cwd = g_get_current_dir ();
2139 : : /* We essentially want to check that cwd == path, but we can’t compare the
2140 : : * paths directly since the tests might be running under a symlink (for
2141 : : * example, /tmp is sometimes a symlink). Compare the inode numbers instead. */
2142 : 1 : g_assert_cmpint (g_stat (cwd, &cwd_statbuf), ==, 0);
2143 : 1 : g_assert_cmpint (g_stat (path, &path_statbuf), ==, 0);
2144 : 1 : g_assert_true (cwd_statbuf.st_dev == path_statbuf.st_dev &&
2145 : : cwd_statbuf.st_ino == path_statbuf.st_ino);
2146 : 1 : g_free (cwd);
2147 : 1 : g_free (path);
2148 : :
2149 : 1 : ret = g_creat ("test-creat", G_TEST_DIR_MODE);
2150 : 1 : g_close (ret, &error);
2151 : 1 : g_assert_no_error (error);
2152 : :
2153 : 1 : ret = g_access ("test-creat", F_OK);
2154 : 1 : g_assert_cmpint (ret, ==, 0);
2155 : :
2156 : 1 : ret = g_rename ("test-creat", "test-create");
2157 : 1 : g_assert_cmpint (ret, ==, 0);
2158 : :
2159 : 1 : ret = g_open ("test-create", O_RDONLY, 0666);
2160 : 1 : g_close (ret, &error);
2161 : 1 : g_assert_no_error (error);
2162 : :
2163 : : #ifdef G_OS_WIN32
2164 : : /* On Windows the 5 permission bit results in a read-only file
2165 : : * that cannot be modified in any way (attribute changes included).
2166 : : * Remove the read-only attribute via chmod().
2167 : : */
2168 : : ret = g_chmod ("test-create", 0666);
2169 : : g_assert_cmpint (ret, ==, 0);
2170 : : #endif
2171 : :
2172 : 1 : now = time (NULL);
2173 : :
2174 : 1 : ut.actime = ut.modtime = now;
2175 : 1 : ret = g_utime ("test-create", &ut);
2176 : 1 : g_assert_cmpint (ret, ==, 0);
2177 : :
2178 : 1 : ret = g_lstat ("test-create", &buf);
2179 : 1 : g_assert_cmpint (ret, ==, 0);
2180 : 1 : g_assert_cmpint (buf.st_atime, ==, now);
2181 : 1 : g_assert_cmpint (buf.st_mtime, ==, now);
2182 : :
2183 : 1 : g_chdir ("..");
2184 : 1 : g_remove ("mkdir-test/test-create");
2185 : 1 : g_rmdir ("mkdir-test");
2186 : 1 : }
2187 : :
2188 : : /* Win32 does not support "wb+", but g_fopen() should automatically
2189 : : * translate this mode to its alias "w+b".
2190 : : * Also check various other file open modes for correct support across
2191 : : * platforms.
2192 : : * See: https://gitlab.gnome.org/GNOME/glib/merge_requests/119
2193 : : */
2194 : : static void
2195 : 1 : test_fopen_modes (void)
2196 : : {
2197 : 1 : char *path = g_build_filename ("temp-fopen", NULL);
2198 : : gsize i;
2199 : 1 : const gchar *modes[] =
2200 : : {
2201 : : "w",
2202 : : "r",
2203 : : "a",
2204 : : "w+",
2205 : : "r+",
2206 : : "a+",
2207 : : "wb",
2208 : : "rb",
2209 : : "ab",
2210 : : "w+b",
2211 : : "r+b",
2212 : : "a+b",
2213 : : "wb+",
2214 : : "rb+",
2215 : : "ab+"
2216 : : };
2217 : :
2218 : 1 : g_test_bug ("https://gitlab.gnome.org/GNOME/glib/merge_requests/119");
2219 : :
2220 [ - + ]: 1 : if (g_file_test (path, G_FILE_TEST_EXISTS))
2221 : 0 : g_error ("failed, %s exists, cannot test g_fopen()", path);
2222 : :
2223 [ + + ]: 16 : for (i = 0; i < G_N_ELEMENTS (modes); i++)
2224 : : {
2225 : : FILE *f;
2226 : :
2227 : 15 : g_test_message ("Testing fopen() mode '%s'", modes[i]);
2228 : :
2229 : 15 : f = g_fopen (path, modes[i]);
2230 : 15 : g_assert_nonnull (f);
2231 : 15 : fclose (f);
2232 : : }
2233 : :
2234 : 1 : g_remove (path);
2235 : 1 : g_free (path);
2236 : 1 : }
2237 : :
2238 : : #ifdef G_OS_WIN32
2239 : : #include "../gstdio-private.c"
2240 : :
2241 : : static int
2242 : : g_wcscmp0 (const gunichar2 *str1,
2243 : : const gunichar2 *str2)
2244 : : {
2245 : : if (!str1)
2246 : : return -(str1 != str2);
2247 : : if (!str2)
2248 : : return str1 != str2;
2249 : : return wcscmp (str1, str2);
2250 : : }
2251 : :
2252 : : #define g_assert_cmpwcs(s1, cmp, s2, s1u8, s2u8) \
2253 : : G_STMT_START { \
2254 : : const gunichar2 *__s1 = (s1), *__s2 = (s2); \
2255 : : if (g_wcscmp0 (__s1, __s2) cmp 0) ; else \
2256 : : g_assertion_message_cmpstr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
2257 : : #s1u8 " " #cmp " " #s2u8, s1u8, #cmp, s2u8); \
2258 : : } G_STMT_END
2259 : :
2260 : : static void
2261 : : test_win32_pathstrip (void)
2262 : : {
2263 : : gunichar2 *buf;
2264 : : gsize i;
2265 : : #define IDENTITY_TEST(x) { x, x, FALSE }
2266 : : struct
2267 : : {
2268 : : gunichar2 *in;
2269 : : gunichar2 *out;
2270 : : gboolean result;
2271 : : } testcases[] = {
2272 : : IDENTITY_TEST (L"\\\\?\\V"),
2273 : : IDENTITY_TEST (L"\\\\?\\Vo"),
2274 : : IDENTITY_TEST (L"\\\\?\\Volume{0700f3d3-6d24-11e3-8b2f-806e6f6e6963}\\"),
2275 : : IDENTITY_TEST (L"\\??\\V"),
2276 : : IDENTITY_TEST (L"\\??\\Vo"),
2277 : : IDENTITY_TEST (L"\\??\\Volume{0700f3d3-6d24-11e3-8b2f-806e6f6e6963}\\"),
2278 : : IDENTITY_TEST (L"\\\\?\\\x0441:\\"),
2279 : : IDENTITY_TEST (L"\\??\\\x0441:\\"),
2280 : : IDENTITY_TEST (L"a:\\"),
2281 : : IDENTITY_TEST (L"a:\\b\\c"),
2282 : : IDENTITY_TEST (L"x"),
2283 : : #undef IDENTITY_TEST
2284 : : {
2285 : : L"\\\\?\\c:\\",
2286 : : L"c:\\",
2287 : : TRUE,
2288 : : },
2289 : : {
2290 : : L"\\\\?\\C:\\",
2291 : : L"C:\\",
2292 : : TRUE,
2293 : : },
2294 : : {
2295 : : L"\\\\?\\c:\\",
2296 : : L"c:\\",
2297 : : TRUE,
2298 : : },
2299 : : {
2300 : : L"\\\\?\\C:\\",
2301 : : L"C:\\",
2302 : : TRUE,
2303 : : },
2304 : : {
2305 : : L"\\\\?\\C:\\",
2306 : : L"C:\\",
2307 : : TRUE,
2308 : : },
2309 : : { 0, }
2310 : : };
2311 : :
2312 : : for (i = 0; testcases[i].in; i++)
2313 : : {
2314 : : gsize str_len = wcslen (testcases[i].in) + 1;
2315 : : gchar *in_u8 = g_utf16_to_utf8 (testcases[i].in, -1, NULL, NULL, NULL);
2316 : : gchar *out_u8 = g_utf16_to_utf8 (testcases[i].out, -1, NULL, NULL, NULL);
2317 : :
2318 : : g_assert_nonnull (in_u8);
2319 : : g_assert_nonnull (out_u8);
2320 : :
2321 : : buf = g_new0 (gunichar2, str_len);
2322 : : memcpy (buf, testcases[i].in, str_len * sizeof (gunichar2));
2323 : : _g_win32_strip_extended_ntobjm_prefix (buf, &str_len);
2324 : : g_assert_cmpwcs (buf, ==, testcases[i].out, in_u8, out_u8);
2325 : : g_free (buf);
2326 : : g_free (in_u8);
2327 : : g_free (out_u8);
2328 : : }
2329 : : /* Check for correct behaviour on non-NUL-terminated strings */
2330 : : for (i = 0; testcases[i].in; i++)
2331 : : {
2332 : : gsize str_len = wcslen (testcases[i].in) + 1;
2333 : : wchar_t old_endchar;
2334 : : gchar *in_u8 = g_utf16_to_utf8 (testcases[i].in, -1, NULL, NULL, NULL);
2335 : : gchar *out_u8 = g_utf16_to_utf8 (testcases[i].out, -1, NULL, NULL, NULL);
2336 : :
2337 : : g_assert_nonnull (in_u8);
2338 : : g_assert_nonnull (out_u8);
2339 : :
2340 : : buf = g_new0 (gunichar2, str_len);
2341 : : memcpy (buf, testcases[i].in, (str_len) * sizeof (gunichar2));
2342 : :
2343 : : old_endchar = buf[wcslen (testcases[i].out)];
2344 : : str_len -= 1;
2345 : :
2346 : : if (testcases[i].result)
2347 : : {
2348 : : /* Given "\\\\?\\C:\\" (len 7, unterminated),
2349 : : * we should get "C:\\" (len 3, unterminated).
2350 : : * Put a character different from "\\" (4-th character of the buffer)
2351 : : * at the end of the unterminated source buffer, into a position
2352 : : * where NUL-terminator would normally be. Then later test that 4-th character
2353 : : * in the buffer is still the old "\\".
2354 : : * After that terminate the string and use normal g_wcscmp0().
2355 : : */
2356 : : buf[str_len] = old_endchar - 1;
2357 : : }
2358 : :
2359 : : _g_win32_strip_extended_ntobjm_prefix (buf, &str_len);
2360 : : g_assert_cmpuint (old_endchar, ==, buf[wcslen (testcases[i].out)]);
2361 : : buf[str_len] = L'\0';
2362 : : g_assert_cmpwcs (buf, ==, testcases[i].out, in_u8, out_u8);
2363 : : g_free (buf);
2364 : : g_free (in_u8);
2365 : : g_free (out_u8);
2366 : : }
2367 : : }
2368 : :
2369 : : #define g_assert_memcmp(m1, cmp, m2, memlen, m1hex, m2hex, testcase_num) \
2370 : : G_STMT_START { \
2371 : : if (memcmp (m1, m2, memlen) cmp 0); else \
2372 : : g_assertion_message_cmpstr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
2373 : : #m1hex " " #cmp " " #m2hex, m1hex, #cmp, m2hex); \
2374 : : } G_STMT_END
2375 : :
2376 : : static gchar *
2377 : : to_hex (const guchar *buf,
2378 : : gsize len)
2379 : : {
2380 : : gsize i;
2381 : : GString *s = g_string_new (NULL);
2382 : : if (len > 0)
2383 : : g_string_append_printf (s, "%02x", buf[0]);
2384 : : for (i = 1; i < len; i++)
2385 : : g_string_append_printf (s, " %02x", buf[i]);
2386 : : return g_string_free (s, FALSE);
2387 : : }
2388 : :
2389 : : static void
2390 : : test_win32_zero_terminate_symlink (void)
2391 : : {
2392 : : gsize i;
2393 : : #define TESTCASE(data, len_mod, use_buf, buf_size, terminate, reported_len, returned_string) \
2394 : : { (const guchar *) data, wcslen (data) * 2 + len_mod, use_buf, buf_size, terminate, reported_len, (guchar *) returned_string},
2395 : :
2396 : : struct
2397 : : {
2398 : : const guchar *data;
2399 : : gsize data_size;
2400 : : gboolean use_buf;
2401 : : gsize buf_size;
2402 : : gboolean terminate;
2403 : : int reported_len;
2404 : : const guchar *returned_string;
2405 : : } testcases[] = {
2406 : : TESTCASE (L"foobar", +2, TRUE, 12 + 4, FALSE, 12 + 2, "f\0o\0o\0b\0a\0r\0\0\0")
2407 : : TESTCASE (L"foobar", +2, TRUE, 12 + 3, FALSE, 12 + 2, "f\0o\0o\0b\0a\0r\0\0\0")
2408 : : TESTCASE (L"foobar", +2, TRUE, 12 + 2, FALSE, 12 + 2, "f\0o\0o\0b\0a\0r\0\0\0")
2409 : : TESTCASE (L"foobar", +2, TRUE, 12 + 1, FALSE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
2410 : : TESTCASE (L"foobar", +2, TRUE, 12 + 0, FALSE, 12 + 0, "f\0o\0o\0b\0a\0r\0")
2411 : : TESTCASE (L"foobar", +2, TRUE, 12 - 1, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
2412 : : TESTCASE (L"foobar", +2, TRUE, 12 - 2, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
2413 : : TESTCASE (L"foobar", +2, TRUE, 12 - 3, FALSE, 12 - 3, "f\0o\0o\0b\0a")
2414 : : TESTCASE (L"foobar", +1, TRUE, 12 + 4, FALSE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
2415 : : TESTCASE (L"foobar", +1, TRUE, 12 + 3, FALSE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
2416 : : TESTCASE (L"foobar", +1, TRUE, 12 + 2, FALSE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
2417 : : TESTCASE (L"foobar", +1, TRUE, 12 + 1, FALSE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
2418 : : TESTCASE (L"foobar", +1, TRUE, 12 + 0, FALSE, 12 + 0, "f\0o\0o\0b\0a\0r\0")
2419 : : TESTCASE (L"foobar", +1, TRUE, 12 - 1, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
2420 : : TESTCASE (L"foobar", +1, TRUE, 12 - 2, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
2421 : : TESTCASE (L"foobar", +1, TRUE, 12 - 3, FALSE, 12 - 3, "f\0o\0o\0b\0a")
2422 : : TESTCASE (L"foobar", +0, TRUE, 12 + 4, FALSE, 12 + 0, "f\0o\0o\0b\0a\0r\0")
2423 : : TESTCASE (L"foobar", +0, TRUE, 12 + 3, FALSE, 12 + 0, "f\0o\0o\0b\0a\0r\0")
2424 : : TESTCASE (L"foobar", +0, TRUE, 12 + 2, FALSE, 12 + 0, "f\0o\0o\0b\0a\0r\0")
2425 : : TESTCASE (L"foobar", +0, TRUE, 12 + 1, FALSE, 12 + 0, "f\0o\0o\0b\0a\0r\0")
2426 : : TESTCASE (L"foobar", +0, TRUE, 12 + 0, FALSE, 12 + 0, "f\0o\0o\0b\0a\0r\0")
2427 : : TESTCASE (L"foobar", +0, TRUE, 12 - 1, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
2428 : : TESTCASE (L"foobar", +0, TRUE, 12 - 2, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
2429 : : TESTCASE (L"foobar", +0, TRUE, 12 - 3, FALSE, 12 - 3, "f\0o\0o\0b\0a")
2430 : : TESTCASE (L"foobar", -1, TRUE, 12 + 3, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
2431 : : TESTCASE (L"foobar", -1, TRUE, 12 + 2, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
2432 : : TESTCASE (L"foobar", -1, TRUE, 12 + 1, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
2433 : : TESTCASE (L"foobar", -1, TRUE, 12 + 0, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
2434 : : TESTCASE (L"foobar", -1, TRUE, 12 - 1, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
2435 : : TESTCASE (L"foobar", -1, TRUE, 12 - 2, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
2436 : : TESTCASE (L"foobar", -1, TRUE, 12 - 3, FALSE, 12 - 3, "f\0o\0o\0b\0a")
2437 : : TESTCASE (L"foobar", -1, TRUE, 12 - 4, FALSE, 12 - 4, "f\0o\0o\0b\0")
2438 : : TESTCASE (L"foobar", -2, TRUE, 12 + 2, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
2439 : : TESTCASE (L"foobar", -2, TRUE, 12 + 1, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
2440 : : TESTCASE (L"foobar", -2, TRUE, 12 + 0, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
2441 : : TESTCASE (L"foobar", -2, TRUE, 12 - 1, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
2442 : : TESTCASE (L"foobar", -2, TRUE, 12 - 2, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
2443 : : TESTCASE (L"foobar", -2, TRUE, 12 - 3, FALSE, 12 - 3, "f\0o\0o\0b\0a")
2444 : : TESTCASE (L"foobar", -2, TRUE, 12 - 4, FALSE, 12 - 4, "f\0o\0o\0b\0")
2445 : : TESTCASE (L"foobar", -2, TRUE, 12 - 5, FALSE, 12 - 5, "f\0o\0o\0b")
2446 : : TESTCASE (L"foobar", +2, TRUE, 12 + 4, TRUE, 12 + 2, "f\0o\0o\0b\0a\0r\0\0\0")
2447 : : TESTCASE (L"foobar", +2, TRUE, 12 + 3, TRUE, 12 + 2, "f\0o\0o\0b\0a\0r\0\0\0")
2448 : : TESTCASE (L"foobar", +2, TRUE, 12 + 2, TRUE, 12 + 2, "f\0o\0o\0b\0a\0r\0\0\0")
2449 : : TESTCASE (L"foobar", +2, TRUE, 12 + 1, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
2450 : : TESTCASE (L"foobar", +2, TRUE, 12 + 0, TRUE, 12 + 0, "f\0o\0o\0b\0a\0\0\0")
2451 : : TESTCASE (L"foobar", +2, TRUE, 12 - 1, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
2452 : : TESTCASE (L"foobar", +2, TRUE, 12 - 2, TRUE, 12 - 2, "f\0o\0o\0b\0\0\0")
2453 : : TESTCASE (L"foobar", +2, TRUE, 12 - 3, TRUE, 12 - 3, "f\0o\0o\0b\0\0")
2454 : : TESTCASE (L"foobar", +1, TRUE, 12 + 4, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
2455 : : TESTCASE (L"foobar", +1, TRUE, 12 + 3, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
2456 : : TESTCASE (L"foobar", +1, TRUE, 12 + 2, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
2457 : : TESTCASE (L"foobar", +1, TRUE, 12 + 1, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
2458 : : TESTCASE (L"foobar", +1, TRUE, 12 + 0, TRUE, 12 + 0, "f\0o\0o\0b\0a\0\0\0")
2459 : : TESTCASE (L"foobar", +1, TRUE, 12 - 1, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
2460 : : TESTCASE (L"foobar", +1, TRUE, 12 - 2, TRUE, 12 - 2, "f\0o\0o\0b\0\0\0")
2461 : : TESTCASE (L"foobar", +1, TRUE, 12 - 3, TRUE, 12 - 3, "f\0o\0o\0b\0\0")
2462 : : TESTCASE (L"foobar", +0, TRUE, 12 + 4, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
2463 : : TESTCASE (L"foobar", +0, TRUE, 12 + 3, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
2464 : : TESTCASE (L"foobar", +0, TRUE, 12 + 2, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
2465 : : TESTCASE (L"foobar", +0, TRUE, 12 + 1, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
2466 : : TESTCASE (L"foobar", +0, TRUE, 12 + 0, TRUE, 12 + 0, "f\0o\0o\0b\0a\0\0\0")
2467 : : TESTCASE (L"foobar", +0, TRUE, 12 - 1, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
2468 : : TESTCASE (L"foobar", +0, TRUE, 12 - 2, TRUE, 12 - 2, "f\0o\0o\0b\0\0\0")
2469 : : TESTCASE (L"foobar", +0, TRUE, 12 - 3, TRUE, 12 - 3, "f\0o\0o\0b\0\0")
2470 : : TESTCASE (L"foobar", -1, TRUE, 12 + 3, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
2471 : : TESTCASE (L"foobar", -1, TRUE, 12 + 2, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
2472 : : TESTCASE (L"foobar", -1, TRUE, 12 + 1, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
2473 : : TESTCASE (L"foobar", -1, TRUE, 12 + 0, TRUE, 12 + 0, "f\0o\0o\0b\0a\0\0\0")
2474 : : TESTCASE (L"foobar", -1, TRUE, 12 - 1, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
2475 : : TESTCASE (L"foobar", -1, TRUE, 12 - 2, TRUE, 12 - 2, "f\0o\0o\0b\0\0\0")
2476 : : TESTCASE (L"foobar", -1, TRUE, 12 - 3, TRUE, 12 - 3, "f\0o\0o\0b\0\0")
2477 : : TESTCASE (L"foobar", -1, TRUE, 12 - 4, TRUE, 12 - 4, "f\0o\0o\0\0\0")
2478 : : TESTCASE (L"foobar", -2, TRUE, 12 + 2, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
2479 : : TESTCASE (L"foobar", -2, TRUE, 12 + 1, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
2480 : : TESTCASE (L"foobar", -2, TRUE, 12 + 0, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
2481 : : TESTCASE (L"foobar", -2, TRUE, 12 - 1, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
2482 : : TESTCASE (L"foobar", -2, TRUE, 12 - 2, TRUE, 12 - 2, "f\0o\0o\0b\0\0\0")
2483 : : TESTCASE (L"foobar", -2, TRUE, 12 - 3, TRUE, 12 - 3, "f\0o\0o\0b\0\0")
2484 : : TESTCASE (L"foobar", -2, TRUE, 12 - 4, TRUE, 12 - 4, "f\0o\0o\0\0\0")
2485 : : TESTCASE (L"foobar", -2, TRUE, 12 - 5, TRUE, 12 - 5, "f\0o\0o\0\0")
2486 : : TESTCASE (L"foobar", +2, FALSE, 0, FALSE, 12 + 2, "f\0o\0o\0b\0a\0r\0\0\0")
2487 : : TESTCASE (L"foobar", +1, FALSE, 0, FALSE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
2488 : : TESTCASE (L"foobar", +0, FALSE, 0, FALSE, 12 + 0, "f\0o\0o\0b\0a\0r\0")
2489 : : TESTCASE (L"foobar", -1, FALSE, 0, FALSE, 12 - 1, "f\0o\0o\0b\0a\0r")
2490 : : TESTCASE (L"foobar", -2, FALSE, 0, FALSE, 12 - 2, "f\0o\0o\0b\0a\0")
2491 : : TESTCASE (L"foobar", +2, FALSE, 0, TRUE, 12 + 2, "f\0o\0o\0b\0a\0r\0\0\0")
2492 : : TESTCASE (L"foobar", +1, FALSE, 0, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
2493 : : TESTCASE (L"foobar", +0, FALSE, 0, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
2494 : : TESTCASE (L"foobar", -1, FALSE, 0, TRUE, 12 + 1, "f\0o\0o\0b\0a\0r\0\0")
2495 : : TESTCASE (L"foobar", -2, FALSE, 0, TRUE, 12 - 1, "f\0o\0o\0b\0a\0\0")
2496 : : TESTCASE (L"x", +2, TRUE, 2 + 4, FALSE, 2 + 2, "x\0\0\0")
2497 : : TESTCASE (L"x", +2, TRUE, 2 + 3, FALSE, 2 + 2, "x\0\0\0")
2498 : : TESTCASE (L"x", +2, TRUE, 2 + 2, FALSE, 2 + 2, "x\0\0\0")
2499 : : TESTCASE (L"x", +2, TRUE, 2 + 1, FALSE, 2 + 1, "x\0\0")
2500 : : TESTCASE (L"x", +2, TRUE, 2 + 0, FALSE, 2 + 0, "x\0")
2501 : : TESTCASE (L"x", +2, TRUE, 2 - 1, FALSE, 2 - 1, "x")
2502 : : TESTCASE (L"x", +2, TRUE, 2 - 2, FALSE, 2 - 2, "")
2503 : : TESTCASE (L"x", +1, TRUE, 2 + 3, FALSE, 2 + 1, "x\0\0")
2504 : : TESTCASE (L"x", +1, TRUE, 2 + 2, FALSE, 2 + 1, "x\0\0")
2505 : : TESTCASE (L"x", +1, TRUE, 2 + 1, FALSE, 2 + 1, "x\0\0")
2506 : : TESTCASE (L"x", +1, TRUE, 2 + 0, FALSE, 2 + 0, "x\0")
2507 : : TESTCASE (L"x", +1, TRUE, 2 - 1, FALSE, 2 - 1, "x")
2508 : : TESTCASE (L"x", +1, TRUE, 2 - 2, FALSE, 2 - 2, "")
2509 : : TESTCASE (L"x", +0, TRUE, 2 + 2, FALSE, 2 + 0, "x\0")
2510 : : TESTCASE (L"x", +0, TRUE, 2 + 1, FALSE, 2 + 0, "x\0")
2511 : : TESTCASE (L"x", +0, TRUE, 2 + 0, FALSE, 2 + 0, "x\0")
2512 : : TESTCASE (L"x", +0, TRUE, 2 - 1, FALSE, 2 - 1, "x")
2513 : : TESTCASE (L"x", +0, TRUE, 2 - 2, FALSE, 2 - 2, "")
2514 : : TESTCASE (L"x", -1, TRUE, 2 + 1, FALSE, 2 - 1, "x")
2515 : : TESTCASE (L"x", -1, TRUE, 2 + 0, FALSE, 2 - 1, "x")
2516 : : TESTCASE (L"x", -1, TRUE, 2 - 1, FALSE, 2 - 1, "x")
2517 : : TESTCASE (L"x", -1, TRUE, 2 - 2, FALSE, 2 - 2, "")
2518 : : TESTCASE (L"x", -2, TRUE, 2 + 0, FALSE, 2 - 2, "")
2519 : : TESTCASE (L"x", -2, TRUE, 2 - 1, FALSE, 2 - 2, "")
2520 : : TESTCASE (L"x", -2, TRUE, 2 - 2, FALSE, 2 - 2, "")
2521 : : TESTCASE (L"x", +2, TRUE, 2 + 4, TRUE, 2 + 2, "x\0\0\0")
2522 : : TESTCASE (L"x", +2, TRUE, 2 + 3, TRUE, 2 + 2, "x\0\0\0")
2523 : : TESTCASE (L"x", +2, TRUE, 2 + 2, TRUE, 2 + 2, "x\0\0\0")
2524 : : TESTCASE (L"x", +2, TRUE, 2 + 1, TRUE, 2 + 1, "x\0\0")
2525 : : TESTCASE (L"x", +2, TRUE, 2 + 0, TRUE, 2 + 0, "\0\0")
2526 : : TESTCASE (L"x", +2, TRUE, 2 - 1, TRUE, 2 - 1, "\0")
2527 : : TESTCASE (L"x", +2, TRUE, 2 - 2, TRUE, 2 - 2, "")
2528 : : TESTCASE (L"x", +1, TRUE, 2 + 3, TRUE, 2 + 1, "x\0\0")
2529 : : TESTCASE (L"x", +1, TRUE, 2 + 2, TRUE, 2 + 1, "x\0\0")
2530 : : TESTCASE (L"x", +1, TRUE, 2 + 1, TRUE, 2 + 1, "x\0\0")
2531 : : TESTCASE (L"x", +1, TRUE, 2 + 0, TRUE, 2 + 0, "\0\0")
2532 : : TESTCASE (L"x", +1, TRUE, 2 - 1, TRUE, 2 - 1, "\0")
2533 : : TESTCASE (L"x", +1, TRUE, 2 - 2, TRUE, 2 - 2, "")
2534 : : TESTCASE (L"x", +0, TRUE, 2 + 2, TRUE, 2 + 1, "x\0\0")
2535 : : TESTCASE (L"x", +0, TRUE, 2 + 1, TRUE, 2 + 1, "x\0\0")
2536 : : TESTCASE (L"x", +0, TRUE, 2 + 0, TRUE, 2 + 0, "\0\0")
2537 : : TESTCASE (L"x", +0, TRUE, 2 - 1, TRUE, 2 - 1, "\0")
2538 : : TESTCASE (L"x", +0, TRUE, 2 - 2, TRUE, 2 - 2, "")
2539 : : TESTCASE (L"x", -1, TRUE, 2 + 1, TRUE, 2 + 1, "x\0\0")
2540 : : TESTCASE (L"x", -1, TRUE, 2 + 0, TRUE, 2 + 0, "\0\0")
2541 : : TESTCASE (L"x", -1, TRUE, 2 - 1, TRUE, 2 - 1, "\0")
2542 : : TESTCASE (L"x", -1, TRUE, 2 - 2, TRUE, 2 - 2, "")
2543 : : TESTCASE (L"x", -2, TRUE, 2 + 0, TRUE, 2 - 2, "")
2544 : : TESTCASE (L"x", -2, TRUE, 2 - 1, TRUE, 2 - 2, "")
2545 : : TESTCASE (L"x", -2, TRUE, 2 - 2, TRUE, 2 - 2, "")
2546 : : TESTCASE (L"x", +2, FALSE, 0, FALSE, 2 + 2, "x\0\0\0")
2547 : : TESTCASE (L"x", +1, FALSE, 0, FALSE, 2 + 1, "x\0\0")
2548 : : TESTCASE (L"x", +0, FALSE, 0, FALSE, 2 + 0, "x\0")
2549 : : TESTCASE (L"x", -1, FALSE, 0, FALSE, 2 - 1, "x")
2550 : : TESTCASE (L"x", -2, FALSE, 0, FALSE, 2 - 2, "")
2551 : : TESTCASE (L"x", +2, FALSE, 0, TRUE, 2 + 2, "x\0\0\0")
2552 : : TESTCASE (L"x", +1, FALSE, 0, TRUE, 2 + 1, "x\0\0")
2553 : : TESTCASE (L"x", +0, FALSE, 0, TRUE, 2 + 1, "x\0\0")
2554 : : TESTCASE (L"x", -1, FALSE, 0, TRUE, 2 + 1, "x\0\0")
2555 : : TESTCASE (L"x", -2, FALSE, 0, TRUE, 2 - 2, "")
2556 : : { 0, },
2557 : : };
2558 : : #undef TESTCASE
2559 : :
2560 : : for (i = 0; testcases[i].data != NULL; i++)
2561 : : {
2562 : : gunichar2 *buf;
2563 : : int result;
2564 : : gchar *buf_hex, *expected_hex;
2565 : : if (testcases[i].use_buf)
2566 : : buf = g_malloc0 (testcases[i].buf_size + 1); /* +1 to ensure it succeeds with buf_size == 0 */
2567 : : else
2568 : : buf = NULL;
2569 : : result = _g_win32_copy_and_maybe_terminate (testcases[i].data,
2570 : : testcases[i].data_size,
2571 : : testcases[i].use_buf ? buf : NULL,
2572 : : testcases[i].buf_size,
2573 : : testcases[i].use_buf ? NULL : &buf,
2574 : : testcases[i].terminate);
2575 : : if (testcases[i].reported_len != result)
2576 : : g_error ("Test %" G_GSIZE_FORMAT " failed, result %d != %d", i, result, testcases[i].reported_len);
2577 : : if (buf == NULL && testcases[i].buf_size != 0)
2578 : : g_error ("Test %" G_GSIZE_FORMAT " failed, buf == NULL", i);
2579 : : g_assert_cmpint (testcases[i].reported_len, ==, result);
2580 : : if ((testcases[i].use_buf && testcases[i].buf_size != 0) ||
2581 : : (!testcases[i].use_buf && testcases[i].reported_len != 0))
2582 : : {
2583 : : g_assert_nonnull (buf);
2584 : : buf_hex = to_hex ((const guchar *) buf, result);
2585 : : expected_hex = to_hex (testcases[i].returned_string, testcases[i].reported_len);
2586 : : if (memcmp (buf, testcases[i].returned_string, result) != 0)
2587 : : g_error ("Test %" G_GSIZE_FORMAT " failed:\n%s !=\n%s", i, buf_hex, expected_hex);
2588 : : g_assert_memcmp (buf, ==, testcases[i].returned_string, testcases[i].reported_len, buf_hex, expected_hex, testcases[i].line);
2589 : : g_free (buf_hex);
2590 : : g_free (expected_hex);
2591 : : }
2592 : : g_free (buf);
2593 : : }
2594 : : }
2595 : :
2596 : : #endif
2597 : :
2598 : : static void
2599 : 1 : test_clear_fd_ebadf (void)
2600 : : {
2601 : 1 : char *name = NULL;
2602 : 1 : GError *error = NULL;
2603 : : int fd;
2604 : : int copy_of_fd;
2605 : : int errsv;
2606 : : gboolean ret;
2607 : : GWin32InvalidParameterHandler handler;
2608 : :
2609 : : /* We're going to trigger a programming error: attmpting to close a
2610 : : * fd that was already closed. Make criticals non-fatal. */
2611 : 1 : g_assert_true (g_test_undefined ());
2612 : 1 : g_log_set_always_fatal (G_LOG_FATAL_MASK);
2613 : 1 : g_log_set_fatal_mask ("GLib", G_LOG_FATAL_MASK);
2614 : 1 : GLIB_PRIVATE_CALL (g_win32_push_empty_invalid_parameter_handler) (&handler);
2615 : :
2616 : 1 : fd = g_file_open_tmp (NULL, &name, &error);
2617 : 1 : g_assert_cmpint (fd, !=, -1);
2618 : 1 : g_assert_no_error (error);
2619 : 1 : g_assert_nonnull (name);
2620 : 1 : ret = g_close (fd, &error);
2621 : 1 : g_assert_no_error (error);
2622 : 1 : assert_fd_was_closed (fd);
2623 : 1 : g_assert_true (ret);
2624 : 1 : g_unlink (name);
2625 : 1 : g_free (name);
2626 : :
2627 : : /* Try to close it again with g_close() */
2628 : 1 : ret = g_close (fd, NULL);
2629 : 1 : errsv = errno;
2630 : 1 : g_assert_cmpint (errsv, ==, EBADF);
2631 : 1 : assert_fd_was_closed (fd);
2632 : 1 : g_assert_false (ret);
2633 : :
2634 : : /* Try to close it again with g_clear_fd() */
2635 : 1 : copy_of_fd = fd;
2636 : 1 : errno = EILSEQ;
2637 : 1 : ret = g_clear_fd (©_of_fd, NULL);
2638 : 1 : errsv = errno;
2639 : 1 : g_assert_cmpint (errsv, ==, EBADF);
2640 : 1 : assert_fd_was_closed (fd);
2641 : 1 : g_assert_false (ret);
2642 : :
2643 : : #ifdef g_autofree
2644 : : {
2645 : 2 : g_autofd int close_me = fd;
2646 : :
2647 : : /* This avoids clang warnings about the variables being unused */
2648 : 1 : g_test_message ("Invalid fd will be closed by autocleanup: %d",
2649 : : close_me);
2650 : 1 : errno = EILSEQ;
2651 : : }
2652 : :
2653 : 1 : errsv = errno;
2654 : 1 : g_assert_cmpint (errsv, ==, EILSEQ);
2655 : : #endif
2656 : :
2657 : 1 : GLIB_PRIVATE_CALL (g_win32_pop_invalid_parameter_handler) (&handler);
2658 : 1 : }
2659 : :
2660 : : static void
2661 : 1 : test_clear_fd (void)
2662 : : {
2663 : 1 : char *name = NULL;
2664 : 1 : GError *error = NULL;
2665 : : int fd;
2666 : : int copy_of_fd;
2667 : : int errsv;
2668 : :
2669 : : #ifdef g_autofree
2670 : 1 : g_test_summary ("Test g_clear_fd() and g_autofd");
2671 : : #else
2672 : : g_test_summary ("Test g_clear_fd() (g_autofd unsupported by this compiler)");
2673 : : #endif
2674 : :
2675 : : /* g_clear_fd() normalizes any negative number to -1 */
2676 : 1 : fd = -23;
2677 : 1 : g_clear_fd (&fd, &error);
2678 : 1 : g_assert_cmpint (fd, ==, -1);
2679 : 1 : g_assert_no_error (error);
2680 : :
2681 : : /* Nothing special about g_file_open_tmp, it's just a convenient way
2682 : : * to get an open fd */
2683 : 1 : fd = g_file_open_tmp (NULL, &name, &error);
2684 : 1 : g_assert_cmpint (fd, !=, -1);
2685 : 1 : g_assert_no_error (error);
2686 : 1 : g_assert_nonnull (name);
2687 : 1 : copy_of_fd = fd;
2688 : 1 : g_clear_fd (&fd, &error);
2689 : 1 : g_assert_cmpint (fd, ==, -1);
2690 : 1 : g_assert_no_error (error);
2691 : 1 : assert_fd_was_closed (copy_of_fd);
2692 : 1 : g_unlink (name);
2693 : 1 : g_free (name);
2694 : :
2695 : : /* g_clear_fd() is idempotent */
2696 : 1 : g_clear_fd (&fd, &error);
2697 : 1 : g_assert_cmpint (fd, ==, -1);
2698 : 1 : g_assert_no_error (error);
2699 : :
2700 : : #ifdef g_autofree
2701 : 1 : fd = g_file_open_tmp (NULL, &name, &error);
2702 : 1 : g_assert_cmpint (fd, !=, -1);
2703 : 1 : g_assert_no_error (error);
2704 : 1 : g_assert_nonnull (name);
2705 : :
2706 : : {
2707 : 1 : g_autofd int close_me = fd;
2708 : 2 : g_autofd int was_never_set = -42;
2709 : :
2710 : : /* This avoids clang warnings about the variables being unused */
2711 : 1 : g_test_message ("Will be closed by autocleanup: %d, %d",
2712 : : close_me, was_never_set);
2713 : : /* This is one of the few errno values guaranteed by Standard C.
2714 : : * We set it here to check that a successful g_autofd close doesn't
2715 : : * alter errno. */
2716 : 1 : errno = EILSEQ;
2717 : : }
2718 : :
2719 : 1 : errsv = errno;
2720 : 1 : g_assert_cmpint (errsv, ==, EILSEQ);
2721 : 1 : assert_fd_was_closed (fd);
2722 : 1 : g_unlink (name);
2723 : 1 : g_free (name);
2724 : : #endif
2725 : :
2726 [ + - ]: 1 : if (g_test_undefined ())
2727 : : {
2728 : 1 : g_test_message ("Testing error handling");
2729 : 1 : g_test_trap_subprocess ("/fileutils/clear-fd/subprocess/ebadf",
2730 : : 0, G_TEST_SUBPROCESS_DEFAULT);
2731 : : #ifdef g_autofree
2732 : 1 : g_test_trap_assert_stderr ("*failed with EBADF*failed with EBADF*failed with EBADF*");
2733 : : #else
2734 : : g_test_trap_assert_stderr ("*failed with EBADF*failed with EBADF*");
2735 : : #endif
2736 : 1 : g_test_trap_assert_passed ();
2737 : : }
2738 : 1 : }
2739 : :
2740 : : int
2741 : 2 : main (int argc,
2742 : : char *argv[])
2743 : : {
2744 : 2 : g_setenv ("LC_ALL", "C", TRUE);
2745 : 2 : g_test_init (&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL);
2746 : :
2747 : : #ifdef G_OS_WIN32
2748 : : g_test_add_func ("/fileutils/stdio-win32-pathstrip", test_win32_pathstrip);
2749 : : g_test_add_func ("/fileutils/stdio-win32-zero-terminate-symlink", test_win32_zero_terminate_symlink);
2750 : : #endif
2751 : 2 : g_test_add_func ("/fileutils/paths", test_paths);
2752 : 2 : g_test_add_func ("/fileutils/build-path", test_build_path);
2753 : 2 : g_test_add_func ("/fileutils/build-pathv", test_build_pathv);
2754 : 2 : g_test_add_func ("/fileutils/build-filename", test_build_filename);
2755 : 2 : g_test_add_func ("/fileutils/build-filenamev", test_build_filenamev);
2756 : 2 : g_test_add_func ("/fileutils/mkdir-with-parents", test_mkdir_with_parents);
2757 : 2 : g_test_add_func ("/fileutils/mkdir-with-parents-permission", test_mkdir_with_parents_permission);
2758 : 2 : g_test_add_func ("/fileutils/format-size-for-display", test_format_size_for_display);
2759 : 2 : g_test_add_func ("/fileutils/errors", test_file_errors);
2760 : 2 : g_test_add_func ("/fileutils/basename", test_basename);
2761 : 2 : g_test_add_func ("/fileutils/get-basename", test_get_basename);
2762 : 2 : g_test_add_func ("/fileutils/dirname", test_dirname);
2763 : 2 : g_test_add_func ("/fileutils/dir-make-tmp", test_dir_make_tmp);
2764 : 2 : g_test_add_func ("/fileutils/file-open-tmp", test_file_open_tmp);
2765 : 2 : g_test_add_func ("/fileutils/file-test", test_file_test);
2766 : 2 : g_test_add_func ("/fileutils/mkstemp", test_mkstemp);
2767 : 2 : g_test_add_func ("/fileutils/mkdtemp", test_mkdtemp);
2768 : 2 : g_test_add_func ("/fileutils/get-contents", test_get_contents);
2769 : 2 : g_test_add_func ("/fileutils/get-contents-large-file", test_get_contents_largefile);
2770 : 2 : g_test_add_func ("/fileutils/set-contents", test_set_contents);
2771 : 2 : g_test_add_func ("/fileutils/set-contents-full", test_set_contents_full);
2772 : 2 : g_test_add_func ("/fileutils/set-contents-full/read-only-file", test_set_contents_full_read_only_file);
2773 : 2 : g_test_add_func ("/fileutils/set-contents-full/read-only-directory", test_set_contents_full_read_only_directory);
2774 : 2 : g_test_add_func ("/fileutils/read-link", test_read_link);
2775 : 2 : g_test_add_func ("/fileutils/stdio-wrappers", test_stdio_wrappers);
2776 : 2 : g_test_add_func ("/fileutils/fopen-modes", test_fopen_modes);
2777 : 2 : g_test_add_func ("/fileutils/clear-fd", test_clear_fd);
2778 : 2 : g_test_add_func ("/fileutils/clear-fd/subprocess/ebadf", test_clear_fd_ebadf);
2779 : :
2780 : 2 : return g_test_run ();
2781 : : }
|