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