]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-fs-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
5 #include "alloc-util.h"
10 #include "id128-util.h"
13 #include "path-util.h"
15 #include "stdio-util.h"
16 #include "string-util.h"
18 #include "user-util.h"
21 static void test_chase_symlinks ( void ) {
22 _cleanup_free_
char * result
= NULL
;
23 char temp
[] = "/tmp/test-chase.XXXXXX" ;
24 const char * top
, * p
, * pslash
, * q
, * qslash
;
28 assert_se ( mkdtemp ( temp
));
30 top
= strjoina ( temp
, "/top" );
31 assert_se ( mkdir ( top
, 0700 ) >= 0 );
33 p
= strjoina ( top
, "/dot" );
34 assert_se ( symlink ( "." , p
) >= 0 );
36 p
= strjoina ( top
, "/dotdot" );
37 assert_se ( symlink ( ".." , p
) >= 0 );
39 p
= strjoina ( top
, "/dotdota" );
40 assert_se ( symlink ( "../a" , p
) >= 0 );
42 p
= strjoina ( temp
, "/a" );
43 assert_se ( symlink ( "b" , p
) >= 0 );
45 p
= strjoina ( temp
, "/b" );
46 assert_se ( symlink ( "/usr" , p
) >= 0 );
48 p
= strjoina ( temp
, "/start" );
49 assert_se ( symlink ( "top/dot/dotdota" , p
) >= 0 );
51 /* Paths that use symlinks underneath the "root" */
53 r
= chase_symlinks ( p
, NULL
, 0 , & result
);
55 assert_se ( path_equal ( result
, "/usr" ));
56 result
= mfree ( result
);
58 pslash
= strjoina ( p
, "/" );
59 r
= chase_symlinks ( pslash
, NULL
, 0 , & result
);
61 assert_se ( path_equal ( result
, "/usr/" ));
62 result
= mfree ( result
);
64 r
= chase_symlinks ( p
, temp
, 0 , & result
);
65 assert_se ( r
== - ENOENT
);
67 r
= chase_symlinks ( pslash
, temp
, 0 , & result
);
68 assert_se ( r
== - ENOENT
);
70 q
= strjoina ( temp
, "/usr" );
72 r
= chase_symlinks ( p
, temp
, CHASE_NONEXISTENT
, & result
);
74 assert_se ( path_equal ( result
, q
));
75 result
= mfree ( result
);
77 qslash
= strjoina ( q
, "/" );
79 r
= chase_symlinks ( pslash
, temp
, CHASE_NONEXISTENT
, & result
);
81 assert_se ( path_equal ( result
, qslash
));
82 result
= mfree ( result
);
84 assert_se ( mkdir ( q
, 0700 ) >= 0 );
86 r
= chase_symlinks ( p
, temp
, 0 , & result
);
88 assert_se ( path_equal ( result
, q
));
89 result
= mfree ( result
);
91 r
= chase_symlinks ( pslash
, temp
, 0 , & result
);
93 assert_se ( path_equal ( result
, qslash
));
94 result
= mfree ( result
);
96 p
= strjoina ( temp
, "/slash" );
97 assert_se ( symlink ( "/" , p
) >= 0 );
99 r
= chase_symlinks ( p
, NULL
, 0 , & result
);
101 assert_se ( path_equal ( result
, "/" ));
102 result
= mfree ( result
);
104 r
= chase_symlinks ( p
, temp
, 0 , & result
);
106 assert_se ( path_equal ( result
, temp
));
107 result
= mfree ( result
);
109 /* Paths that would "escape" outside of the "root" */
111 p
= strjoina ( temp
, "/6dots" );
112 assert_se ( symlink ( "../../.." , p
) >= 0 );
114 r
= chase_symlinks ( p
, temp
, 0 , & result
);
115 assert_se ( r
> 0 && path_equal ( result
, temp
));
116 result
= mfree ( result
);
118 p
= strjoina ( temp
, "/6dotsusr" );
119 assert_se ( symlink ( "../../../usr" , p
) >= 0 );
121 r
= chase_symlinks ( p
, temp
, 0 , & result
);
122 assert_se ( r
> 0 && path_equal ( result
, q
));
123 result
= mfree ( result
);
125 p
= strjoina ( temp
, "/top/8dotsusr" );
126 assert_se ( symlink ( "../../../../usr" , p
) >= 0 );
128 r
= chase_symlinks ( p
, temp
, 0 , & result
);
129 assert_se ( r
> 0 && path_equal ( result
, q
));
130 result
= mfree ( result
);
132 /* Paths that contain repeated slashes */
134 p
= strjoina ( temp
, "/slashslash" );
135 assert_se ( symlink ( "///usr///" , p
) >= 0 );
137 r
= chase_symlinks ( p
, NULL
, 0 , & result
);
139 assert_se ( path_equal ( result
, "/usr" ));
140 result
= mfree ( result
);
142 r
= chase_symlinks ( p
, temp
, 0 , & result
);
144 assert_se ( path_equal ( result
, q
));
145 result
= mfree ( result
);
149 r
= chase_symlinks ( "/etc/./.././" , NULL
, 0 , & result
);
151 assert_se ( path_equal ( result
, "/" ));
152 result
= mfree ( result
);
154 r
= chase_symlinks ( "/etc/./.././" , "/etc" , 0 , & result
);
155 assert_se ( r
> 0 && path_equal ( result
, "/etc" ));
156 result
= mfree ( result
);
158 r
= chase_symlinks ( "/../.././//../../etc" , NULL
, 0 , & result
);
160 assert_se ( streq ( result
, "/etc" ));
161 result
= mfree ( result
);
163 r
= chase_symlinks ( "/../.././//../../test-chase.fsldajfl" , NULL
, CHASE_NONEXISTENT
, & result
);
165 assert_se ( streq ( result
, "/test-chase.fsldajfl" ));
166 result
= mfree ( result
);
168 r
= chase_symlinks ( "/../.././//../../etc" , "/" , CHASE_PREFIX_ROOT
, & result
);
170 assert_se ( streq ( result
, "/etc" ));
171 result
= mfree ( result
);
173 r
= chase_symlinks ( "/../.././//../../test-chase.fsldajfl" , "/" , CHASE_PREFIX_ROOT
| CHASE_NONEXISTENT
, & result
);
175 assert_se ( streq ( result
, "/test-chase.fsldajfl" ));
176 result
= mfree ( result
);
178 r
= chase_symlinks ( "/etc/machine-id/foo" , NULL
, 0 , & result
);
179 assert_se ( r
== - ENOTDIR
);
180 result
= mfree ( result
);
182 /* Path that loops back to self */
184 p
= strjoina ( temp
, "/recursive-symlink" );
185 assert_se ( symlink ( "recursive-symlink" , p
) >= 0 );
186 r
= chase_symlinks ( p
, NULL
, 0 , & result
);
187 assert_se ( r
== - ELOOP
);
189 /* Path which doesn't exist */
191 p
= strjoina ( temp
, "/idontexist" );
192 r
= chase_symlinks ( p
, NULL
, 0 , & result
);
193 assert_se ( r
== - ENOENT
);
195 r
= chase_symlinks ( p
, NULL
, CHASE_NONEXISTENT
, & result
);
197 assert_se ( path_equal ( result
, p
));
198 result
= mfree ( result
);
200 p
= strjoina ( temp
, "/idontexist/meneither" );
201 r
= chase_symlinks ( p
, NULL
, 0 , & result
);
202 assert_se ( r
== - ENOENT
);
204 r
= chase_symlinks ( p
, NULL
, CHASE_NONEXISTENT
, & result
);
206 assert_se ( path_equal ( result
, p
));
207 result
= mfree ( result
);
209 /* Path which doesn't exist, but contains weird stuff */
211 p
= strjoina ( temp
, "/idontexist/.." );
212 r
= chase_symlinks ( p
, NULL
, 0 , & result
);
213 assert_se ( r
== - ENOENT
);
215 r
= chase_symlinks ( p
, NULL
, CHASE_NONEXISTENT
, & result
);
216 assert_se ( r
== - ENOENT
);
218 p
= strjoina ( temp
, "/target" );
219 q
= strjoina ( temp
, "/top" );
220 assert_se ( symlink ( q
, p
) >= 0 );
221 p
= strjoina ( temp
, "/target/idontexist" );
222 r
= chase_symlinks ( p
, NULL
, 0 , & result
);
223 assert_se ( r
== - ENOENT
);
225 if ( geteuid () == 0 ) {
226 p
= strjoina ( temp
, "/priv1" );
227 assert_se ( mkdir ( p
, 0755 ) >= 0 );
229 q
= strjoina ( p
, "/priv2" );
230 assert_se ( mkdir ( q
, 0755 ) >= 0 );
232 assert_se ( chase_symlinks ( q
, NULL
, CHASE_SAFE
, NULL
) >= 0 );
234 assert_se ( chown ( q
, UID_NOBODY
, GID_NOBODY
) >= 0 );
235 assert_se ( chase_symlinks ( q
, NULL
, CHASE_SAFE
, NULL
) >= 0 );
237 assert_se ( chown ( p
, UID_NOBODY
, GID_NOBODY
) >= 0 );
238 assert_se ( chase_symlinks ( q
, NULL
, CHASE_SAFE
, NULL
) >= 0 );
240 assert_se ( chown ( q
, 0 , 0 ) >= 0 );
241 assert_se ( chase_symlinks ( q
, NULL
, CHASE_SAFE
, NULL
) == - EPERM
);
243 assert_se ( rmdir ( q
) >= 0 );
244 assert_se ( symlink ( "/etc/passwd" , q
) >= 0 );
245 assert_se ( chase_symlinks ( q
, NULL
, CHASE_SAFE
, NULL
) == - EPERM
);
247 assert_se ( chown ( p
, 0 , 0 ) >= 0 );
248 assert_se ( chase_symlinks ( q
, NULL
, CHASE_SAFE
, NULL
) >= 0 );
251 p
= strjoina ( temp
, "/machine-id-test" );
252 assert_se ( symlink ( "/usr/../etc/./machine-id" , p
) >= 0 );
254 pfd
= chase_symlinks ( p
, NULL
, CHASE_OPEN
, NULL
);
255 if ( pfd
!= - ENOENT
) {
256 _cleanup_close_
int fd
= - 1 ;
261 fd
= fd_reopen ( pfd
, O_RDONLY
| O_CLOEXEC
);
265 assert_se ( id128_read_fd ( fd
, ID128_PLAIN
, & a
) >= 0 );
266 assert_se ( sd_id128_get_machine (& b
) >= 0 );
267 assert_se ( sd_id128_equal ( a
, b
));
270 /* Test CHASE_NOFOLLOW */
272 p
= strjoina ( temp
, "/target" );
273 q
= strjoina ( temp
, "/symlink" );
274 assert_se ( symlink ( p
, q
) >= 0 );
275 pfd
= chase_symlinks ( q
, NULL
, CHASE_OPEN
| CHASE_NOFOLLOW
, & result
);
277 assert_se ( path_equal ( result
, q
));
278 assert_se ( fstat ( pfd
, & st
) >= 0 );
279 assert_se ( S_ISLNK ( st
. st_mode
));
280 result
= mfree ( result
);
282 /* s1 -> s2 -> nonexistent */
283 q
= strjoina ( temp
, "/s1" );
284 assert_se ( symlink ( "s2" , q
) >= 0 );
285 p
= strjoina ( temp
, "/s2" );
286 assert_se ( symlink ( "nonexistent" , p
) >= 0 );
287 pfd
= chase_symlinks ( q
, NULL
, CHASE_OPEN
| CHASE_NOFOLLOW
, & result
);
289 assert_se ( path_equal ( result
, q
));
290 assert_se ( fstat ( pfd
, & st
) >= 0 );
291 assert_se ( S_ISLNK ( st
. st_mode
));
292 result
= mfree ( result
);
296 p
= strjoina ( temp
, "/start" );
297 r
= chase_symlinks ( p
, NULL
, CHASE_STEP
, & result
);
299 p
= strjoina ( temp
, "/top/dot/dotdota" );
300 assert_se ( streq ( p
, result
));
301 result
= mfree ( result
);
303 r
= chase_symlinks ( p
, NULL
, CHASE_STEP
, & result
);
305 p
= strjoina ( temp
, "/top/./dotdota" );
306 assert_se ( streq ( p
, result
));
307 result
= mfree ( result
);
309 r
= chase_symlinks ( p
, NULL
, CHASE_STEP
, & result
);
311 p
= strjoina ( temp
, "/top/../a" );
312 assert_se ( streq ( p
, result
));
313 result
= mfree ( result
);
315 r
= chase_symlinks ( p
, NULL
, CHASE_STEP
, & result
);
317 p
= strjoina ( temp
, "/a" );
318 assert_se ( streq ( p
, result
));
319 result
= mfree ( result
);
321 r
= chase_symlinks ( p
, NULL
, CHASE_STEP
, & result
);
323 p
= strjoina ( temp
, "/b" );
324 assert_se ( streq ( p
, result
));
325 result
= mfree ( result
);
327 r
= chase_symlinks ( p
, NULL
, CHASE_STEP
, & result
);
329 assert_se ( streq ( "/usr" , result
));
330 result
= mfree ( result
);
332 r
= chase_symlinks ( "/usr" , NULL
, CHASE_STEP
, & result
);
334 assert_se ( streq ( "/usr" , result
));
335 result
= mfree ( result
);
337 assert_se ( rm_rf ( temp
, REMOVE_ROOT
| REMOVE_PHYSICAL
) >= 0 );
340 static void test_unlink_noerrno ( void ) {
341 char name
[] = "/tmp/test-close_nointr.XXXXXX" ;
344 fd
= mkostemp_safe ( name
);
346 assert_se ( close_nointr ( fd
) >= 0 );
351 assert_se ( unlink_noerrno ( name
) >= 0 );
352 assert_se ( errno
== - 42 );
353 assert_se ( unlink_noerrno ( name
) < 0 );
354 assert_se ( errno
== - 42 );
358 static void test_readlink_and_make_absolute ( void ) {
359 char tempdir
[] = "/tmp/test-readlink_and_make_absolute" ;
360 char name
[] = "/tmp/test-readlink_and_make_absolute/original" ;
361 char name2
[] = "test-readlink_and_make_absolute/original" ;
362 char name_alias
[] = "/tmp/test-readlink_and_make_absolute-alias" ;
364 _cleanup_free_
char * pwd
= NULL
;
366 assert_se ( mkdir_safe ( tempdir
, 0755 , getuid (), getgid (), MKDIR_WARN_MODE
) >= 0 );
367 assert_se ( touch ( name
) >= 0 );
369 assert_se ( symlink ( name
, name_alias
) >= 0 );
370 assert_se ( readlink_and_make_absolute ( name_alias
, & r
) >= 0 );
371 assert_se ( streq ( r
, name
));
373 assert_se ( unlink ( name_alias
) >= 0 );
375 assert_se ( safe_getcwd (& pwd
) >= 0 );
377 assert_se ( chdir ( tempdir
) >= 0 );
378 assert_se ( symlink ( name2
, name_alias
) >= 0 );
379 assert_se ( readlink_and_make_absolute ( name_alias
, & r
) >= 0 );
380 assert_se ( streq ( r
, name
));
382 assert_se ( unlink ( name_alias
) >= 0 );
384 assert_se ( chdir ( pwd
) >= 0 );
386 assert_se ( rm_rf ( tempdir
, REMOVE_ROOT
| REMOVE_PHYSICAL
) >= 0 );
389 static void test_get_files_in_directory ( void ) {
390 _cleanup_strv_free_
char ** l
= NULL
, ** t
= NULL
;
392 assert_se ( get_files_in_directory ( "/tmp" , & l
) >= 0 );
393 assert_se ( get_files_in_directory ( "." , & t
) >= 0 );
394 assert_se ( get_files_in_directory ( "." , NULL
) >= 0 );
397 static void test_var_tmp ( void ) {
398 _cleanup_free_
char * tmpdir_backup
= NULL
, * temp_backup
= NULL
, * tmp_backup
= NULL
;
399 const char * tmp_dir
= NULL
, * t
;
401 t
= getenv ( "TMPDIR" );
403 tmpdir_backup
= strdup ( t
);
404 assert_se ( tmpdir_backup
);
409 temp_backup
= strdup ( t
);
410 assert_se ( temp_backup
);
415 tmp_backup
= strdup ( t
);
416 assert_se ( tmp_backup
);
419 assert_se ( unsetenv ( "TMPDIR" ) >= 0 );
420 assert_se ( unsetenv ( "TEMP" ) >= 0 );
421 assert_se ( unsetenv ( "TMP" ) >= 0 );
423 assert_se ( var_tmp_dir (& tmp_dir
) >= 0 );
424 assert_se ( streq ( tmp_dir
, "/var/tmp" ));
426 assert_se ( setenv ( "TMPDIR" , "/tmp" , true ) >= 0 );
427 assert_se ( streq ( getenv ( "TMPDIR" ), "/tmp" ));
429 assert_se ( var_tmp_dir (& tmp_dir
) >= 0 );
430 assert_se ( streq ( tmp_dir
, "/tmp" ));
432 assert_se ( setenv ( "TMPDIR" , "/88_does_not_exist_88" , true ) >= 0 );
433 assert_se ( streq ( getenv ( "TMPDIR" ), "/88_does_not_exist_88" ));
435 assert_se ( var_tmp_dir (& tmp_dir
) >= 0 );
436 assert_se ( streq ( tmp_dir
, "/var/tmp" ));
439 assert_se ( setenv ( "TMPDIR" , tmpdir_backup
, true ) >= 0 );
440 assert_se ( streq ( getenv ( "TMPDIR" ), tmpdir_backup
));
444 assert_se ( setenv ( "TEMP" , temp_backup
, true ) >= 0 );
445 assert_se ( streq ( getenv ( "TEMP" ), temp_backup
));
449 assert_se ( setenv ( "TMP" , tmp_backup
, true ) >= 0 );
450 assert_se ( streq ( getenv ( "TMP" ), tmp_backup
));
454 static void test_dot_or_dot_dot ( void ) {
455 assert_se (! dot_or_dot_dot ( NULL
));
456 assert_se (! dot_or_dot_dot ( "" ));
457 assert_se (! dot_or_dot_dot ( "xxx" ));
458 assert_se ( dot_or_dot_dot ( "." ));
459 assert_se ( dot_or_dot_dot ( ".." ));
460 assert_se (! dot_or_dot_dot ( ".foo" ));
461 assert_se (! dot_or_dot_dot ( "..foo" ));
464 static void test_access_fd ( void ) {
465 _cleanup_ ( rmdir_and_freep
) char * p
= NULL
;
466 _cleanup_close_
int fd
= - 1 ;
468 assert_se ( mkdtemp_malloc ( "/tmp/access-fd.XXXXXX" , & p
) >= 0 );
470 fd
= open ( p
, O_RDONLY
| O_DIRECTORY
| O_CLOEXEC
);
473 assert_se ( access_fd ( fd
, R_OK
) >= 0 );
474 assert_se ( access_fd ( fd
, F_OK
) >= 0 );
475 assert_se ( access_fd ( fd
, W_OK
) >= 0 );
477 assert_se ( fchmod ( fd
, 0000 ) >= 0 );
479 assert_se ( access_fd ( fd
, F_OK
) >= 0 );
481 if ( geteuid () == 0 ) {
482 assert_se ( access_fd ( fd
, R_OK
) >= 0 );
483 assert_se ( access_fd ( fd
, W_OK
) >= 0 );
485 assert_se ( access_fd ( fd
, R_OK
) == - EACCES
);
486 assert_se ( access_fd ( fd
, W_OK
) == - EACCES
);
490 static void test_touch_file ( void ) {
491 uid_t test_uid
, test_gid
;
492 _cleanup_ ( rm_rf_physical_and_freep
) char * p
= NULL
;
497 test_uid
= geteuid () == 0 ? 65534 : getuid ();
498 test_gid
= geteuid () == 0 ? 65534 : getgid ();
500 test_mtime
= usec_sub_unsigned ( now ( CLOCK_REALTIME
), USEC_PER_WEEK
);
502 assert_se ( mkdtemp_malloc ( "/dev/shm/touch-file-XXXXXX" , & p
) >= 0 );
504 a
= strjoina ( p
, "/regular" );
505 assert_se ( touch_file ( a
, false , test_mtime
, test_uid
, test_gid
, 0640 ) >= 0 );
506 assert_se ( lstat ( a
, & st
) >= 0 );
507 assert_se ( st
. st_uid
== test_uid
);
508 assert_se ( st
. st_gid
== test_gid
);
509 assert_se ( S_ISREG ( st
. st_mode
));
510 assert_se (( st
. st_mode
& 0777 ) == 0640 );
511 assert_se ( timespec_load (& st
. st_mtim
) == test_mtime
);
513 a
= strjoina ( p
, "/dir" );
514 assert_se ( mkdir ( a
, 0775 ) >= 0 );
515 assert_se ( touch_file ( a
, false , test_mtime
, test_uid
, test_gid
, 0640 ) >= 0 );
516 assert_se ( lstat ( a
, & st
) >= 0 );
517 assert_se ( st
. st_uid
== test_uid
);
518 assert_se ( st
. st_gid
== test_gid
);
519 assert_se ( S_ISDIR ( st
. st_mode
));
520 assert_se (( st
. st_mode
& 0777 ) == 0640 );
521 assert_se ( timespec_load (& st
. st_mtim
) == test_mtime
);
523 a
= strjoina ( p
, "/fifo" );
524 assert_se ( mkfifo ( a
, 0775 ) >= 0 );
525 assert_se ( touch_file ( a
, false , test_mtime
, test_uid
, test_gid
, 0640 ) >= 0 );
526 assert_se ( lstat ( a
, & st
) >= 0 );
527 assert_se ( st
. st_uid
== test_uid
);
528 assert_se ( st
. st_gid
== test_gid
);
529 assert_se ( S_ISFIFO ( st
. st_mode
));
530 assert_se (( st
. st_mode
& 0777 ) == 0640 );
531 assert_se ( timespec_load (& st
. st_mtim
) == test_mtime
);
533 a
= strjoina ( p
, "/sock" );
534 assert_se ( mknod ( a
, 0775 | S_IFSOCK
, 0 ) >= 0 );
535 assert_se ( touch_file ( a
, false , test_mtime
, test_uid
, test_gid
, 0640 ) >= 0 );
536 assert_se ( lstat ( a
, & st
) >= 0 );
537 assert_se ( st
. st_uid
== test_uid
);
538 assert_se ( st
. st_gid
== test_gid
);
539 assert_se ( S_ISSOCK ( st
. st_mode
));
540 assert_se (( st
. st_mode
& 0777 ) == 0640 );
541 assert_se ( timespec_load (& st
. st_mtim
) == test_mtime
);
543 if ( geteuid () == 0 ) {
544 a
= strjoina ( p
, "/cdev" );
545 assert_se ( mknod ( a
, 0775 | S_IFCHR
, makedev ( 0 , 0 )) >= 0 );
546 assert_se ( touch_file ( a
, false , test_mtime
, test_uid
, test_gid
, 0640 ) >= 0 );
547 assert_se ( lstat ( a
, & st
) >= 0 );
548 assert_se ( st
. st_uid
== test_uid
);
549 assert_se ( st
. st_gid
== test_gid
);
550 assert_se ( S_ISCHR ( st
. st_mode
));
551 assert_se (( st
. st_mode
& 0777 ) == 0640 );
552 assert_se ( timespec_load (& st
. st_mtim
) == test_mtime
);
554 a
= strjoina ( p
, "/bdev" );
555 assert_se ( mknod ( a
, 0775 | S_IFBLK
, makedev ( 0 , 0 )) >= 0 );
556 assert_se ( touch_file ( a
, false , test_mtime
, test_uid
, test_gid
, 0640 ) >= 0 );
557 assert_se ( lstat ( a
, & st
) >= 0 );
558 assert_se ( st
. st_uid
== test_uid
);
559 assert_se ( st
. st_gid
== test_gid
);
560 assert_se ( S_ISBLK ( st
. st_mode
));
561 assert_se (( st
. st_mode
& 0777 ) == 0640 );
562 assert_se ( timespec_load (& st
. st_mtim
) == test_mtime
);
565 a
= strjoina ( p
, "/lnk" );
566 assert_se ( symlink ( "target" , a
) >= 0 );
567 assert_se ( touch_file ( a
, false , test_mtime
, test_uid
, test_gid
, 0640 ) >= 0 );
568 assert_se ( lstat ( a
, & st
) >= 0 );
569 assert_se ( st
. st_uid
== test_uid
);
570 assert_se ( st
. st_gid
== test_gid
);
571 assert_se ( S_ISLNK ( st
. st_mode
));
572 assert_se (( st
. st_mode
& 0777 ) == 0640 );
573 assert_se ( timespec_load (& st
. st_mtim
) == test_mtime
);
576 static void test_unlinkat_deallocate ( void ) {
577 _cleanup_free_
char * p
= NULL
;
578 _cleanup_close_
int fd
= - 1 ;
581 assert_se ( tempfn_random_child ( NULL
, "unlink-deallocation" , & p
) >= 0 );
583 fd
= open ( p
, O_WRONLY
| O_CLOEXEC
| O_CREAT
| O_EXCL
, 0600 );
586 assert_se ( write ( fd
, "hallo \n " , 6 ) == 6 );
588 assert_se ( fstat ( fd
, & st
) >= 0 );
589 assert_se ( st
. st_size
== 6 );
590 assert_se ( st
. st_blocks
> 0 );
591 assert_se ( st
. st_nlink
== 1 );
593 assert_se ( unlinkat_deallocate ( AT_FDCWD
, p
, 0 ) >= 0 );
595 assert_se ( fstat ( fd
, & st
) >= 0 );
596 assert_se ( IN_SET ( st
. st_size
, 0 , 6 )); /* depending on whether hole punching worked the size will be 6 (it worked) or 0 (we had to resort to truncation) */
597 assert_se ( st
. st_blocks
== 0 );
598 assert_se ( st
. st_nlink
== 0 );
601 static void test_fsync_directory_of_file ( void ) {
602 _cleanup_close_
int fd
= - 1 ;
604 fd
= open_tmpfile_unlinkable ( NULL
, O_RDWR
);
607 assert_se ( fsync_directory_of_file ( fd
) >= 0 );
610 int main ( int argc
, char * argv
[]) {
611 test_unlink_noerrno ();
612 test_get_files_in_directory ();
613 test_readlink_and_make_absolute ();
615 test_chase_symlinks ();
616 test_dot_or_dot_dot ();
619 test_unlinkat_deallocate ();
620 test_fsync_directory_of_file ();