Branch data Line data Source code
1 : : /* GLib testing framework examples and tests
2 : : * Copyright (C) 2008 Red Hat, Inc.
3 : : * Authors: Tomas Bzatek <tbzatek@redhat.com>
4 : : *
5 : : * SPDX-License-Identifier: LicenseRef-old-glib-tests
6 : : *
7 : : * This work is provided "as is"; redistribution and modification
8 : : * in whole or in part, in any medium, physical or electronic is
9 : : * permitted without restriction.
10 : : *
11 : : * This work is distributed in the hope that it will be useful,
12 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 : : *
15 : : * In no event shall the authors or contributors be liable for any
16 : : * direct, indirect, incidental, special, exemplary, or consequential
17 : : * damages (including, but not limited to, procurement of substitute
18 : : * goods or services; loss of use, data, or profits; or business
19 : : * interruption) however caused and on any theory of liability, whether
20 : : * in contract, strict liability, or tort (including negligence or
21 : : * otherwise) arising in any way out of the use of this software, even
22 : : * if advised of the possibility of such damage.
23 : : */
24 : :
25 : : #include "config.h"
26 : :
27 : : #include <glib/glib.h>
28 : : #include <gio/gio.h>
29 : : #include <stdlib.h>
30 : : #include <string.h>
31 : : #ifdef G_OS_WIN32
32 : : #include <stdio.h>
33 : : #include <glib/gstdio.h>
34 : : #include <windows.h>
35 : : #include <shlobj.h>
36 : : #include <io.h> /* for _get_osfhandle */
37 : : #endif
38 : :
39 : : #define TEST_NAME "Prilis zlutoucky kun"
40 : : #define TEST_DISPLAY_NAME "UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88"
41 : : #define TEST_SIZE 0xFFFFFFF0
42 : :
43 : : static void
44 : 6 : test_assigned_values (GFileInfo *info)
45 : : {
46 : : const char *name, *name_filepath, *display_name, *mistake;
47 : : guint64 size;
48 : : GFileType type;
49 : :
50 : : /* Test for attributes presence */
51 : 6 : g_assert_true (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_NAME));
52 : 6 : g_assert_true (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME));
53 : 6 : g_assert_true (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SIZE));
54 : 6 : g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_COPY_NAME));
55 : :
56 : : /* Retrieve data back and compare */
57 : :
58 : 6 : name = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_STANDARD_NAME);
59 : 6 : name_filepath = g_file_info_get_attribute_file_path (info, G_FILE_ATTRIBUTE_STANDARD_NAME);
60 : 6 : display_name = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME);
61 : 6 : mistake = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_COPY_NAME);
62 : 6 : size = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_STANDARD_SIZE);
63 : 6 : type = g_file_info_get_file_type (info);
64 : :
65 : 6 : g_assert_cmpstr (name, ==, TEST_NAME);
66 : 6 : g_assert_cmpstr (name_filepath, ==, name);
67 : 6 : g_assert_cmpstr (display_name, ==, TEST_DISPLAY_NAME);
68 : 6 : g_assert_null (mistake);
69 : 6 : g_assert_cmpint (size, ==, TEST_SIZE);
70 : 6 : g_assert_cmpstr (name, ==, g_file_info_get_name (info));
71 : 6 : g_assert_cmpstr (display_name, ==, g_file_info_get_display_name (info));
72 : 6 : g_assert_cmpint (size, ==, g_file_info_get_size (info) );
73 : 6 : g_assert_cmpint (type, ==, G_FILE_TYPE_DIRECTORY);
74 : 6 : }
75 : :
76 : :
77 : :
78 : : static void
79 : 2 : test_g_file_info (void)
80 : : {
81 : : GFileInfo *info;
82 : : GFileInfo *info_dup;
83 : : GFileInfo *info_copy;
84 : : char **attr_list;
85 : : GFileAttributeMatcher *matcher;
86 : :
87 : 2 : info = g_file_info_new ();
88 : :
89 : : /* Test for empty instance */
90 : 2 : attr_list = g_file_info_list_attributes (info, NULL);
91 : 2 : g_assert_nonnull (attr_list);
92 : 2 : g_assert_null (*attr_list);
93 : 2 : g_strfreev (attr_list);
94 : :
95 : 2 : g_file_info_set_attribute_byte_string (info, G_FILE_ATTRIBUTE_STANDARD_NAME, TEST_NAME);
96 : 2 : g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, TEST_DISPLAY_NAME);
97 : 2 : g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_STANDARD_SIZE, TEST_SIZE);
98 : 2 : g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
99 : :
100 : : /* The attr list should not be empty now */
101 : 2 : attr_list = g_file_info_list_attributes (info, NULL);
102 : 2 : g_assert_nonnull (attr_list);
103 : 2 : g_assert_nonnull (*attr_list);
104 : 2 : g_strfreev (attr_list);
105 : :
106 : 2 : test_assigned_values (info);
107 : :
108 : : /* Test the file path encoding functions */
109 : 2 : g_file_info_set_attribute_file_path (info, G_FILE_ATTRIBUTE_STANDARD_NAME, "something different");
110 : 2 : g_assert_cmpstr (g_file_info_get_attribute_file_path (info, G_FILE_ATTRIBUTE_STANDARD_NAME), ==, "something different");
111 : 2 : g_file_info_set_attribute_file_path (info, G_FILE_ATTRIBUTE_STANDARD_NAME, TEST_NAME);
112 : :
113 : : /* Test dups */
114 : 2 : info_dup = g_file_info_dup (info);
115 : 2 : g_assert_nonnull (info_dup);
116 : 2 : test_assigned_values (info_dup);
117 : :
118 : 2 : info_copy = g_file_info_new ();
119 : 2 : g_file_info_copy_into (info_dup, info_copy);
120 : 2 : g_assert_nonnull (info_copy);
121 : 2 : test_assigned_values (info_copy);
122 : :
123 : : /* Test remove attribute */
124 : 2 : g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER));
125 : 2 : g_file_info_set_attribute_int32 (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER, 10);
126 : 2 : g_assert_true (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER));
127 : :
128 : 2 : g_assert_cmpint (g_file_info_get_attribute_type (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER), ==, G_FILE_ATTRIBUTE_TYPE_INT32);
129 : 2 : g_assert_cmpint (g_file_info_get_attribute_status (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER), !=, G_FILE_ATTRIBUTE_STATUS_ERROR_SETTING);
130 : :
131 : 2 : g_file_info_remove_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER);
132 : 2 : g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER));
133 : 2 : g_assert_cmpint (g_file_info_get_attribute_type (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER), ==, G_FILE_ATTRIBUTE_TYPE_INVALID);
134 : :
135 : 2 : matcher = g_file_attribute_matcher_new (G_FILE_ATTRIBUTE_STANDARD_NAME ","
136 : : G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME);
137 : :
138 : 2 : g_assert_true (g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_STANDARD_NAME));
139 : 2 : g_assert_false (g_file_attribute_matcher_matches_only (matcher, G_FILE_ATTRIBUTE_STANDARD_NAME));
140 : 2 : g_assert_false (g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_STANDARD_SIZE));
141 : :
142 : 2 : g_file_info_set_attribute_mask (info, matcher);
143 : 2 : g_file_attribute_matcher_unref (matcher);
144 : :
145 : 2 : g_assert_false (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SIZE));
146 : 2 : g_assert_true (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_NAME));
147 : :
148 : 2 : g_object_unref (info);
149 : 2 : g_object_unref (info_dup);
150 : 2 : g_object_unref (info_copy);
151 : 2 : }
152 : :
153 : : static void
154 : 2 : test_g_file_info_modification_time (void)
155 : : {
156 : 2 : GFile *file = NULL;
157 : 2 : GFileIOStream *io_stream = NULL;
158 : 2 : GFileInfo *info = NULL;
159 : 2 : GDateTime *dt = NULL, *dt_usecs = NULL, *dt_new = NULL, *dt_new_usecs = NULL;
160 : : GTimeSpan ts;
161 : : gboolean nsecs_supported;
162 : : gint usecs;
163 : : guint32 nsecs;
164 : 2 : GError *error = NULL;
165 : :
166 : 2 : g_test_summary ("Test that getting the modification time of a file works.");
167 : :
168 : 2 : file = g_file_new_tmp ("g-file-info-test-XXXXXX", &io_stream, &error);
169 : 2 : g_assert_no_error (error);
170 : :
171 : 2 : info = g_file_query_info (file,
172 : : G_FILE_ATTRIBUTE_TIME_MODIFIED,
173 : : G_FILE_QUERY_INFO_NONE,
174 : : NULL, &error);
175 : 2 : g_assert_no_error (error);
176 : :
177 : : /* Check the modification time is retrievable. */
178 : 2 : dt = g_file_info_get_modification_date_time (info);
179 : 2 : g_assert_nonnull (dt);
180 : :
181 : : /* Try again with microsecond precision. */
182 : 2 : g_clear_object (&info);
183 : 2 : info = g_file_query_info (file,
184 : : G_FILE_ATTRIBUTE_TIME_MODIFIED "," G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC,
185 : : G_FILE_QUERY_INFO_NONE,
186 : : NULL, &error);
187 : 2 : g_assert_no_error (error);
188 : :
189 : 2 : dt_usecs = g_file_info_get_modification_date_time (info);
190 : 2 : g_assert_nonnull (dt_usecs);
191 : :
192 : 2 : ts = g_date_time_difference (dt_usecs, dt);
193 : 2 : g_assert_cmpint (ts, >=, 0);
194 : 2 : g_assert_cmpint (ts, <, G_USEC_PER_SEC);
195 : :
196 : : /* Try again with nanosecond precision. */
197 : 2 : g_clear_object (&info);
198 : 2 : info = g_file_query_info (file,
199 : : G_FILE_ATTRIBUTE_TIME_MODIFIED "," G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC "," G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC,
200 : : G_FILE_QUERY_INFO_NONE,
201 : : NULL, &error);
202 : 2 : g_assert_no_error (error);
203 : :
204 : 2 : nsecs_supported = g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC);
205 : 2 : if (nsecs_supported)
206 : : {
207 : 2 : usecs = g_date_time_get_microsecond (dt_usecs);
208 : 2 : nsecs = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC);
209 : :
210 : 2 : g_assert_cmpuint (nsecs, >=, usecs * 1000);
211 : 2 : g_assert_cmpuint (nsecs, <, (usecs + 1) * 1000);
212 : 1 : }
213 : :
214 : : /* Try round-tripping the modification time. */
215 : 2 : dt_new = g_date_time_add (dt_usecs, G_USEC_PER_SEC + 50);
216 : 2 : g_file_info_set_modification_date_time (info, dt_new);
217 : :
218 : 2 : dt_new_usecs = g_file_info_get_modification_date_time (info);
219 : 2 : ts = g_date_time_difference (dt_new_usecs, dt_new);
220 : 2 : g_assert_cmpint (ts, ==, 0);
221 : :
222 : : /* Setting the modification time with usec-precision should have cleared nsecs. */
223 : 2 : g_assert_cmpuint (g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC), ==, 0);
224 : :
225 : : /* Try setting the modification time with nsec-precision and it should set the
226 : : * usecs too. */
227 : 2 : if (nsecs_supported)
228 : : {
229 : : gint new_usecs;
230 : : guint32 new_nsecs;
231 : 2 : GDateTime *new_dt_usecs = NULL;
232 : :
233 : 2 : g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC, nsecs + 100,
234 : : G_FILE_QUERY_INFO_NONE, NULL, &error);
235 : 2 : g_assert_no_error (error);
236 : :
237 : 2 : g_clear_object (&info);
238 : 2 : info = g_file_query_info (file,
239 : : G_FILE_ATTRIBUTE_TIME_MODIFIED "," G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC "," G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC,
240 : : G_FILE_QUERY_INFO_NONE,
241 : : NULL, &error);
242 : 2 : g_assert_no_error (error);
243 : :
244 : 2 : new_dt_usecs = g_file_info_get_modification_date_time (info);
245 : 2 : g_assert_nonnull (new_dt_usecs);
246 : :
247 : 2 : new_usecs = g_date_time_get_microsecond (new_dt_usecs);
248 : 2 : new_nsecs = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC);
249 : :
250 : 2 : g_assert_cmpuint (new_nsecs, ==, nsecs + 100);
251 : 2 : g_assert_cmpuint (new_nsecs, >=, new_usecs * 1000);
252 : 2 : g_assert_cmpuint (new_nsecs, <, (new_usecs + 1) * 1000);
253 : :
254 : 2 : g_date_time_unref (new_dt_usecs);
255 : 1 : }
256 : :
257 : : /* Clean up. */
258 : 2 : g_clear_object (&io_stream);
259 : 2 : g_file_delete (file, NULL, NULL);
260 : 2 : g_clear_object (&file);
261 : :
262 : 2 : g_clear_object (&info);
263 : 2 : g_date_time_unref (dt);
264 : 2 : g_date_time_unref (dt_usecs);
265 : 2 : g_date_time_unref (dt_new);
266 : 2 : g_date_time_unref (dt_new_usecs);
267 : 2 : }
268 : :
269 : : static void
270 : 2 : test_g_file_info_access_time (void)
271 : : {
272 : 2 : GFile *file = NULL;
273 : 2 : GFileIOStream *io_stream = NULL;
274 : 2 : GFileInfo *info = NULL;
275 : 2 : GDateTime *dt = NULL, *dt_usecs = NULL, *dt_new = NULL, *dt_new_usecs = NULL,
276 : 2 : *dt_before_epoch = NULL, *dt_before_epoch_returned = NULL;
277 : : GTimeSpan ts;
278 : : gboolean nsecs_supported;
279 : : gint usecs;
280 : : guint32 nsecs;
281 : 2 : GError *error = NULL;
282 : :
283 : 2 : g_test_summary ("Test that getting the access time of a file works.");
284 : :
285 : 2 : file = g_file_new_tmp ("g-file-info-test-XXXXXX", &io_stream, &error);
286 : 2 : g_assert_no_error (error);
287 : :
288 : 2 : info = g_file_query_info (file,
289 : : G_FILE_ATTRIBUTE_TIME_ACCESS,
290 : : G_FILE_QUERY_INFO_NONE,
291 : : NULL, &error);
292 : 2 : g_assert_no_error (error);
293 : :
294 : 2 : if (!g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_TIME_ACCESS))
295 : : {
296 : 0 : g_test_skip ("Skipping testing access time as it’s not supported by the kernel");
297 : 0 : g_file_delete (file, NULL, NULL);
298 : 0 : g_clear_object (&file);
299 : 0 : g_clear_object (&info);
300 : 0 : return;
301 : : }
302 : :
303 : : /* Check the access time is retrievable. */
304 : 2 : dt = g_file_info_get_access_date_time (info);
305 : 2 : g_assert_nonnull (dt);
306 : :
307 : : /* Try again with microsecond precision. */
308 : 2 : g_clear_object (&info);
309 : 2 : info = g_file_query_info (file,
310 : : G_FILE_ATTRIBUTE_TIME_ACCESS "," G_FILE_ATTRIBUTE_TIME_ACCESS_USEC,
311 : : G_FILE_QUERY_INFO_NONE,
312 : : NULL, &error);
313 : 2 : g_assert_no_error (error);
314 : :
315 : 2 : dt_usecs = g_file_info_get_access_date_time (info);
316 : 2 : g_assert_nonnull (dt_usecs);
317 : :
318 : 2 : ts = g_date_time_difference (dt_usecs, dt);
319 : 2 : g_assert_cmpint (ts, >=, 0);
320 : 2 : g_assert_cmpint (ts, <, G_USEC_PER_SEC);
321 : :
322 : : /* Try again with nanosecond precision. */
323 : 2 : g_clear_object (&info);
324 : 2 : info = g_file_query_info (file,
325 : : G_FILE_ATTRIBUTE_TIME_ACCESS "," G_FILE_ATTRIBUTE_TIME_ACCESS_USEC "," G_FILE_ATTRIBUTE_TIME_ACCESS_NSEC,
326 : : G_FILE_QUERY_INFO_NONE,
327 : : NULL, &error);
328 : 2 : g_assert_no_error (error);
329 : :
330 : 2 : nsecs_supported = g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_TIME_ACCESS_NSEC);
331 : 2 : if (nsecs_supported)
332 : : {
333 : 2 : usecs = g_date_time_get_microsecond (dt_usecs);
334 : 2 : nsecs = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_ACCESS_NSEC);
335 : :
336 : 2 : g_assert_cmpuint (nsecs, >=, usecs * 1000);
337 : 2 : g_assert_cmpuint (nsecs, <, (usecs + 1) * 1000);
338 : 1 : }
339 : :
340 : : /* Try round-tripping the access time. */
341 : 2 : dt_new = g_date_time_add (dt_usecs, G_USEC_PER_SEC + 50);
342 : 2 : g_file_info_set_access_date_time (info, dt_new);
343 : :
344 : 2 : dt_new_usecs = g_file_info_get_access_date_time (info);
345 : 2 : ts = g_date_time_difference (dt_new_usecs, dt_new);
346 : 2 : g_assert_cmpint (ts, ==, 0);
347 : :
348 : : // try with a negative timestamp
349 : 2 : dt_before_epoch = g_date_time_new_from_unix_utc (-10000);
350 : 2 : g_file_info_set_access_date_time (info, dt_before_epoch);
351 : 2 : dt_before_epoch_returned = g_file_info_get_access_date_time (info);
352 : 2 : ts = g_date_time_difference (dt_before_epoch, dt_before_epoch_returned);
353 : 2 : g_assert_cmpint (ts, ==, 0);
354 : :
355 : : /* Setting the access time with usec-precision should have cleared nsecs. */
356 : 2 : g_assert_cmpuint (g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_ACCESS_NSEC), ==, 0);
357 : :
358 : : /* Try setting the access time with nsec-precision and it should set the
359 : : * usecs too. */
360 : 2 : if (nsecs_supported)
361 : : {
362 : : gint new_usecs;
363 : : guint32 new_nsecs;
364 : 2 : GDateTime *new_dt_usecs = NULL;
365 : :
366 : 2 : g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_TIME_ACCESS_NSEC, nsecs + 100,
367 : : G_FILE_QUERY_INFO_NONE, NULL, &error);
368 : 2 : g_assert_no_error (error);
369 : :
370 : 2 : g_clear_object (&info);
371 : 2 : info = g_file_query_info (file,
372 : : G_FILE_ATTRIBUTE_TIME_ACCESS "," G_FILE_ATTRIBUTE_TIME_ACCESS_USEC "," G_FILE_ATTRIBUTE_TIME_ACCESS_NSEC,
373 : : G_FILE_QUERY_INFO_NONE,
374 : : NULL, &error);
375 : 2 : g_assert_no_error (error);
376 : :
377 : 2 : new_dt_usecs = g_file_info_get_access_date_time (info);
378 : 2 : g_assert_nonnull (new_dt_usecs);
379 : :
380 : 2 : new_usecs = g_date_time_get_microsecond (new_dt_usecs);
381 : 2 : new_nsecs = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_ACCESS_NSEC);
382 : :
383 : 2 : g_assert_cmpuint (new_nsecs, ==, nsecs + 100);
384 : 2 : g_assert_cmpuint (new_nsecs, >=, new_usecs * 1000);
385 : 2 : g_assert_cmpuint (new_nsecs, <, (new_usecs + 1) * 1000);
386 : :
387 : 2 : g_date_time_unref (new_dt_usecs);
388 : 1 : }
389 : :
390 : : /* Clean up. */
391 : 2 : g_clear_object (&io_stream);
392 : 2 : g_file_delete (file, NULL, NULL);
393 : 2 : g_clear_object (&file);
394 : :
395 : 2 : g_clear_object (&info);
396 : 2 : g_date_time_unref (dt);
397 : 2 : g_date_time_unref (dt_usecs);
398 : 2 : g_date_time_unref (dt_new);
399 : 2 : g_date_time_unref (dt_new_usecs);
400 : 2 : g_date_time_unref (dt_before_epoch);
401 : 2 : g_date_time_unref (dt_before_epoch_returned);
402 : 1 : }
403 : :
404 : : static void
405 : 2 : test_g_file_info_creation_time (void)
406 : : {
407 : 2 : GFile *file = NULL;
408 : 2 : GFileIOStream *io_stream = NULL;
409 : 2 : GFileInfo *info = NULL;
410 : 2 : GDateTime *dt = NULL, *dt_usecs = NULL, *dt_new = NULL, *dt_new_usecs = NULL,
411 : 2 : *dt_before_epoch = NULL, *dt_before_epoch_returned = NULL;
412 : : GTimeSpan ts;
413 : : gboolean nsecs_supported;
414 : : gint usecs;
415 : : guint32 nsecs;
416 : 2 : GError *error = NULL;
417 : :
418 : 2 : g_test_summary ("Test that getting the creation time of a file works.");
419 : :
420 : 2 : file = g_file_new_tmp ("g-file-info-test-XXXXXX", &io_stream, &error);
421 : 2 : g_assert_no_error (error);
422 : :
423 : 2 : info = g_file_query_info (file,
424 : : G_FILE_ATTRIBUTE_TIME_CREATED,
425 : : G_FILE_QUERY_INFO_NONE,
426 : : NULL, &error);
427 : 2 : g_assert_no_error (error);
428 : :
429 : 2 : if (!g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_TIME_CREATED))
430 : : {
431 : 0 : g_test_skip ("Skipping testing creation time as it’s not supported by the kernel");
432 : 0 : g_clear_object (&io_stream);
433 : 0 : g_file_delete (file, NULL, NULL);
434 : 0 : g_clear_object (&file);
435 : 0 : g_clear_object (&info);
436 : 0 : return;
437 : : }
438 : :
439 : : /* Check the creation time is retrievable. */
440 : 2 : dt = g_file_info_get_creation_date_time (info);
441 : :
442 : : /* Try again with microsecond precision. */
443 : 2 : g_clear_object (&info);
444 : 2 : info = g_file_query_info (file,
445 : : G_FILE_ATTRIBUTE_TIME_CREATED "," G_FILE_ATTRIBUTE_TIME_CREATED_USEC,
446 : : G_FILE_QUERY_INFO_NONE,
447 : : NULL, &error);
448 : 2 : g_assert_no_error (error);
449 : :
450 : 2 : dt_usecs = g_file_info_get_creation_date_time (info);
451 : 2 : g_assert_nonnull (dt_usecs);
452 : :
453 : 2 : ts = g_date_time_difference (dt_usecs, dt);
454 : 2 : g_assert_cmpint (ts, >=, 0);
455 : 2 : g_assert_cmpint (ts, <, G_USEC_PER_SEC);
456 : :
457 : : /* Try again with nanosecond precision. */
458 : 2 : g_clear_object (&info);
459 : 2 : info = g_file_query_info (file,
460 : : G_FILE_ATTRIBUTE_TIME_CREATED "," G_FILE_ATTRIBUTE_TIME_CREATED_USEC "," G_FILE_ATTRIBUTE_TIME_CREATED_NSEC,
461 : : G_FILE_QUERY_INFO_NONE,
462 : : NULL, &error);
463 : 2 : g_assert_no_error (error);
464 : :
465 : 2 : nsecs_supported = g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_TIME_CREATED_NSEC);
466 : 2 : if (nsecs_supported)
467 : : {
468 : 2 : usecs = g_date_time_get_microsecond (dt_usecs);
469 : 2 : nsecs = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_CREATED_NSEC);
470 : :
471 : 2 : g_assert_cmpuint (nsecs, >=, usecs * 1000);
472 : 2 : g_assert_cmpuint (nsecs, <, (usecs + 1) * 1000);
473 : 1 : }
474 : :
475 : : /* Try round-tripping the creation time. */
476 : 2 : dt_new = g_date_time_add (dt_usecs, G_USEC_PER_SEC + 50);
477 : 2 : g_file_info_set_creation_date_time (info, dt_new);
478 : :
479 : 2 : dt_new_usecs = g_file_info_get_creation_date_time (info);
480 : 2 : ts = g_date_time_difference (dt_new_usecs, dt_new);
481 : 2 : g_assert_cmpint (ts, ==, 0);
482 : :
483 : : // try with a negative timestamp
484 : 2 : dt_before_epoch = g_date_time_new_from_unix_utc (-10000);
485 : 2 : g_file_info_set_creation_date_time (info, dt_before_epoch);
486 : 2 : dt_before_epoch_returned = g_file_info_get_creation_date_time (info);
487 : 2 : ts = g_date_time_difference (dt_before_epoch, dt_before_epoch_returned);
488 : 2 : g_assert_cmpint (ts, ==, 0);
489 : :
490 : : /* Setting the creation time with usec-precision should have cleared nsecs. */
491 : 2 : g_assert_cmpuint (g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_CREATED_NSEC), ==, 0);
492 : :
493 : : /* Try setting the creation time with nsec-precision and it should set the
494 : : * usecs too. */
495 : 2 : if (nsecs_supported)
496 : : {
497 : : gint new_usecs;
498 : : guint32 new_nsecs;
499 : 2 : GDateTime *new_dt_usecs = NULL;
500 : :
501 : : /* This can fail on some platforms, even if reading CREATED_NSEC works */
502 : 2 : g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_TIME_CREATED_NSEC, nsecs + 100,
503 : : G_FILE_QUERY_INFO_NONE, NULL, &error);
504 : 2 : if (error == NULL)
505 : : {
506 : 0 : g_clear_object (&info);
507 : 0 : info = g_file_query_info (file,
508 : : G_FILE_ATTRIBUTE_TIME_CREATED "," G_FILE_ATTRIBUTE_TIME_CREATED_USEC "," G_FILE_ATTRIBUTE_TIME_CREATED_NSEC,
509 : : G_FILE_QUERY_INFO_NONE,
510 : : NULL, &error);
511 : 0 : g_assert_no_error (error);
512 : :
513 : 0 : new_dt_usecs = g_file_info_get_creation_date_time (info);
514 : 0 : g_assert_nonnull (new_dt_usecs);
515 : :
516 : 0 : new_usecs = g_date_time_get_microsecond (new_dt_usecs);
517 : 0 : new_nsecs = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_CREATED_NSEC);
518 : :
519 : 0 : g_assert_cmpuint (new_nsecs, ==, nsecs + 100);
520 : 0 : g_assert_cmpuint (new_nsecs, >=, new_usecs * 1000);
521 : 0 : g_assert_cmpuint (new_nsecs, <, (new_usecs + 1) * 1000);
522 : :
523 : 0 : g_date_time_unref (new_dt_usecs);
524 : 0 : }
525 : : else
526 : : {
527 : 2 : if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
528 : 2 : g_clear_error (&error);
529 : 2 : g_assert_no_error (error);
530 : : }
531 : 1 : }
532 : :
533 : : /* Clean up. */
534 : 2 : g_clear_object (&io_stream);
535 : 2 : g_file_delete (file, NULL, NULL);
536 : 2 : g_clear_object (&file);
537 : :
538 : 2 : g_clear_object (&info);
539 : 2 : g_date_time_unref (dt);
540 : 2 : g_date_time_unref (dt_usecs);
541 : 2 : g_date_time_unref (dt_new);
542 : 2 : g_date_time_unref (dt_new_usecs);
543 : 2 : g_date_time_unref (dt_before_epoch);
544 : 2 : g_date_time_unref (dt_before_epoch_returned);
545 : 1 : }
546 : :
547 : : static void
548 : 2 : test_g_file_info_icons (void)
549 : : {
550 : 2 : GFile *file = NULL;
551 : 2 : GFileIOStream *io_stream = NULL;
552 : 2 : GError *error = NULL;
553 : : GFileInfo *info, *fast_info;
554 : : GIcon *icon, *symbolic_icon;
555 : : GIcon *fast_icon, *fast_symbolic_icon;
556 : :
557 : 2 : g_test_summary ("Test fetching icons for a file.");
558 : :
559 : 2 : file = g_file_new_tmp ("g-file-info-test-XXXXXX", &io_stream, &error);
560 : 2 : g_assert_no_error (error);
561 : :
562 : 2 : info = g_file_query_info (file,
563 : : G_FILE_ATTRIBUTE_STANDARD_NAME ","
564 : : G_FILE_ATTRIBUTE_STANDARD_ICON ","
565 : : G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON,
566 : : G_FILE_QUERY_INFO_NONE,
567 : : NULL, &error);
568 : 2 : g_assert_no_error (error);
569 : :
570 : 2 : g_assert_true (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_ICON));
571 : 2 : g_assert_true (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON));
572 : :
573 : 2 : icon = g_file_info_get_icon (info);
574 : 2 : symbolic_icon = g_file_info_get_symbolic_icon (info);
575 : :
576 : 2 : g_assert_nonnull (icon);
577 : 2 : g_assert_nonnull (symbolic_icon);
578 : :
579 : : /* Query icons with fast content type to skip implicit normal content type */
580 : 2 : fast_info = g_file_query_info (file,
581 : : G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE ","
582 : : G_FILE_ATTRIBUTE_STANDARD_NAME ","
583 : : G_FILE_ATTRIBUTE_STANDARD_ICON ","
584 : : G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON,
585 : : G_FILE_QUERY_INFO_NONE,
586 : : NULL, &error);
587 : 2 : g_assert_no_error (error);
588 : :
589 : 2 : g_assert_false (g_file_info_has_attribute (fast_info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE));
590 : 2 : g_assert_true (g_file_info_has_attribute (fast_info, G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE));
591 : 2 : g_assert_true (g_file_info_has_attribute (fast_info, G_FILE_ATTRIBUTE_STANDARD_ICON));
592 : 2 : g_assert_true (g_file_info_has_attribute (fast_info, G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON));
593 : :
594 : 2 : fast_icon = g_file_info_get_icon (fast_info);
595 : 2 : fast_symbolic_icon = g_file_info_get_symbolic_icon (fast_info);
596 : :
597 : 2 : g_assert_nonnull (fast_icon);
598 : 2 : g_assert_nonnull (fast_symbolic_icon);
599 : :
600 : : /* Clean up. */
601 : 2 : g_clear_object (&io_stream);
602 : 2 : g_file_delete (file, NULL, NULL);
603 : 2 : g_clear_object (&file);
604 : 2 : g_clear_object (&info);
605 : 2 : g_clear_object (&fast_info);
606 : 2 : }
607 : :
608 : : #ifdef G_OS_WIN32
609 : : static void
610 : 1 : test_internal_enhanced_stdio (void)
611 : : {
612 : : char *p0, *p1, *ps;
613 : : gboolean try_sparse;
614 : : gchar *tmp_dir_root;
615 : : wchar_t *tmp_dir_root_w;
616 : : gchar *c;
617 : : DWORD fsflags;
618 : : FILE *f;
619 : : SYSTEMTIME st;
620 : : FILETIME ft;
621 : : HANDLE h;
622 : : GStatBuf statbuf_p0, statbuf_p1, statbuf_ps;
623 : : GFile *gf_p0, *gf_p1, *gf_ps;
624 : : GFileInfo *fi_p0, *fi_p1, *fi_ps;
625 : : guint64 size_p0, alsize_p0, size_ps, alsize_ps;
626 : : const gchar *id_p0;
627 : : const gchar *id_p1;
628 : : guint64 time_p0;
629 : : gchar *tmp_dir;
630 : : wchar_t *programdata_dir_w;
631 : : wchar_t *users_dir_w;
632 : : static const GUID folder_id_programdata =
633 : : { 0x62AB5D82, 0xFDC1, 0x4DC3, { 0xA9, 0xDD, 0x07, 0x0D, 0x1D, 0x49, 0x5D, 0x97 } };
634 : : static const GUID folder_id_users =
635 : : { 0x0762D272, 0xC50A, 0x4BB0, { 0xA3, 0x82, 0x69, 0x7D, 0xCD, 0x72, 0x9B, 0x80 } };
636 : 1 : GDateTime *dt = NULL, *dt2 = NULL;
637 : : GTimeSpan ts;
638 : : /* Just before SYSTEMTIME limit (Jan 1 30827) */
639 : 1 : const gint64 one_sec_before_systemtime_limit = 910670515199;
640 : : gboolean retval;
641 : 1 : GError *local_error = NULL;
642 : :
643 : :
644 : 1 : programdata_dir_w = NULL;
645 : 1 : SHGetKnownFolderPath (&folder_id_programdata, 0, NULL, &programdata_dir_w);
646 : :
647 : 1 : users_dir_w = NULL;
648 : 1 : SHGetKnownFolderPath (&folder_id_users, 0, NULL, &users_dir_w);
649 : :
650 : 1 : if (programdata_dir_w != NULL && users_dir_w != NULL)
651 : : {
652 : : gchar *programdata;
653 : : gchar *users_dir;
654 : : gchar *allusers;
655 : : gchar *commondata;
656 : : GFile *gf_programdata, *gf_allusers, *gf_commondata;
657 : : GFileInfo *fi_programdata, *fi_allusers, *fi_allusers_target, *fi_commondata, *fi_commondata_target;
658 : : GFileType ft_allusers;
659 : : GFileType ft_allusers_target;
660 : : GFileType ft_programdata;
661 : : GFileType ft_commondata;
662 : : gboolean allusers_is_symlink;
663 : : gboolean commondata_is_symlink;
664 : : gboolean commondata_is_mount_point;
665 : : guint32 allusers_reparse_tag;
666 : : guint32 commondata_reparse_tag;
667 : : const gchar *id_allusers;
668 : : const gchar *id_allusers_target;
669 : : const gchar *id_commondata_target;
670 : : const gchar *id_programdata;
671 : : const gchar *allusers_target;
672 : : const gchar *commondata_target;
673 : :
674 : : /* C:/ProgramData */
675 : 1 : programdata = g_utf16_to_utf8 (programdata_dir_w, -1, NULL, NULL, NULL);
676 : 1 : g_assert_nonnull (programdata);
677 : : /* C:/Users */
678 : 1 : users_dir = g_utf16_to_utf8 (users_dir_w, -1, NULL, NULL, NULL);
679 : 1 : g_assert_nonnull (users_dir);
680 : : /* "C:/Users/All Users" is a known directory symlink
681 : : * for "C:/ProgramData".
682 : : */
683 : 1 : allusers = g_build_filename (users_dir, "All Users", NULL);
684 : :
685 : : /* "C:/Users/All Users/Application Data" is a known
686 : : * junction for "C:/ProgramData"
687 : : */
688 : 1 : commondata = g_build_filename (allusers, "Application Data", NULL);
689 : :
690 : : /* We don't test g_stat() and g_lstat() on these directories,
691 : : * because it is pointless - there's no way to tell that these
692 : : * functions behave correctly in this case
693 : : * (st_ino is useless, so we can't tell apart g_stat() and g_lstat()
694 : : * results; st_mode is also useless as it does not support S_ISLNK;
695 : : * and these directories have no interesting properties other
696 : : * than [not] being symlinks).
697 : : */
698 : 1 : gf_programdata = g_file_new_for_path (programdata);
699 : 1 : gf_allusers = g_file_new_for_path (allusers);
700 : 1 : gf_commondata = g_file_new_for_path (commondata);
701 : :
702 : 1 : fi_programdata = g_file_query_info (gf_programdata,
703 : : G_FILE_ATTRIBUTE_ID_FILE ","
704 : : G_FILE_ATTRIBUTE_STANDARD_TYPE,
705 : : G_FILE_QUERY_INFO_NONE,
706 : : NULL, NULL);
707 : :
708 : 1 : fi_allusers_target = g_file_query_info (gf_allusers,
709 : : G_FILE_ATTRIBUTE_ID_FILE ","
710 : : G_FILE_ATTRIBUTE_STANDARD_TYPE,
711 : : G_FILE_QUERY_INFO_NONE,
712 : : NULL, NULL);
713 : :
714 : 1 : fi_allusers = g_file_query_info (gf_allusers,
715 : : G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET ","
716 : : G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK ","
717 : : G_FILE_ATTRIBUTE_DOS_REPARSE_POINT_TAG ","
718 : : G_FILE_ATTRIBUTE_ID_FILE ","
719 : : G_FILE_ATTRIBUTE_STANDARD_TYPE,
720 : : G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
721 : : NULL, NULL);
722 : :
723 : 1 : fi_commondata = g_file_query_info (gf_commondata,
724 : : G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET ","
725 : : G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK ","
726 : : G_FILE_ATTRIBUTE_DOS_IS_MOUNTPOINT ","
727 : : G_FILE_ATTRIBUTE_DOS_REPARSE_POINT_TAG ","
728 : : G_FILE_ATTRIBUTE_ID_FILE ","
729 : : G_FILE_ATTRIBUTE_STANDARD_TYPE,
730 : : G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
731 : : NULL, NULL);
732 : :
733 : 1 : fi_commondata_target = g_file_query_info (gf_commondata,
734 : : G_FILE_ATTRIBUTE_ID_FILE ","
735 : : G_FILE_ATTRIBUTE_STANDARD_TYPE,
736 : : G_FILE_QUERY_INFO_NONE,
737 : : NULL, NULL);
738 : :
739 : 1 : g_assert_true (g_file_info_has_attribute (fi_programdata, G_FILE_ATTRIBUTE_ID_FILE));
740 : 1 : g_assert_true (g_file_info_has_attribute (fi_programdata, G_FILE_ATTRIBUTE_STANDARD_TYPE));
741 : :
742 : 1 : g_assert_true (g_file_info_has_attribute (fi_allusers_target, G_FILE_ATTRIBUTE_ID_FILE));
743 : 1 : g_assert_true (g_file_info_has_attribute (fi_allusers_target, G_FILE_ATTRIBUTE_STANDARD_TYPE));
744 : 1 : g_assert_true (g_file_info_has_attribute (fi_commondata_target, G_FILE_ATTRIBUTE_ID_FILE));
745 : 1 : g_assert_true (g_file_info_has_attribute (fi_commondata_target, G_FILE_ATTRIBUTE_STANDARD_TYPE));
746 : :
747 : 1 : g_assert_true (g_file_info_has_attribute (fi_allusers, G_FILE_ATTRIBUTE_ID_FILE));
748 : 1 : g_assert_true (g_file_info_has_attribute (fi_allusers, G_FILE_ATTRIBUTE_STANDARD_TYPE));
749 : 1 : g_assert_true (g_file_info_has_attribute (fi_allusers, G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK));
750 : 1 : g_assert_true (g_file_info_has_attribute (fi_allusers, G_FILE_ATTRIBUTE_DOS_REPARSE_POINT_TAG));
751 : 1 : g_assert_true (g_file_info_has_attribute (fi_allusers, G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET));
752 : :
753 : 1 : g_assert_true (g_file_info_has_attribute (fi_commondata, G_FILE_ATTRIBUTE_ID_FILE));
754 : 1 : g_assert_true (g_file_info_has_attribute (fi_commondata, G_FILE_ATTRIBUTE_STANDARD_TYPE));
755 : 1 : g_assert_true (g_file_info_has_attribute (fi_commondata, G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK));
756 : 1 : g_assert_true (g_file_info_has_attribute (fi_commondata, G_FILE_ATTRIBUTE_DOS_IS_MOUNTPOINT));
757 : 1 : g_assert_true (g_file_info_has_attribute (fi_commondata, G_FILE_ATTRIBUTE_DOS_REPARSE_POINT_TAG));
758 : 1 : g_assert_true (g_file_info_has_attribute (fi_commondata, G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET));
759 : :
760 : 1 : ft_allusers = g_file_info_get_file_type (fi_allusers);
761 : 1 : ft_allusers_target = g_file_info_get_file_type (fi_allusers_target);
762 : 1 : ft_programdata = g_file_info_get_file_type (fi_programdata);
763 : 1 : ft_commondata = g_file_info_get_file_type (fi_commondata);
764 : :
765 : 1 : g_assert_cmpint (ft_allusers, ==, G_FILE_TYPE_DIRECTORY);
766 : 1 : g_assert_cmpint (ft_allusers_target, ==, G_FILE_TYPE_DIRECTORY);
767 : 1 : g_assert_cmpint (ft_programdata, ==, G_FILE_TYPE_DIRECTORY);
768 : 1 : g_assert_cmpint (ft_commondata, ==, G_FILE_TYPE_DIRECTORY);
769 : :
770 : 1 : allusers_is_symlink = g_file_info_get_attribute_boolean (fi_allusers, G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK);
771 : 1 : allusers_reparse_tag = g_file_info_get_attribute_uint32 (fi_allusers, G_FILE_ATTRIBUTE_DOS_REPARSE_POINT_TAG);
772 : 1 : commondata_is_symlink = g_file_info_get_attribute_boolean (fi_commondata, G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK);
773 : 1 : commondata_is_mount_point = g_file_info_get_attribute_boolean (fi_commondata, G_FILE_ATTRIBUTE_DOS_IS_MOUNTPOINT);
774 : 1 : commondata_reparse_tag = g_file_info_get_attribute_uint32 (fi_commondata, G_FILE_ATTRIBUTE_DOS_REPARSE_POINT_TAG);
775 : :
776 : 1 : g_assert_true (allusers_is_symlink);
777 : 1 : g_assert_cmpuint (allusers_reparse_tag, ==, IO_REPARSE_TAG_SYMLINK);
778 : 1 : g_assert_true (commondata_is_symlink);
779 : 1 : g_assert_true (commondata_is_mount_point);
780 : 1 : g_assert_cmpuint (commondata_reparse_tag, ==, IO_REPARSE_TAG_MOUNT_POINT);
781 : :
782 : 1 : id_allusers = g_file_info_get_attribute_string (fi_allusers, G_FILE_ATTRIBUTE_ID_FILE);
783 : 1 : id_allusers_target = g_file_info_get_attribute_string (fi_allusers_target, G_FILE_ATTRIBUTE_ID_FILE);
784 : 1 : id_commondata_target = g_file_info_get_attribute_string (fi_commondata_target, G_FILE_ATTRIBUTE_ID_FILE);
785 : 1 : id_programdata = g_file_info_get_attribute_string (fi_programdata, G_FILE_ATTRIBUTE_ID_FILE);
786 : :
787 : 1 : g_assert_cmpstr (id_allusers_target, ==, id_programdata);
788 : 1 : g_assert_cmpstr (id_commondata_target, ==, id_programdata);
789 : 1 : g_assert_cmpstr (id_allusers, !=, id_programdata);
790 : :
791 : 1 : allusers_target = g_file_info_get_symlink_target (fi_allusers);
792 : :
793 : 2 : g_assert_true (g_str_has_suffix (allusers_target, "ProgramData"));
794 : :
795 : 1 : commondata_target = g_file_info_get_symlink_target (fi_commondata);
796 : :
797 : 2 : g_assert_true (g_str_has_suffix (commondata_target, "ProgramData"));
798 : :
799 : 1 : g_object_unref (fi_allusers);
800 : 1 : g_object_unref (fi_allusers_target);
801 : 1 : g_object_unref (fi_commondata);
802 : 1 : g_object_unref (fi_commondata_target);
803 : 1 : g_object_unref (fi_programdata);
804 : 1 : g_object_unref (gf_allusers);
805 : 1 : g_object_unref (gf_commondata);
806 : 1 : g_object_unref (gf_programdata);
807 : :
808 : 1 : g_free (allusers);
809 : 1 : g_free (commondata);
810 : 1 : g_free (users_dir);
811 : 1 : g_free (programdata);
812 : 1 : }
813 : :
814 : 1 : if (programdata_dir_w)
815 : 1 : CoTaskMemFree (programdata_dir_w);
816 : :
817 : 1 : if (users_dir_w)
818 : 1 : CoTaskMemFree (users_dir_w);
819 : :
820 : 1 : tmp_dir = g_dir_make_tmp ("glib_stdio_testXXXXXX", NULL);
821 : 1 : g_assert_nonnull (tmp_dir);
822 : :
823 : : /* Technically, this isn't necessary - we already assume NTFS, because of
824 : : * symlink support, and NTFS also supports sparse files. Still, given
825 : : * the amount of unusual I/O APIs called in this test, checking for
826 : : * sparse file support of the filesystem where temp directory is
827 : : * doesn't seem to be out of place.
828 : : */
829 : 1 : try_sparse = FALSE;
830 : 1 : tmp_dir_root = g_strdup (tmp_dir);
831 : : /* We need "C:\\" or "C:/", with a trailing [back]slash */
832 : 2 : for (c = tmp_dir_root; c && c[0] && c[1]; c++)
833 : 2 : if (c[0] == ':')
834 : : {
835 : 1 : c[2] = '\0';
836 : 1 : break;
837 : : }
838 : 1 : tmp_dir_root_w = g_utf8_to_utf16 (tmp_dir_root, -1, NULL, NULL, NULL);
839 : 1 : g_assert_nonnull (tmp_dir_root_w);
840 : 1 : g_free (tmp_dir_root);
841 : 1 : g_assert_true (GetVolumeInformationW (tmp_dir_root_w, NULL, 0, NULL, NULL, &fsflags, NULL, 0));
842 : 1 : g_free (tmp_dir_root_w);
843 : 1 : try_sparse = (fsflags & FILE_SUPPORTS_SPARSE_FILES) == FILE_SUPPORTS_SPARSE_FILES;
844 : :
845 : 1 : p0 = g_build_filename (tmp_dir, "zool", NULL);
846 : 1 : p1 = g_build_filename (tmp_dir, "looz", NULL);
847 : 1 : ps = g_build_filename (tmp_dir, "sparse", NULL);
848 : :
849 : 1 : if (try_sparse)
850 : : {
851 : : FILE_SET_SPARSE_BUFFER ssb;
852 : : FILE_ZERO_DATA_INFORMATION zdi;
853 : :
854 : 1 : g_remove (ps);
855 : :
856 : 1 : f = g_fopen (ps, "wbe");
857 : 1 : g_assert_nonnull (f);
858 : :
859 : 1 : h = (HANDLE) _get_osfhandle (fileno (f));
860 : 1 : g_assert_cmpuint ((guintptr) h, !=, (guintptr) INVALID_HANDLE_VALUE);
861 : :
862 : 1 : ssb.SetSparse = TRUE;
863 : 1 : g_assert_true (DeviceIoControl (h,
864 : : FSCTL_SET_SPARSE,
865 : : &ssb, sizeof (ssb),
866 : : NULL, 0, NULL, NULL));
867 : :
868 : : /* Make it a sparse file that starts with 4GBs of zeros */
869 : 1 : zdi.FileOffset.QuadPart = 0;
870 : 1 : zdi.BeyondFinalZero.QuadPart = 0xFFFFFFFFULL + 1;
871 : 1 : g_assert_true (DeviceIoControl (h,
872 : : FSCTL_SET_ZERO_DATA,
873 : : &zdi, sizeof (zdi),
874 : : NULL, 0, NULL, NULL));
875 : :
876 : : /* Let's not keep this seemingly 4GB monster around
877 : : * longer than we absolutely need to. Do all operations
878 : : * without assertions, then remove the file immediately.
879 : : */
880 : 1 : _fseeki64 (f, 0xFFFFFFFFULL, SEEK_SET);
881 : 1 : fprintf (f, "Hello 4GB World!");
882 : 1 : fflush (f);
883 : 1 : fclose (f);
884 : :
885 : 1 : memset (&statbuf_ps, 0, sizeof (statbuf_ps));
886 : :
887 : 1 : g_stat (ps, &statbuf_ps);
888 : :
889 : 1 : gf_ps = g_file_new_for_path (ps);
890 : :
891 : 1 : fi_ps = g_file_query_info (gf_ps,
892 : : G_FILE_ATTRIBUTE_STANDARD_SIZE ","
893 : : G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE,
894 : : G_FILE_QUERY_INFO_NONE,
895 : : NULL, NULL);
896 : :
897 : 1 : g_remove (ps);
898 : :
899 : 1 : g_assert_true (g_file_info_has_attribute (fi_ps, G_FILE_ATTRIBUTE_STANDARD_SIZE));
900 : 1 : g_assert_true (g_file_info_has_attribute (fi_ps, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE));
901 : :
902 : 1 : size_ps = g_file_info_get_attribute_uint64 (fi_ps, G_FILE_ATTRIBUTE_STANDARD_SIZE);
903 : 1 : alsize_ps = g_file_info_get_attribute_uint64 (fi_ps, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE);
904 : :
905 : : /* allocated size should small (usually - size of the FS cluster,
906 : : * let's assume it's less than 1 gigabyte),
907 : : * size should be more than 4 gigabytes,
908 : : * st_size should not exceed its 0xFFFFFFFF 32-bit limit,
909 : : * and should be nonzero (this also detects a failed g_stat() earlier).
910 : : */
911 : 1 : g_assert_cmpuint (alsize_ps, <, 0x40000000);
912 : 1 : g_assert_cmpuint (size_ps, >, G_GUINT64_CONSTANT (0xFFFFFFFF));
913 : 1 : g_assert_cmpuint (statbuf_ps.st_size, >, 0);
914 : : #if defined(_WIN64)
915 : 1 : g_assert_cmpuint (statbuf_ps.st_size, ==, G_GUINT64_CONSTANT (0x10000000f));
916 : : #else
917 : : g_assert_cmpuint (statbuf_ps.st_size, <=, 0xFFFFFFFF);
918 : : #endif
919 : :
920 : 1 : g_object_unref (fi_ps);
921 : 1 : g_object_unref (gf_ps);
922 : 1 : }
923 : :
924 : : /* Wa-a-ay past 02/07/2106 @ 6:28am (UTC),
925 : : * which is the date corresponding to 0xFFFFFFFF + 1.
926 : : * This is easier to check than Y2038 (0x80000000 + 1),
927 : : * since there's no need to worry about signedness this way.
928 : : */
929 : 1 : st.wYear = 2106;
930 : 1 : st.wMonth = 2;
931 : 1 : st.wDay = 9;
932 : 1 : st.wHour = 0;
933 : 1 : st.wMinute = 0;
934 : 1 : st.wSecond = 0;
935 : 1 : st.wMilliseconds = 0;
936 : :
937 : 1 : g_assert_true (SystemTimeToFileTime (&st, &ft));
938 : :
939 : 1 : f = g_fopen (p0, "we");
940 : 1 : g_assert_nonnull (f);
941 : :
942 : 1 : h = (HANDLE) _get_osfhandle (fileno (f));
943 : 1 : g_assert_cmpuint ((guintptr) h, !=, (guintptr) INVALID_HANDLE_VALUE);
944 : :
945 : 1 : fprintf (f, "1");
946 : 1 : fflush (f);
947 : :
948 : 1 : g_assert_true (SetFileTime (h, &ft, &ft, &ft));
949 : :
950 : 1 : fclose (f);
951 : :
952 : 1 : f = g_fopen (p1, "we");
953 : 1 : g_assert_nonnull (f);
954 : :
955 : 1 : fclose (f);
956 : :
957 : 1 : memset (&statbuf_p0, 0, sizeof (statbuf_p0));
958 : 1 : memset (&statbuf_p1, 0, sizeof (statbuf_p1));
959 : :
960 : 1 : g_assert_cmpint (g_stat (p0, &statbuf_p0), ==, 0);
961 : 1 : g_assert_cmpint (g_stat (p1, &statbuf_p1), ==, 0);
962 : :
963 : 1 : gf_p0 = g_file_new_for_path (p0);
964 : 1 : gf_p1 = g_file_new_for_path (p1);
965 : :
966 : 1 : fi_p0 = g_file_query_info (gf_p0,
967 : : G_FILE_ATTRIBUTE_STANDARD_SIZE ","
968 : : G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE ","
969 : : G_FILE_ATTRIBUTE_ID_FILE ","
970 : : G_FILE_ATTRIBUTE_TIME_MODIFIED ","
971 : : G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC ","
972 : : G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC,
973 : : G_FILE_QUERY_INFO_NONE,
974 : : NULL, NULL);
975 : :
976 : 1 : fi_p1 = g_file_query_info (gf_p1,
977 : : G_FILE_ATTRIBUTE_STANDARD_SIZE ","
978 : : G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE ","
979 : : G_FILE_ATTRIBUTE_ID_FILE ","
980 : : G_FILE_ATTRIBUTE_TIME_MODIFIED ","
981 : : G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC ","
982 : : G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC,
983 : : G_FILE_QUERY_INFO_NONE,
984 : : NULL, NULL);
985 : :
986 : 1 : g_assert_true (g_file_info_has_attribute (fi_p0, G_FILE_ATTRIBUTE_STANDARD_SIZE));
987 : 1 : g_assert_true (g_file_info_has_attribute (fi_p0, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE));
988 : 1 : g_assert_true (g_file_info_has_attribute (fi_p0, G_FILE_ATTRIBUTE_ID_FILE));
989 : 1 : g_assert_true (g_file_info_has_attribute (fi_p0, G_FILE_ATTRIBUTE_TIME_MODIFIED));
990 : 1 : g_assert_true (g_file_info_has_attribute (fi_p0, G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC));
991 : 1 : g_assert_true (g_file_info_has_attribute (fi_p0, G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC));
992 : :
993 : 1 : g_assert_true (g_file_info_has_attribute (fi_p1, G_FILE_ATTRIBUTE_STANDARD_SIZE));
994 : 1 : g_assert_true (g_file_info_has_attribute (fi_p1, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE));
995 : 1 : g_assert_true (g_file_info_has_attribute (fi_p1, G_FILE_ATTRIBUTE_ID_FILE));
996 : 1 : g_assert_true (g_file_info_has_attribute (fi_p1, G_FILE_ATTRIBUTE_TIME_MODIFIED));
997 : 1 : g_assert_true (g_file_info_has_attribute (fi_p1, G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC));
998 : 1 : g_assert_true (g_file_info_has_attribute (fi_p1, G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC));
999 : :
1000 : 1 : size_p0 = g_file_info_get_attribute_uint64 (fi_p0, G_FILE_ATTRIBUTE_STANDARD_SIZE);
1001 : 1 : alsize_p0 = g_file_info_get_attribute_uint64 (fi_p0, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE);
1002 : :
1003 : : /* size should be 1, allocated size should be something else
1004 : : * (could be 0 or the size of the FS cluster, but never 1).
1005 : : */
1006 : 1 : g_assert_cmpuint (size_p0, ==, statbuf_p0.st_size);
1007 : 1 : g_assert_cmpuint (size_p0, ==, 1);
1008 : 1 : g_assert_cmpuint (alsize_p0, !=, size_p0);
1009 : :
1010 : 1 : id_p0 = g_file_info_get_attribute_string (fi_p0, G_FILE_ATTRIBUTE_ID_FILE);
1011 : 1 : id_p1 = g_file_info_get_attribute_string (fi_p1, G_FILE_ATTRIBUTE_ID_FILE);
1012 : :
1013 : : /* st_ino from W32 stat() is useless for file identification.
1014 : : * It will be either 0, or it will be the same for both files.
1015 : : */
1016 : 1 : g_assert_cmpint (statbuf_p0.st_ino, ==, statbuf_p1.st_ino);
1017 : 1 : g_assert_cmpstr (id_p0, !=, id_p1);
1018 : :
1019 : 1 : time_p0 = g_file_info_get_attribute_uint64 (fi_p0, G_FILE_ATTRIBUTE_TIME_MODIFIED);
1020 : :
1021 : : /* Check that GFileInfo doesn't suffer from Y2106 problem.
1022 : : * Don't check stat(), as its contents may vary depending on
1023 : : * the host platform architecture
1024 : : * (time fields are 32-bit on 32-bit Windows,
1025 : : * and 64-bit on 64-bit Windows, usually),
1026 : : * so it *can* pass this test in some cases.
1027 : : */
1028 : 1 : g_assert_cmpuint (time_p0, >, G_GUINT64_CONSTANT (0xFFFFFFFF));
1029 : :
1030 : 1 : dt = g_file_info_get_modification_date_time (fi_p0);
1031 : 1 : g_assert_nonnull (dt);
1032 : 1 : dt2 = g_date_time_add (dt, G_USEC_PER_SEC / 100 * 200);
1033 : 1 : g_object_unref (fi_p0);
1034 : 1 : fi_p0 = g_file_info_new ();
1035 : 1 : g_file_info_set_modification_date_time (fi_p0, dt2);
1036 : :
1037 : 1 : g_assert_true (g_file_set_attributes_from_info (gf_p0,
1038 : 1 : fi_p0,
1039 : : G_FILE_QUERY_INFO_NONE,
1040 : : NULL,
1041 : : NULL));
1042 : 1 : g_date_time_unref (dt2);
1043 : 1 : g_object_unref (fi_p0);
1044 : 1 : fi_p0 = g_file_query_info (gf_p0,
1045 : : G_FILE_ATTRIBUTE_TIME_MODIFIED ","
1046 : : G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC ","
1047 : : G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC,
1048 : : G_FILE_QUERY_INFO_NONE,
1049 : : NULL, NULL);
1050 : 1 : dt2 = g_file_info_get_modification_date_time (fi_p0);
1051 : 1 : ts = g_date_time_difference (dt2, dt);
1052 : 1 : g_assert_cmpint (ts, >, 0);
1053 : 1 : g_assert_cmpint (ts, <, G_USEC_PER_SEC / 100 * 300);
1054 : :
1055 : 1 : g_date_time_unref (dt);
1056 : 1 : g_date_time_unref (dt2);
1057 : :
1058 : 1 : g_file_info_set_attribute_uint64 (fi_p0,
1059 : : G_FILE_ATTRIBUTE_TIME_MODIFIED,
1060 : : one_sec_before_systemtime_limit);
1061 : 1 : g_file_info_set_attribute_uint32 (fi_p0, G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC, 0);
1062 : 1 : g_assert_true (g_file_set_attributes_from_info (gf_p0,
1063 : 1 : fi_p0,
1064 : : G_FILE_QUERY_INFO_NONE,
1065 : : NULL,
1066 : : NULL));
1067 : :
1068 : 1 : g_file_info_set_attribute_uint64 (fi_p0,
1069 : : G_FILE_ATTRIBUTE_TIME_MODIFIED,
1070 : : one_sec_before_systemtime_limit + G_USEC_PER_SEC * 2);
1071 : 1 : g_file_info_set_attribute_uint32 (fi_p0, G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC, 0);
1072 : 2 : retval = g_file_set_attributes_from_info (gf_p0,
1073 : 1 : fi_p0,
1074 : : G_FILE_QUERY_INFO_NONE,
1075 : : NULL,
1076 : : &local_error);
1077 : 1 : g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA);
1078 : 1 : g_assert_false (retval);
1079 : 1 : g_clear_error (&local_error);
1080 : :
1081 : 1 : g_object_unref (fi_p0);
1082 : 1 : g_object_unref (fi_p1);
1083 : 1 : g_object_unref (gf_p0);
1084 : 1 : g_object_unref (gf_p1);
1085 : 1 : g_remove (p0);
1086 : 1 : g_remove (p1);
1087 : 1 : g_free (p0);
1088 : 1 : g_free (p1);
1089 : 1 : g_rmdir (tmp_dir);
1090 : 1 : }
1091 : : #endif
1092 : :
1093 : : static void
1094 : 2 : test_xattrs (void)
1095 : : {
1096 : 2 : GFile *file = NULL;
1097 : 2 : GFileIOStream *stream = NULL;
1098 : 2 : GFileInfo *file_info0 = NULL, *file_info1 = NULL, *file_info2 = NULL;
1099 : 2 : GError *local_error = NULL;
1100 : :
1101 : 2 : g_test_summary ("Test setting and getting escaped xattrs");
1102 : :
1103 : : /* Create a temporary file; no need to write anything to it. */
1104 : 2 : file = g_file_new_tmp ("g-file-info-test-xattrs-XXXXXX", &stream, &local_error);
1105 : 2 : g_assert_no_error (local_error);
1106 : 2 : g_assert_nonnull (file);
1107 : :
1108 : 2 : g_io_stream_close (G_IO_STREAM (stream), NULL, NULL);
1109 : 2 : g_object_unref (stream);
1110 : :
1111 : : /* Check the existing xattrs. */
1112 : 2 : file_info0 = g_file_query_info (file, "xattr::*", G_FILE_QUERY_INFO_NONE, NULL, &local_error);
1113 : 2 : g_assert_no_error (local_error);
1114 : 2 : g_assert_nonnull (file_info0);
1115 : :
1116 : : /* Set some new xattrs, with escaping and some embedded nuls. */
1117 : 2 : g_file_info_set_attribute_string (file_info0, "xattr::escaped", "hello\\x82\\x80\\xbd");
1118 : 2 : g_file_info_set_attribute_string (file_info0, "xattr::string", "hi there");
1119 : 2 : g_file_info_set_attribute_string (file_info0, "xattr::embedded-nul", "hi\\x00there");
1120 : 2 : g_file_info_set_attribute_string (file_info0, "xattr::deleteme", "this attribute will be deleted");
1121 : :
1122 : 2 : g_file_set_attributes_from_info (file, file_info0, G_FILE_QUERY_INFO_NONE, NULL, &local_error);
1123 : :
1124 : 2 : g_object_unref (file_info0);
1125 : :
1126 : 2 : if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
1127 : : {
1128 : 1 : g_test_skip ("xattrs not supported on this file system");
1129 : 1 : g_clear_error (&local_error);
1130 : 1 : }
1131 : : else
1132 : : {
1133 : 1 : g_assert_no_error (local_error);
1134 : :
1135 : : /* Check they were set properly. */
1136 : 1 : file_info1 = g_file_query_info (file, "xattr::*", G_FILE_QUERY_INFO_NONE, NULL, &local_error);
1137 : 1 : g_assert_no_error (local_error);
1138 : 1 : g_assert_nonnull (file_info1);
1139 : :
1140 : 1 : g_assert_true (g_file_info_has_namespace (file_info1, "xattr"));
1141 : :
1142 : 1 : g_assert_cmpstr (g_file_info_get_attribute_string (file_info1, "xattr::escaped"), ==, "hello\\x82\\x80\\xbd");
1143 : 1 : g_assert_cmpstr (g_file_info_get_attribute_string (file_info1, "xattr::string"), ==, "hi there");
1144 : 1 : g_assert_cmpstr (g_file_info_get_attribute_string (file_info1, "xattr::embedded-nul"), ==, "hi\\x00there");
1145 : 1 : g_assert_cmpstr (g_file_info_get_attribute_string (file_info1, "xattr::deleteme"), ==, "this attribute will be deleted");
1146 : :
1147 : 1 : g_object_unref (file_info1);
1148 : :
1149 : : /* Check whether removing extended attributes works. */
1150 : 1 : g_file_set_attribute (file, "xattr::deleteme", G_FILE_ATTRIBUTE_TYPE_INVALID, NULL, G_FILE_QUERY_INFO_NONE, NULL, &local_error);
1151 : 1 : g_assert_no_error (local_error);
1152 : 1 : file_info2 = g_file_query_info (file, "xattr::deleteme", G_FILE_QUERY_INFO_NONE, NULL, &local_error);
1153 : 1 : g_assert_no_error (local_error);
1154 : 1 : g_assert_nonnull (file_info2);
1155 : 1 : g_assert_cmpstr (g_file_info_get_attribute_string (file_info2, "xattr::deleteme"), ==, NULL);
1156 : :
1157 : 1 : g_object_unref (file_info2);
1158 : : }
1159 : :
1160 : : /* Tidy up. */
1161 : 2 : g_file_delete (file, NULL, NULL);
1162 : :
1163 : 2 : g_object_unref (file);
1164 : 2 : }
1165 : :
1166 : : static void
1167 : 2 : test_set_modified_date_time_precision (void)
1168 : : {
1169 : 2 : GDateTime *modified = NULL;
1170 : 2 : GFile *file = NULL;
1171 : 2 : GFileIOStream *stream = NULL;
1172 : 2 : GFileInfo *info = NULL;
1173 : 2 : GError *local_error = NULL;
1174 : :
1175 : :
1176 : 2 : g_test_summary ("Test that g_file_info_set_modified_date_time() preserves microseconds");
1177 : 2 : g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/3116");
1178 : :
1179 : 2 : file = g_file_new_tmp ("g-file-info-test-set-modified-date-time-precision-XXXXXX", &stream, &local_error);
1180 : 2 : g_assert_no_error (local_error);
1181 : :
1182 : 2 : modified = g_date_time_new_from_iso8601 ("2000-01-01T00:00:00.123456Z", NULL);
1183 : :
1184 : 2 : info = g_file_query_info (file,
1185 : : G_FILE_ATTRIBUTE_TIME_MODIFIED ","
1186 : : G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC ","
1187 : : G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC, G_FILE_QUERY_INFO_NONE, NULL, &local_error);
1188 : 2 : g_assert_no_error (local_error);
1189 : :
1190 : 2 : g_file_info_set_modification_date_time (info, modified);
1191 : 2 : g_assert_true (g_file_set_attributes_from_info (file, info, G_FILE_QUERY_INFO_NONE, NULL, &local_error));
1192 : 2 : g_assert_no_error (local_error);
1193 : :
1194 : 2 : g_clear_object (&info);
1195 : 2 : g_clear_pointer (&modified, g_date_time_unref);
1196 : :
1197 : 2 : info = g_file_query_info (file,
1198 : : G_FILE_ATTRIBUTE_TIME_MODIFIED ","
1199 : : G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC ","
1200 : : G_FILE_ATTRIBUTE_TIME_MODIFIED_NSEC, G_FILE_QUERY_INFO_NONE, NULL, &local_error);
1201 : 2 : g_assert_no_error (local_error);
1202 : :
1203 : 2 : g_assert_cmpuint (g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC), ==, 123456);
1204 : :
1205 : 2 : g_clear_object (&stream);
1206 : 2 : g_clear_object (&info);
1207 : 2 : g_clear_object (&file);
1208 : 2 : }
1209 : :
1210 : : static void
1211 : 2 : test_set_symlink_target (void)
1212 : : {
1213 : 2 : GFile *file = NULL;
1214 : 2 : GFileIOStream *stream = NULL;
1215 : 2 : GFileInfo *info = NULL;
1216 : 2 : GError *local_error = NULL;
1217 : :
1218 : 2 : g_test_summary ("Test that g_file_info_set_symlink_target() sets symlink target correctly");
1219 : 2 : g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/3897");
1220 : :
1221 : : /* Create a temp file to reserve a unique filename for the test */
1222 : 2 : file = g_file_new_tmp ("g-file-info-test-set-symlink-XXXXXX", &stream, &local_error);
1223 : 2 : g_assert_no_error (local_error);
1224 : :
1225 : : /* Remove the file and recreate it as a symlink */
1226 : 2 : g_file_delete (file, NULL, NULL);
1227 : :
1228 : 2 : if (!g_file_make_symbolic_link (file, "initial-target", NULL, &local_error) &&
1229 : 1 : g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
1230 : : {
1231 : 1 : g_clear_error (&local_error);
1232 : 1 : g_test_skip ("Skipping testing symbolic links as they’re not supported on this system");
1233 : 1 : return;
1234 : : }
1235 : :
1236 : 1 : g_assert_no_error (local_error);
1237 : :
1238 : 1 : info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET,
1239 : : G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &local_error);
1240 : 1 : g_assert_no_error (local_error);
1241 : :
1242 : : /* Try setting the symlink target when there isn’t one already set via GIO */
1243 : 1 : g_file_info_set_symlink_target (info, "symlink-target");
1244 : 1 : g_file_set_attributes_from_info (file, info, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &local_error);
1245 : 1 : g_assert_no_error (local_error);
1246 : :
1247 : 1 : g_clear_object (&info);
1248 : :
1249 : 1 : info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET,
1250 : : G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &local_error);
1251 : 1 : g_assert_no_error (local_error);
1252 : :
1253 : 1 : g_assert_cmpstr (g_file_info_get_symlink_target (info), ==, "symlink-target");
1254 : :
1255 : : /* Now try setting it again when there is one already */
1256 : 1 : g_file_info_set_symlink_target (info, "symlink-target2");
1257 : 1 : g_file_set_attributes_from_info (file, info, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &local_error);
1258 : 1 : g_assert_no_error (local_error);
1259 : :
1260 : 1 : g_clear_object (&info);
1261 : :
1262 : 1 : info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET,
1263 : : G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &local_error);
1264 : 1 : g_assert_no_error (local_error);
1265 : :
1266 : 1 : g_assert_cmpstr (g_file_info_get_symlink_target (info), ==, "symlink-target2");
1267 : :
1268 : : /* Clean up */
1269 : 1 : g_file_delete (file, NULL, NULL);
1270 : :
1271 : 1 : g_clear_object (&stream);
1272 : 1 : g_clear_object (&info);
1273 : 1 : g_clear_object (&file);
1274 : 1 : }
1275 : :
1276 : : int
1277 : 2 : main (int argc,
1278 : : char *argv[])
1279 : : {
1280 : 2 : g_test_init (&argc, &argv, NULL);
1281 : :
1282 : 2 : g_test_add_func ("/g-file-info/test_g_file_info", test_g_file_info);
1283 : 2 : g_test_add_func ("/g-file-info/test_g_file_info/modification-time", test_g_file_info_modification_time);
1284 : 2 : g_test_add_func ("/g-file-info/test_g_file_info/access-time", test_g_file_info_access_time);
1285 : 2 : g_test_add_func ("/g-file-info/test_g_file_info/creation-time", test_g_file_info_creation_time);
1286 : 2 : g_test_add_func ("/g-file-info/test_g_file_info/icons", test_g_file_info_icons);
1287 : : #ifdef G_OS_WIN32
1288 : 1 : g_test_add_func ("/g-file-info/internal-enhanced-stdio", test_internal_enhanced_stdio);
1289 : : #endif
1290 : 2 : g_test_add_func ("/g-file-info/xattrs", test_xattrs);
1291 : 2 : g_test_add_func ("/g-file-info/set-modified-date-time-precision", test_set_modified_date_time_precision);
1292 : 2 : g_test_add_func ("/g-file-info/set-symlink-target", test_set_symlink_target);
1293 : :
1294 : 2 : return g_test_run();
1295 : : }
|