2020-11-09 13:23:58 +09:00
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2013-03-28 22:03:53 -04:00
2013-03-29 20:26:47 -04:00
# include <stdio.h>
2015-10-24 22:58:24 +02:00
# include <unistd.h>
2013-03-29 20:26:47 -04:00
2015-10-27 03:01:06 +01:00
# include "alloc-util.h"
2020-09-18 14:28:08 +02:00
# include "exec-util.h"
2015-10-25 13:14:12 +01:00
# include "fd-util.h"
2021-07-08 17:10:47 -07:00
# include "fs-util.h"
2013-03-28 22:03:53 -04:00
# include "macro.h"
2015-10-24 22:58:24 +02:00
# include "path-util.h"
2020-09-17 15:02:47 +02:00
# include "process-util.h"
2015-04-04 11:52:57 +02:00
# include "rm-rf.h"
2017-04-25 23:50:35 -04:00
# include "stat-util.h"
2015-10-24 22:58:24 +02:00
# include "string-util.h"
# include "strv.h"
2018-09-13 14:31:13 +02:00
# include "tests.h"
2021-07-08 17:10:47 -07:00
# include "tmpfile-util.h"
2013-03-28 22:03:53 -04:00
2021-11-24 12:00:02 +01:00
TEST ( print_paths ) {
2019-11-12 15:38:19 +01:00
log_info ( " DEFAULT_PATH=%s " , DEFAULT_PATH ) ;
log_info ( " DEFAULT_USER_PATH=%s " , DEFAULT_USER_PATH ) ;
}
2021-11-24 12:00:02 +01:00
TEST ( path ) {
2013-03-28 22:03:53 -04:00
assert_se ( path_is_absolute ( " / " ) ) ;
assert_se ( ! path_is_absolute ( " ./ " ) ) ;
assert_se ( is_path ( " /dir " ) ) ;
assert_se ( is_path ( " a/b " ) ) ;
assert_se ( ! is_path ( " . " ) ) ;
2013-12-06 21:29:55 -05:00
assert_se ( streq ( basename ( " ./aa/bb/../file.da. " ) , " file.da. " ) ) ;
assert_se ( streq ( basename ( " /aa///.file " ) , " .file " ) ) ;
assert_se ( streq ( basename ( " /aa///file... " ) , " file... " ) ) ;
assert_se ( streq ( basename ( " file.../ " ) , " " ) ) ;
2013-03-28 22:03:53 -04:00
2016-04-16 22:52:06 -04:00
assert_se ( PATH_IN_SET ( " /bin " , " / " , " /bin " , " /foo " ) ) ;
assert_se ( PATH_IN_SET ( " /bin " , " /bin " ) ) ;
assert_se ( PATH_IN_SET ( " /bin " , " /foo/bar " , " /bin " ) ) ;
assert_se ( PATH_IN_SET ( " / " , " / " , " / " , " /foo/bar " ) ) ;
assert_se ( ! PATH_IN_SET ( " / " , " /abc " , " /def " ) ) ;
2016-04-16 23:08:23 -04:00
assert_se ( path_equal_ptr ( NULL , NULL ) ) ;
assert_se ( path_equal_ptr ( " /a " , " /a " ) ) ;
assert_se ( ! path_equal_ptr ( " /a " , " /b " ) ) ;
assert_se ( ! path_equal_ptr ( " /a " , NULL ) ) ;
assert_se ( ! path_equal_ptr ( NULL , " /a " ) ) ;
2021-04-07 10:45:33 +01:00
assert_se ( path_equal_filename ( " /a/c " , " /b/c " ) ) ;
assert_se ( path_equal_filename ( " /a " , " /a " ) ) ;
assert_se ( ! path_equal_filename ( " /a/b " , " /a/c " ) ) ;
assert_se ( ! path_equal_filename ( " /b " , " /c " ) ) ;
2013-03-28 22:03:53 -04:00
}
2021-05-04 16:00:41 +09:00
static void test_path_simplify_one ( const char * in , const char * out ) {
char * p ;
2021-10-13 12:38:37 +02:00
p = strdupa_safe ( in ) ;
2021-05-04 16:00:41 +09:00
path_simplify ( p ) ;
log_debug ( " /* test_path_simplify(%s) → %s (expected: %s) */ " , in , p , out ) ;
assert_se ( streq ( p , out ) ) ;
}
2021-11-24 12:00:02 +01:00
TEST ( path_simplify ) {
2021-05-04 16:00:41 +09:00
_cleanup_free_ char * hoge = NULL , * hoge_out = NULL ;
char foo [ NAME_MAX * 2 ] ;
test_path_simplify_one ( " " , " " ) ;
test_path_simplify_one ( " aaa/bbb////ccc " , " aaa/bbb/ccc " ) ;
test_path_simplify_one ( " //aaa/.////ccc " , " /aaa/ccc " ) ;
test_path_simplify_one ( " /// " , " / " ) ;
test_path_simplify_one ( " ///.// " , " / " ) ;
test_path_simplify_one ( " ///.//./// " , " / " ) ;
test_path_simplify_one ( " ////.././///../. " , " /../.. " ) ;
test_path_simplify_one ( " . " , " . " ) ;
test_path_simplify_one ( " ./ " , " . " ) ;
test_path_simplify_one ( " .///.//./. " , " . " ) ;
test_path_simplify_one ( " .///.//./.// " , " . " ) ;
test_path_simplify_one ( " //./aaa///.//./.bbb/..///c.//d.dd///..eeee/. " ,
" /aaa/.bbb/../c./d.dd/..eeee " ) ;
test_path_simplify_one ( " //./aaa///.//./.bbb/..///c.//d.dd///..eeee/.. " ,
" /aaa/.bbb/../c./d.dd/..eeee/.. " ) ;
test_path_simplify_one ( " .//./aaa///.//./.bbb/..///c.//d.dd///..eeee/.. " ,
" aaa/.bbb/../c./d.dd/..eeee/.. " ) ;
test_path_simplify_one ( " ..//./aaa///.//./.bbb/..///c.//d.dd///..eeee/.. " ,
" ../aaa/.bbb/../c./d.dd/..eeee/.. " ) ;
memset ( foo , ' a ' , sizeof ( foo ) - 1 ) ;
char_array_0 ( foo ) ;
test_path_simplify_one ( foo , foo ) ;
hoge = strjoin ( " / " , foo ) ;
assert_se ( hoge ) ;
test_path_simplify_one ( hoge , hoge ) ;
hoge = mfree ( hoge ) ;
hoge = strjoin ( " a////.//././//./b///././/./c/////././//./ " , foo , " //.//////d/e/.//f/ " ) ;
assert_se ( hoge ) ;
hoge_out = strjoin ( " a/b/c/ " , foo , " //.//////d/e/.//f/ " ) ;
assert_se ( hoge_out ) ;
test_path_simplify_one ( hoge , hoge_out ) ;
}
2021-05-02 06:39:55 +09:00
static void test_path_compare_one ( const char * a , const char * b , int expected ) {
int r ;
assert_se ( path_compare ( a , a ) = = 0 ) ;
assert_se ( path_compare ( b , b ) = = 0 ) ;
r = path_compare ( a , b ) ;
assert_se ( ( r > 0 ) = = ( expected > 0 ) & & ( r < 0 ) = = ( expected < 0 ) ) ;
r = path_compare ( b , a ) ;
assert_se ( ( r < 0 ) = = ( expected > 0 ) & & ( r > 0 ) = = ( expected < 0 ) ) ;
assert_se ( path_equal ( a , a ) = = 1 ) ;
assert_se ( path_equal ( b , b ) = = 1 ) ;
assert_se ( path_equal ( a , b ) = = ( expected = = 0 ) ) ;
assert_se ( path_equal ( b , a ) = = ( expected = = 0 ) ) ;
}
2021-11-24 12:00:02 +01:00
TEST ( path_compare ) {
2021-05-02 06:39:55 +09:00
test_path_compare_one ( " /goo " , " /goo " , 0 ) ;
test_path_compare_one ( " /goo " , " /goo " , 0 ) ;
test_path_compare_one ( " //goo " , " /goo " , 0 ) ;
test_path_compare_one ( " //goo///// " , " /goo " , 0 ) ;
test_path_compare_one ( " goo///// " , " goo " , 0 ) ;
test_path_compare_one ( " /goo/boo " , " /goo//boo " , 0 ) ;
test_path_compare_one ( " //goo/boo " , " /goo/boo// " , 0 ) ;
test_path_compare_one ( " //goo/././//./boo//././// " , " /goo/boo//. " , 0 ) ;
test_path_compare_one ( " /. " , " //./// " , 0 ) ;
test_path_compare_one ( " /x " , " x/ " , 1 ) ;
test_path_compare_one ( " x/ " , " / " , - 1 ) ;
test_path_compare_one ( " /x/./y " , " x/y " , 1 ) ;
2021-06-23 16:05:47 +02:00
test_path_compare_one ( " /x/./y " , " /x/y " , 0 ) ;
test_path_compare_one ( " /x/./././y " , " /x/y/././. " , 0 ) ;
test_path_compare_one ( " ./x/./././y " , " ./x/y/././. " , 0 ) ;
test_path_compare_one ( " . " , " ./. " , 0 ) ;
test_path_compare_one ( " . " , " ././. " , 0 ) ;
test_path_compare_one ( " ./.. " , " . " , 1 ) ;
2021-05-02 06:39:55 +09:00
test_path_compare_one ( " x/.y " , " x/y " , - 1 ) ;
test_path_compare_one ( " foo " , " /foo " , - 1 ) ;
test_path_compare_one ( " /foo " , " /foo/bar " , - 1 ) ;
test_path_compare_one ( " /foo/aaa " , " /foo/b " , - 1 ) ;
test_path_compare_one ( " /foo/aaa " , " /foo/b/a " , - 1 ) ;
test_path_compare_one ( " /foo/a " , " /foo/aaa " , - 1 ) ;
test_path_compare_one ( " /foo/a/b " , " /foo/aaa " , - 1 ) ;
}
2021-11-24 12:00:02 +01:00
TEST ( path_equal_root ) {
2017-04-25 23:50:35 -04:00
/* Nail down the details of how path_equal("/", ...) works. */
assert_se ( path_equal ( " / " , " / " ) ) ;
assert_se ( path_equal ( " / " , " // " ) ) ;
2021-05-02 06:39:55 +09:00
assert_se ( path_equal ( " / " , " /./ " ) ) ;
2017-04-25 23:50:35 -04:00
assert_se ( ! path_equal ( " / " , " /../ " ) ) ;
assert_se ( ! path_equal ( " / " , " /.../ " ) ) ;
/* Make sure that files_same works as expected. */
2017-06-17 12:37:16 -04:00
assert_se ( files_same ( " / " , " / " , 0 ) > 0 ) ;
assert_se ( files_same ( " / " , " / " , AT_SYMLINK_NOFOLLOW ) > 0 ) ;
assert_se ( files_same ( " / " , " // " , 0 ) > 0 ) ;
assert_se ( files_same ( " / " , " // " , AT_SYMLINK_NOFOLLOW ) > 0 ) ;
2017-04-25 23:50:35 -04:00
2017-06-17 12:37:16 -04:00
assert_se ( files_same ( " / " , " /./ " , 0 ) > 0 ) ;
assert_se ( files_same ( " / " , " /./ " , AT_SYMLINK_NOFOLLOW ) > 0 ) ;
assert_se ( files_same ( " / " , " /../ " , 0 ) > 0 ) ;
assert_se ( files_same ( " / " , " /../ " , AT_SYMLINK_NOFOLLOW ) > 0 ) ;
2017-04-25 23:50:35 -04:00
2017-06-17 12:37:16 -04:00
assert_se ( files_same ( " / " , " /.../ " , 0 ) = = - ENOENT ) ;
assert_se ( files_same ( " / " , " /.../ " , AT_SYMLINK_NOFOLLOW ) = = - ENOENT ) ;
2017-04-25 23:50:35 -04:00
/* The same for path_equal_or_files_same. */
2017-06-17 12:37:16 -04:00
assert_se ( path_equal_or_files_same ( " / " , " / " , 0 ) ) ;
assert_se ( path_equal_or_files_same ( " / " , " / " , AT_SYMLINK_NOFOLLOW ) ) ;
assert_se ( path_equal_or_files_same ( " / " , " // " , 0 ) ) ;
assert_se ( path_equal_or_files_same ( " / " , " // " , AT_SYMLINK_NOFOLLOW ) ) ;
2017-04-25 23:50:35 -04:00
2017-06-17 12:37:16 -04:00
assert_se ( path_equal_or_files_same ( " / " , " /./ " , 0 ) ) ;
assert_se ( path_equal_or_files_same ( " / " , " /./ " , AT_SYMLINK_NOFOLLOW ) ) ;
assert_se ( path_equal_or_files_same ( " / " , " /../ " , 0 ) ) ;
assert_se ( path_equal_or_files_same ( " / " , " /../ " , AT_SYMLINK_NOFOLLOW ) ) ;
2017-04-25 23:50:35 -04:00
2017-06-17 12:37:16 -04:00
assert_se ( ! path_equal_or_files_same ( " / " , " /.../ " , 0 ) ) ;
assert_se ( ! path_equal_or_files_same ( " / " , " /.../ " , AT_SYMLINK_NOFOLLOW ) ) ;
2017-04-25 23:50:35 -04:00
}
2021-11-24 12:00:02 +01:00
TEST ( find_executable_full ) {
2020-09-17 14:32:17 +02:00
char * p ;
2021-07-08 17:10:47 -07:00
char * test_file_name ;
2022-12-19 13:07:42 +01:00
_cleanup_close_ int fd = - EBADF ;
2021-07-08 17:10:47 -07:00
char fn [ ] = " /tmp/test-XXXXXX " ;
2020-09-17 14:32:17 +02:00
2021-07-08 17:10:47 -07:00
assert_se ( find_executable_full ( " sh " , NULL , NULL , true , & p , NULL ) = = 0 ) ;
2020-09-17 14:32:17 +02:00
puts ( p ) ;
assert_se ( streq ( basename ( p ) , " sh " ) ) ;
free ( p ) ;
2021-07-08 17:10:47 -07:00
assert_se ( find_executable_full ( " sh " , NULL , NULL , false , & p , NULL ) = = 0 ) ;
2020-09-17 14:32:17 +02:00
puts ( p ) ;
assert_se ( streq ( basename ( p ) , " sh " ) ) ;
free ( p ) ;
_cleanup_free_ char * oldpath = NULL ;
p = getenv ( " PATH " ) ;
if ( p )
assert_se ( oldpath = strdup ( p ) ) ;
2020-11-10 12:14:28 +01:00
assert_se ( unsetenv ( " PATH " ) = = 0 ) ;
2020-09-17 14:32:17 +02:00
2021-07-08 17:10:47 -07:00
assert_se ( find_executable_full ( " sh " , NULL , NULL , true , & p , NULL ) = = 0 ) ;
2020-09-17 14:32:17 +02:00
puts ( p ) ;
assert_se ( streq ( basename ( p ) , " sh " ) ) ;
free ( p ) ;
2021-07-08 17:10:47 -07:00
assert_se ( find_executable_full ( " sh " , NULL , NULL , false , & p , NULL ) = = 0 ) ;
2020-09-17 14:32:17 +02:00
puts ( p ) ;
assert_se ( streq ( basename ( p ) , " sh " ) ) ;
free ( p ) ;
if ( oldpath )
assert_se ( setenv ( " PATH " , oldpath , true ) > = 0 ) ;
2021-07-08 17:10:47 -07:00
assert_se ( ( fd = mkostemp_safe ( fn ) ) > = 0 ) ;
assert_se ( fchmod ( fd , 0755 ) > = 0 ) ;
test_file_name = basename ( fn ) ;
assert_se ( find_executable_full ( test_file_name , NULL , STRV_MAKE ( " /doesnotexist " , " /tmp " , " /bin " ) , false , & p , NULL ) = = 0 ) ;
puts ( p ) ;
assert_se ( streq ( p , fn ) ) ;
free ( p ) ;
( void ) unlink ( fn ) ;
assert_se ( find_executable_full ( test_file_name , NULL , STRV_MAKE ( " /doesnotexist " , " /tmp " , " /bin " ) , false , & p , NULL ) = = - ENOENT ) ;
2020-09-17 14:32:17 +02:00
}
2021-11-24 12:00:02 +01:00
TEST ( find_executable ) {
2013-09-08 07:51:39 -04:00
char * p ;
2020-09-17 13:44:12 +02:00
assert_se ( find_executable ( " /bin/sh " , & p ) = = 0 ) ;
2013-09-08 07:51:39 -04:00
puts ( p ) ;
2015-10-22 18:24:59 +02:00
assert_se ( path_equal ( p , " /bin/sh " ) ) ;
2013-09-08 07:51:39 -04:00
free ( p ) ;
2021-11-24 12:00:02 +01:00
assert_se ( find_executable ( saved_argv [ 0 ] , & p ) = = 0 ) ;
2013-09-08 07:51:39 -04:00
puts ( p ) ;
2020-09-17 14:32:17 +02:00
assert_se ( endswith ( p , " /test-path-util " ) ) ;
2014-08-25 22:05:03 -07:00
assert_se ( path_is_absolute ( p ) ) ;
2013-09-08 07:51:39 -04:00
free ( p ) ;
2020-09-17 13:44:12 +02:00
assert_se ( find_executable ( " sh " , & p ) = = 0 ) ;
2013-09-08 07:51:39 -04:00
puts ( p ) ;
2014-08-25 22:05:03 -07:00
assert_se ( endswith ( p , " /sh " ) ) ;
assert_se ( path_is_absolute ( p ) ) ;
2013-09-08 07:51:39 -04:00
free ( p ) ;
2020-09-17 14:32:17 +02:00
assert_se ( find_executable ( " /bin/touch " , & p ) = = 0 ) ;
assert_se ( streq ( p , " /bin/touch " ) ) ;
free ( p ) ;
assert_se ( find_executable ( " touch " , & p ) = = 0 ) ;
assert_se ( path_is_absolute ( p ) ) ;
assert_se ( streq ( basename ( p ) , " touch " ) ) ;
free ( p ) ;
2020-09-17 13:44:12 +02:00
assert_se ( find_executable ( " xxxx-xxxx " , & p ) = = - ENOENT ) ;
assert_se ( find_executable ( " /some/dir/xxxx-xxxx " , & p ) = = - ENOENT ) ;
2020-09-17 14:32:17 +02:00
assert_se ( find_executable ( " /proc/filesystems " , & p ) = = - EACCES ) ;
2013-09-08 07:51:39 -04:00
}
2020-09-17 15:02:47 +02:00
static void test_find_executable_exec_one ( const char * path ) {
_cleanup_free_ char * t = NULL ;
2022-12-19 13:07:42 +01:00
_cleanup_close_ int fd = - EBADF ;
2020-09-17 15:02:47 +02:00
pid_t pid ;
int r ;
2021-07-08 17:10:47 -07:00
r = find_executable_full ( path , NULL , NULL , false , & t , & fd ) ;
2020-09-17 15:02:47 +02:00
log_info_errno ( r , " %s: %s → %s: %d/%m " , __func__ , path , t ? : " - " , fd ) ;
assert_se ( fd > STDERR_FILENO ) ;
assert_se ( path_is_absolute ( t ) ) ;
if ( path_is_absolute ( path ) )
assert_se ( streq ( t , path ) ) ;
pid = fork ( ) ;
assert_se ( pid > = 0 ) ;
if ( pid = = 0 ) {
2020-09-18 14:28:08 +02:00
r = fexecve_or_execve ( fd , t , STRV_MAKE ( t , " --version " ) , STRV_MAKE ( NULL ) ) ;
log_error_errno ( r , " [f]execve: %m " ) ;
2020-09-17 15:02:47 +02:00
_exit ( EXIT_FAILURE ) ;
}
assert_se ( wait_for_terminate_and_check ( t , pid , WAIT_LOG ) = = 0 ) ;
}
2021-11-24 12:00:02 +01:00
TEST ( find_executable_exec ) {
2020-09-17 15:02:47 +02:00
test_find_executable_exec_one ( " touch " ) ;
test_find_executable_exec_one ( " /bin/touch " ) ;
2020-09-18 14:28:08 +02:00
_cleanup_free_ char * script = NULL ;
assert_se ( get_testdata_dir ( " test-path-util/script.sh " , & script ) > = 0 ) ;
test_find_executable_exec_one ( script ) ;
2020-09-17 15:02:47 +02:00
}
2021-11-24 12:00:02 +01:00
TEST ( prefixes ) {
2019-03-22 19:19:32 +01:00
static const char * const values [ ] = {
" /a/b/c/d " ,
" /a/b/c " ,
" /a/b " ,
" /a " ,
" " ,
NULL
} ;
2013-09-26 19:58:33 +02:00
unsigned i ;
2013-09-25 20:58:23 +02:00
char s [ PATH_MAX ] ;
2013-09-26 19:58:33 +02:00
bool b ;
2013-09-25 20:58:23 +02:00
2013-09-26 19:58:33 +02:00
i = 0 ;
PATH_FOREACH_PREFIX_MORE ( s , " /a/b/c/d " ) {
2013-09-25 20:58:23 +02:00
log_error ( " ---%s--- " , s ) ;
assert_se ( streq ( s , values [ i + + ] ) ) ;
}
2013-09-26 19:58:33 +02:00
assert_se ( values [ i ] = = NULL ) ;
2013-09-25 20:58:23 +02:00
2013-09-26 19:58:33 +02:00
i = 1 ;
PATH_FOREACH_PREFIX ( s , " /a/b/c/d " ) {
log_error ( " ---%s--- " , s ) ;
assert_se ( streq ( s , values [ i + + ] ) ) ;
}
2013-09-25 20:58:23 +02:00
assert_se ( values [ i ] = = NULL ) ;
i = 0 ;
2013-09-26 19:58:33 +02:00
PATH_FOREACH_PREFIX_MORE ( s , " ////a////b////c///d/////// " )
2013-09-25 20:58:23 +02:00
assert_se ( streq ( s , values [ i + + ] ) ) ;
2013-09-26 19:58:33 +02:00
assert_se ( values [ i ] = = NULL ) ;
2013-09-25 20:58:23 +02:00
2013-09-26 19:58:33 +02:00
i = 1 ;
PATH_FOREACH_PREFIX ( s , " ////a////b////c///d/////// " )
assert_se ( streq ( s , values [ i + + ] ) ) ;
2013-09-25 20:58:23 +02:00
assert_se ( values [ i ] = = NULL ) ;
PATH_FOREACH_PREFIX ( s , " //// " )
Drop the text argument from assert_not_reached()
In general we almost never hit those asserts in production code, so users see
them very rarely, if ever. But either way, we just need something that users
can pass to the developers.
We have quite a few of those asserts, and some have fairly nice messages, but
many are like "WTF?" or "???" or "unexpected something". The error that is
printed includes the file location, and function name. In almost all functions
there's at most one assert, so the function name alone is enough to identify
the failure for a developer. So we don't get much extra from the message, and
we might just as well drop them.
Dropping them makes our code a tiny bit smaller, and most importantly, improves
development experience by making it easy to insert such an assert in the code
without thinking how to phrase the argument.
2021-07-27 12:27:28 +02:00
assert_not_reached ( ) ;
2013-09-26 19:58:33 +02:00
b = false ;
PATH_FOREACH_PREFIX_MORE ( s , " //// " ) {
assert_se ( ! b ) ;
2013-09-25 20:58:23 +02:00
assert_se ( streq ( s , " " ) ) ;
2013-09-26 19:58:33 +02:00
b = true ;
}
assert_se ( b ) ;
2013-09-25 20:58:23 +02:00
PATH_FOREACH_PREFIX ( s , " " )
Drop the text argument from assert_not_reached()
In general we almost never hit those asserts in production code, so users see
them very rarely, if ever. But either way, we just need something that users
can pass to the developers.
We have quite a few of those asserts, and some have fairly nice messages, but
many are like "WTF?" or "???" or "unexpected something". The error that is
printed includes the file location, and function name. In almost all functions
there's at most one assert, so the function name alone is enough to identify
the failure for a developer. So we don't get much extra from the message, and
we might just as well drop them.
Dropping them makes our code a tiny bit smaller, and most importantly, improves
development experience by making it easy to insert such an assert in the code
without thinking how to phrase the argument.
2021-07-27 12:27:28 +02:00
assert_not_reached ( ) ;
2013-09-25 20:58:23 +02:00
2013-09-26 19:58:33 +02:00
b = false ;
PATH_FOREACH_PREFIX_MORE ( s , " " ) {
2014-08-25 22:05:03 -07:00
assert_se ( ! b ) ;
assert_se ( streq ( s , " " ) ) ;
2013-09-26 19:58:33 +02:00
b = true ;
}
2013-09-25 20:58:23 +02:00
}
2021-11-24 12:00:02 +01:00
TEST ( path_join ) {
2018-11-30 10:43:57 +01:00
# define test_join(expected, ...) { \
2014-09-30 22:18:18 +02:00
_cleanup_free_ char * z = NULL ; \
2018-11-30 10:43:57 +01:00
z = path_join ( __VA_ARGS__ ) ; \
log_debug ( " got \" %s \" , expected \" %s \" " , z , expected ) ; \
2014-09-30 22:18:18 +02:00
assert_se ( streq ( z , expected ) ) ; \
}
2018-11-30 10:43:57 +01:00
test_join ( " /root/a/b/c " , " /root " , " /a/b " , " /c " ) ;
test_join ( " /root/a/b/c " , " /root " , " a/b " , " c " ) ;
test_join ( " /root/a/b/c " , " /root " , " /a/b " , " c " ) ;
test_join ( " /root/c " , " /root " , " / " , " c " ) ;
test_join ( " /root/ " , " /root " , " / " , NULL ) ;
test_join ( " /a/b/c " , " " , " /a/b " , " /c " ) ;
test_join ( " a/b/c " , " " , " a/b " , " c " ) ;
test_join ( " /a/b/c " , " " , " /a/b " , " c " ) ;
test_join ( " /c " , " " , " / " , " c " ) ;
test_join ( " / " , " " , " / " , NULL ) ;
2018-11-30 11:06:24 +01:00
test_join ( " /a/b/c " , NULL , " /a/b " , " /c " ) ;
test_join ( " a/b/c " , NULL , " a/b " , " c " ) ;
test_join ( " /a/b/c " , NULL , " /a/b " , " c " ) ;
test_join ( " /c " , NULL , " / " , " c " ) ;
test_join ( " / " , NULL , " / " , NULL ) ;
2018-11-30 10:43:57 +01:00
test_join ( " " , " " , NULL ) ;
2018-11-30 11:06:24 +01:00
test_join ( " " , NULL , " " ) ;
test_join ( " " , NULL , NULL ) ;
2018-11-30 10:43:57 +01:00
test_join ( " foo/bar " , " foo " , " bar " ) ;
test_join ( " foo/bar " , " " , " foo " , " bar " ) ;
2018-11-30 11:06:24 +01:00
test_join ( " foo/bar " , NULL , " foo " , NULL , " bar " ) ;
2018-11-30 10:43:57 +01:00
test_join ( " foo/bar " , " " , " foo " , " " , " bar " , " " ) ;
test_join ( " foo/bar " , " " , " " , " " , " " , " foo " , " " , " " , " " , " bar " , " " , " " , " " ) ;
test_join ( " //foo///bar// " , " " , " / " , " " , " /foo/ " , " " , " / " , " " , " /bar/ " , " " , " / " , " " ) ;
test_join ( " /foo/bar/ " , " / " , " foo " , " / " , " bar " , " / " ) ;
test_join ( " foo/bar/baz " , " foo " , " bar " , " baz " ) ;
test_join ( " foo/bar/baz " , " foo/ " , " bar " , " /baz " ) ;
test_join ( " foo//bar//baz " , " foo/ " , " /bar/ " , " /baz " ) ;
test_join ( " //foo////bar////baz// " , " //foo/ " , " ///bar/ " , " ///baz// " ) ;
2014-07-26 14:47:31 -04:00
}
2021-11-24 12:00:02 +01:00
TEST ( path_extend ) {
2021-05-27 16:01:20 +02:00
_cleanup_free_ char * p = NULL ;
assert_se ( path_extend ( & p , " foo " , " bar " , " baz " ) = = p ) ;
assert_se ( streq ( p , " foo/bar/baz " ) ) ;
assert_se ( path_extend ( & p , " foo " , " bar " , " baz " ) = = p ) ;
assert_se ( streq ( p , " foo/bar/baz/foo/bar/baz " ) ) ;
p = mfree ( p ) ;
assert_se ( path_extend ( & p , " foo " ) = = p ) ;
assert_se ( streq ( p , " foo " ) ) ;
assert_se ( path_extend ( & p , " /foo " ) = = p ) ;
assert_se ( streq ( p , " foo/foo " ) ) ;
2021-05-28 13:38:31 +09:00
assert_se ( path_extend ( & p , " /waaaah/wahhh// " ) = = p ) ;
assert_se ( streq ( p , " foo/foo/waaaah/wahhh// " ) ) ; /* path_extend() does not drop redundant slashes */
assert_se ( path_extend ( & p , " /aaa/bbb/ " ) = = p ) ;
assert_se ( streq ( p , " foo/foo/waaaah/wahhh///aaa/bbb/ " ) ) ; /* but not add an extra slash */
assert_se ( free_and_strdup ( & p , " / " ) > = 0 ) ;
assert_se ( path_extend ( & p , " foo " ) = = p ) ;
assert_se ( streq ( p , " /foo " ) ) ;
2021-05-27 16:01:20 +02:00
}
2021-11-24 12:00:02 +01:00
TEST ( fsck_exists ) {
2014-04-12 16:07:45 -04:00
/* Ensure we use a sane default for PATH. */
2020-11-10 12:14:28 +01:00
assert_se ( unsetenv ( " PATH " ) = = 0 ) ;
2014-04-12 16:07:45 -04:00
/* fsck.minix is provided by util-linux and will probably exist. */
2022-09-29 18:51:03 +02:00
assert_se ( fsck_exists_for_fstype ( " minix " ) = = 1 ) ;
2014-04-12 16:07:45 -04:00
2022-09-29 18:51:03 +02:00
assert_se ( fsck_exists_for_fstype ( " AbCdE " ) = = 0 ) ;
assert_se ( fsck_exists_for_fstype ( " /../bin/ " ) = = 0 ) ;
2014-04-12 16:07:45 -04:00
}
2021-05-02 05:53:14 +09:00
static void test_path_make_relative_one ( const char * from , const char * to , const char * expected ) {
_cleanup_free_ char * z = NULL ;
int r ;
2014-05-24 12:01:13 +03:00
2021-05-02 05:53:14 +09:00
log_info ( " /* %s(%s, %s) */ " , __func__ , from , to ) ;
2019-03-28 17:59:26 +01:00
2021-05-02 05:53:14 +09:00
r = path_make_relative ( from , to , & z ) ;
assert_se ( ( r > = 0 ) = = ! ! expected ) ;
assert_se ( streq_ptr ( z , expected ) ) ;
}
2014-05-24 12:01:13 +03:00
2021-11-24 12:00:02 +01:00
TEST ( path_make_relative ) {
2021-05-02 05:53:14 +09:00
test_path_make_relative_one ( " some/relative/path " , " /some/path " , NULL ) ;
test_path_make_relative_one ( " /some/path " , " some/relative/path " , NULL ) ;
test_path_make_relative_one ( " /some/dotdot/../path " , " /some/path " , NULL ) ;
test_path_make_relative_one ( " / " , " / " , " . " ) ;
test_path_make_relative_one ( " / " , " /some/path " , " some/path " ) ;
test_path_make_relative_one ( " /some/path " , " /some/path " , " . " ) ;
test_path_make_relative_one ( " /some/path " , " /some/path/in/subdir " , " in/subdir " ) ;
test_path_make_relative_one ( " /some/path " , " / " , " ../.. " ) ;
test_path_make_relative_one ( " /some/path " , " /some/other/path " , " ../other/path " ) ;
test_path_make_relative_one ( " /some/path/./dot " , " /some/further/path " , " ../../further/path " ) ;
test_path_make_relative_one ( " //extra.//.//./.slashes//./won't////fo.ol///anybody// " , " /././/extra././/.slashes////ar.e/.just/././.fine/// " , " ../../../ar.e/.just/.fine " ) ;
2014-05-24 12:01:13 +03:00
}
2022-04-11 07:01:59 +09:00
static void test_path_make_relative_parent_one ( const char * from , const char * to , const char * expected ) {
_cleanup_free_ char * z = NULL ;
int r ;
log_info ( " /* %s(%s, %s) */ " , __func__ , from , to ) ;
r = path_make_relative_parent ( from , to , & z ) ;
assert_se ( ( r > = 0 ) = = ! ! expected ) ;
assert_se ( streq_ptr ( z , expected ) ) ;
}
TEST ( path_make_relative_parent ) {
test_path_make_relative_parent_one ( " some/relative/path/hoge " , " /some/path " , NULL ) ;
test_path_make_relative_parent_one ( " /some/path/hoge " , " some/relative/path " , NULL ) ;
test_path_make_relative_parent_one ( " /some/dotdot/../path/hoge " , " /some/path " , NULL ) ;
test_path_make_relative_parent_one ( " / " , " /aaa " , NULL ) ;
test_path_make_relative_parent_one ( " /hoge " , " / " , " . " ) ;
test_path_make_relative_parent_one ( " /hoge " , " /some/path " , " some/path " ) ;
test_path_make_relative_parent_one ( " /some/path/hoge " , " /some/path " , " . " ) ;
test_path_make_relative_parent_one ( " /some/path/hoge " , " /some/path/in/subdir " , " in/subdir " ) ;
test_path_make_relative_parent_one ( " /some/path/hoge " , " / " , " ../.. " ) ;
test_path_make_relative_parent_one ( " /some/path/hoge " , " /some/other/path " , " ../other/path " ) ;
test_path_make_relative_parent_one ( " /some/path/./dot/hoge " , " /some/further/path " , " ../../further/path " ) ;
test_path_make_relative_parent_one ( " //extra.//.//./.slashes//./won't////fo.ol///anybody//hoge " , " /././/extra././/.slashes////ar.e/.just/././.fine/// " , " ../../../ar.e/.just/.fine " ) ;
}
2021-11-24 12:00:02 +01:00
TEST ( path_strv_resolve ) {
2014-06-19 19:07:03 -07:00
char tmp_dir [ ] = " /tmp/test-path-util-XXXXXX " ;
_cleanup_strv_free_ char * * search_dirs = NULL ;
_cleanup_strv_free_ char * * absolute_dirs = NULL ;
assert_se ( mkdtemp ( tmp_dir ) ! = NULL ) ;
2018-10-31 17:03:50 +01:00
search_dirs = strv_new ( " /dir1 " , " /dir2 " , " /dir3 " ) ;
2014-06-19 19:07:03 -07:00
assert_se ( search_dirs ) ;
STRV_FOREACH ( d , search_dirs ) {
2019-07-11 19:14:16 +02:00
char * p = path_join ( tmp_dir , * d ) ;
2014-06-19 19:07:03 -07:00
assert_se ( p ) ;
assert_se ( strv_push ( & absolute_dirs , p ) = = 0 ) ;
}
assert_se ( mkdir ( absolute_dirs [ 0 ] , 0700 ) = = 0 ) ;
assert_se ( mkdir ( absolute_dirs [ 1 ] , 0700 ) = = 0 ) ;
assert_se ( symlink ( " dir2 " , absolute_dirs [ 2 ] ) = = 0 ) ;
path_strv_resolve ( search_dirs , tmp_dir ) ;
assert_se ( streq ( search_dirs [ 0 ] , " /dir1 " ) ) ;
assert_se ( streq ( search_dirs [ 1 ] , " /dir2 " ) ) ;
assert_se ( streq ( search_dirs [ 2 ] , " /dir2 " ) ) ;
2015-04-04 11:52:57 +02:00
assert_se ( rm_rf ( tmp_dir , REMOVE_ROOT | REMOVE_PHYSICAL ) = = 0 ) ;
2014-06-19 19:07:03 -07:00
}
2021-05-01 20:17:16 +09:00
static void test_path_startswith_one ( const char * path , const char * prefix , const char * skipped , const char * expected ) {
const char * p , * q ;
2016-10-30 10:21:29 -04:00
2021-05-01 20:17:16 +09:00
log_debug ( " /* %s(%s, %s) */ " , __func__ , path , prefix ) ;
2016-10-30 10:21:29 -04:00
2021-05-01 20:17:16 +09:00
p = path_startswith ( path , prefix ) ;
assert_se ( streq_ptr ( p , expected ) ) ;
if ( p ) {
q = strjoina ( skipped , p ) ;
assert_se ( streq ( q , path ) ) ;
assert_se ( p = = path + strlen ( skipped ) ) ;
}
}
2016-10-30 10:21:29 -04:00
2021-11-24 12:00:02 +01:00
TEST ( path_startswith ) {
2021-05-01 20:17:16 +09:00
test_path_startswith_one ( " /foo/bar/barfoo/ " , " /foo " , " /foo/ " , " bar/barfoo/ " ) ;
test_path_startswith_one ( " /foo/bar/barfoo/ " , " /foo/ " , " /foo/ " , " bar/barfoo/ " ) ;
test_path_startswith_one ( " /foo/bar/barfoo/ " , " / " , " / " , " foo/bar/barfoo/ " ) ;
test_path_startswith_one ( " /foo/bar/barfoo/ " , " //// " , " / " , " foo/bar/barfoo/ " ) ;
test_path_startswith_one ( " /foo/bar/barfoo/ " , " /foo//bar/////barfoo/// " , " /foo/bar/barfoo/ " , " " ) ;
test_path_startswith_one ( " /foo/bar/barfoo/ " , " /foo/bar/barfoo//// " , " /foo/bar/barfoo/ " , " " ) ;
test_path_startswith_one ( " /foo/bar/barfoo/ " , " /foo/bar///barfoo/ " , " /foo/bar/barfoo/ " , " " ) ;
test_path_startswith_one ( " /foo/bar/barfoo/ " , " /foo////bar/barfoo/ " , " /foo/bar/barfoo/ " , " " ) ;
test_path_startswith_one ( " /foo/bar/barfoo/ " , " ////foo/bar/barfoo/ " , " /foo/bar/barfoo/ " , " " ) ;
test_path_startswith_one ( " /foo/bar/barfoo/ " , " /foo/bar/barfoo " , " /foo/bar/barfoo/ " , " " ) ;
test_path_startswith_one ( " /foo/bar/barfoo/ " , " /foo/bar/barfooa/ " , NULL , NULL ) ;
test_path_startswith_one ( " /foo/bar/barfoo/ " , " /foo/bar/barfooa " , NULL , NULL ) ;
test_path_startswith_one ( " /foo/bar/barfoo/ " , " " , NULL , NULL ) ;
test_path_startswith_one ( " /foo/bar/barfoo/ " , " /bar/foo " , NULL , NULL ) ;
test_path_startswith_one ( " /foo/bar/barfoo/ " , " /f/b/b/ " , NULL , NULL ) ;
test_path_startswith_one ( " /foo/bar/barfoo/ " , " /foo/bar/barfo " , NULL , NULL ) ;
test_path_startswith_one ( " /foo/bar/barfoo/ " , " /foo/bar/bar " , NULL , NULL ) ;
test_path_startswith_one ( " /foo/bar/barfoo/ " , " /fo " , NULL , NULL ) ;
2014-10-22 00:58:24 +02:00
}
2015-05-13 17:42:10 +02:00
static void test_prefix_root_one ( const char * r , const char * p , const char * expected ) {
_cleanup_free_ char * s = NULL ;
const char * t ;
2019-06-19 15:20:13 +02:00
assert_se ( s = path_join ( r , p ) ) ;
assert_se ( path_equal_ptr ( s , expected ) ) ;
2015-05-13 17:42:10 +02:00
t = prefix_roota ( r , p ) ;
assert_se ( t ) ;
2019-06-19 15:20:13 +02:00
assert_se ( path_equal_ptr ( t , expected ) ) ;
2015-05-13 17:42:10 +02:00
}
2021-11-24 12:00:02 +01:00
TEST ( prefix_root ) {
2015-05-13 17:42:10 +02:00
test_prefix_root_one ( " / " , " /foo " , " /foo " ) ;
test_prefix_root_one ( NULL , " /foo " , " /foo " ) ;
test_prefix_root_one ( " " , " /foo " , " /foo " ) ;
test_prefix_root_one ( " /// " , " /foo " , " /foo " ) ;
test_prefix_root_one ( " / " , " ////foo " , " /foo " ) ;
test_prefix_root_one ( NULL , " ////foo " , " /foo " ) ;
2019-06-24 23:40:33 +09:00
test_prefix_root_one ( " / " , " foo " , " /foo " ) ;
test_prefix_root_one ( " " , " foo " , " foo " ) ;
test_prefix_root_one ( NULL , " foo " , " foo " ) ;
2015-05-13 17:42:10 +02:00
test_prefix_root_one ( " /foo " , " /bar " , " /foo/bar " ) ;
test_prefix_root_one ( " /foo " , " bar " , " /foo/bar " ) ;
test_prefix_root_one ( " foo " , " bar " , " foo/bar " ) ;
test_prefix_root_one ( " /foo/ " , " /bar " , " /foo/bar " ) ;
test_prefix_root_one ( " /foo/ " , " //bar " , " /foo/bar " ) ;
test_prefix_root_one ( " /foo/// " , " //bar " , " /foo/bar " ) ;
}
2021-11-24 12:00:02 +01:00
TEST ( file_in_same_dir ) {
2016-03-02 23:54:35 +01:00
char * t ;
2023-01-23 16:34:07 +01:00
assert_se ( file_in_same_dir ( " / " , " a " , & t ) = = - EADDRNOTAVAIL ) ;
2016-03-02 23:54:35 +01:00
2023-01-23 16:34:07 +01:00
assert_se ( file_in_same_dir ( " / " , " /a " , & t ) > = 0 ) ;
2016-03-02 23:54:35 +01:00
assert_se ( streq ( t , " /a " ) ) ;
free ( t ) ;
2023-01-23 16:34:07 +01:00
assert_se ( file_in_same_dir ( " " , " a " , & t ) = = - EINVAL ) ;
2016-03-02 23:54:35 +01:00
2023-01-23 16:34:07 +01:00
assert_se ( file_in_same_dir ( " a/ " , " x " , & t ) > = 0 ) ;
assert_se ( streq ( t , " x " ) ) ;
2016-03-02 23:54:35 +01:00
free ( t ) ;
2023-01-23 16:34:07 +01:00
assert_se ( file_in_same_dir ( " bar/foo " , " bar " , & t ) > = 0 ) ;
2016-03-02 23:54:35 +01:00
assert_se ( streq ( t , " bar/bar " ) ) ;
free ( t ) ;
}
2021-05-01 01:57:28 +09:00
static void test_path_find_first_component_one (
const char * path ,
bool accept_dot_dot ,
char * * expected ,
int ret ) {
log_debug ( " /* %s( \" %s \" , accept_dot_dot=%s) */ " , __func__ , strnull ( path ) , yes_no ( accept_dot_dot ) ) ;
for ( const char * p = path ; ; ) {
const char * e ;
int r ;
r = path_find_first_component ( & p , accept_dot_dot , & e ) ;
if ( r < = 0 ) {
if ( r = = 0 ) {
if ( path )
assert_se ( p = = path + strlen_ptr ( path ) ) ;
else
assert_se ( ! p ) ;
assert_se ( ! e ) ;
}
assert_se ( r = = ret ) ;
assert_se ( strv_isempty ( expected ) ) ;
return ;
}
assert_se ( e ) ;
assert_se ( strcspn ( e , " / " ) = = ( size_t ) r ) ;
assert_se ( strlen_ptr ( * expected ) = = ( size_t ) r ) ;
assert_se ( strneq ( e , * expected + + , r ) ) ;
}
}
2021-11-24 12:00:02 +01:00
TEST ( path_find_first_component ) {
2021-05-01 01:57:28 +09:00
_cleanup_free_ char * hoge = NULL ;
char foo [ NAME_MAX * 2 ] ;
test_path_find_first_component_one ( NULL , false , NULL , 0 ) ;
test_path_find_first_component_one ( " " , false , NULL , 0 ) ;
test_path_find_first_component_one ( " / " , false , NULL , 0 ) ;
test_path_find_first_component_one ( " . " , false , NULL , 0 ) ;
test_path_find_first_component_one ( " ./ " , false , NULL , 0 ) ;
test_path_find_first_component_one ( " ./. " , false , NULL , 0 ) ;
test_path_find_first_component_one ( " .. " , false , NULL , - EINVAL ) ;
test_path_find_first_component_one ( " /.. " , false , NULL , - EINVAL ) ;
test_path_find_first_component_one ( " ./.. " , false , NULL , - EINVAL ) ;
test_path_find_first_component_one ( " ////./././//. " , false , NULL , 0 ) ;
test_path_find_first_component_one ( " a/b/c " , false , STRV_MAKE ( " a " , " b " , " c " ) , 0 ) ;
test_path_find_first_component_one ( " ././//.///aa/bbb//./ccc " , false , STRV_MAKE ( " aa " , " bbb " , " ccc " ) , 0 ) ;
test_path_find_first_component_one ( " ././//.///aa/.../../bbb//./ccc/. " , false , STRV_MAKE ( " aa " , " ... " ) , - EINVAL ) ;
test_path_find_first_component_one ( " //./aaa///.//./.bbb/..///c.//d.dd///..eeee/. " , false , STRV_MAKE ( " aaa " , " .bbb " ) , - EINVAL ) ;
test_path_find_first_component_one ( " a/foo./b " , false , STRV_MAKE ( " a " , " foo. " , " b " ) , 0 ) ;
test_path_find_first_component_one ( NULL , true , NULL , 0 ) ;
test_path_find_first_component_one ( " " , true , NULL , 0 ) ;
test_path_find_first_component_one ( " / " , true , NULL , 0 ) ;
test_path_find_first_component_one ( " . " , true , NULL , 0 ) ;
test_path_find_first_component_one ( " ./ " , true , NULL , 0 ) ;
test_path_find_first_component_one ( " ./. " , true , NULL , 0 ) ;
test_path_find_first_component_one ( " .. " , true , STRV_MAKE ( " .. " ) , 0 ) ;
test_path_find_first_component_one ( " /.. " , true , STRV_MAKE ( " .. " ) , 0 ) ;
test_path_find_first_component_one ( " ./.. " , true , STRV_MAKE ( " .. " ) , 0 ) ;
test_path_find_first_component_one ( " ////./././//. " , true , NULL , 0 ) ;
test_path_find_first_component_one ( " a/b/c " , true , STRV_MAKE ( " a " , " b " , " c " ) , 0 ) ;
test_path_find_first_component_one ( " ././//.///aa/bbb//./ccc " , true , STRV_MAKE ( " aa " , " bbb " , " ccc " ) , 0 ) ;
test_path_find_first_component_one ( " ././//.///aa/.../../bbb//./ccc/. " , true , STRV_MAKE ( " aa " , " ... " , " .. " , " bbb " , " ccc " ) , 0 ) ;
test_path_find_first_component_one ( " //./aaa///.//./.bbb/..///c.//d.dd///..eeee/. " , true , STRV_MAKE ( " aaa " , " .bbb " , " .. " , " c. " , " d.dd " , " ..eeee " ) , 0 ) ;
test_path_find_first_component_one ( " a/foo./b " , true , STRV_MAKE ( " a " , " foo. " , " b " ) , 0 ) ;
memset ( foo , ' a ' , sizeof ( foo ) - 1 ) ;
char_array_0 ( foo ) ;
test_path_find_first_component_one ( foo , false , NULL , - EINVAL ) ;
test_path_find_first_component_one ( foo , true , NULL , - EINVAL ) ;
hoge = strjoin ( " a/b/c/ " , foo , " //d/e/.//f/ " ) ;
assert_se ( hoge ) ;
test_path_find_first_component_one ( hoge , false , STRV_MAKE ( " a " , " b " , " c " ) , - EINVAL ) ;
test_path_find_first_component_one ( hoge , true , STRV_MAKE ( " a " , " b " , " c " ) , - EINVAL ) ;
}
2021-05-03 23:47:57 +09:00
static void test_path_find_last_component_one (
const char * path ,
bool accept_dot_dot ,
char * * expected ,
int ret ) {
log_debug ( " /* %s( \" %s \" , accept_dot_dot=%s) */ " , __func__ , strnull ( path ) , yes_no ( accept_dot_dot ) ) ;
for ( const char * next = NULL ; ; ) {
const char * e ;
int r ;
r = path_find_last_component ( path , accept_dot_dot , & next , & e ) ;
if ( r < = 0 ) {
if ( r = = 0 ) {
assert_se ( next = = path ) ;
assert_se ( ! e ) ;
}
assert_se ( r = = ret ) ;
assert_se ( strv_isempty ( expected ) ) ;
return ;
}
assert_se ( e ) ;
assert_se ( strcspn ( e , " / " ) = = ( size_t ) r ) ;
assert_se ( strlen_ptr ( * expected ) = = ( size_t ) r ) ;
assert_se ( strneq ( e , * expected + + , r ) ) ;
}
}
2021-11-24 12:00:02 +01:00
TEST ( path_find_last_component ) {
2021-05-03 23:47:57 +09:00
_cleanup_free_ char * hoge = NULL ;
char foo [ NAME_MAX * 2 ] ;
test_path_find_last_component_one ( NULL , false , NULL , 0 ) ;
test_path_find_last_component_one ( " " , false , NULL , 0 ) ;
test_path_find_last_component_one ( " / " , false , NULL , 0 ) ;
test_path_find_last_component_one ( " . " , false , NULL , 0 ) ;
test_path_find_last_component_one ( " ./ " , false , NULL , 0 ) ;
test_path_find_last_component_one ( " ./. " , false , NULL , 0 ) ;
test_path_find_last_component_one ( " .. " , false , NULL , - EINVAL ) ;
test_path_find_last_component_one ( " /.. " , false , NULL , - EINVAL ) ;
test_path_find_last_component_one ( " ./.. " , false , NULL , - EINVAL ) ;
test_path_find_last_component_one ( " ////./././//. " , false , NULL , 0 ) ;
test_path_find_last_component_one ( " a/b/c " , false , STRV_MAKE ( " c " , " b " , " a " ) , 0 ) ;
test_path_find_last_component_one ( " ././//.///aa./.bbb//./ccc/./.// " , false , STRV_MAKE ( " ccc " , " .bbb " , " aa. " ) , 0 ) ;
test_path_find_last_component_one ( " ././//.///aa/../.../bbb//./ccc/. " , false , STRV_MAKE ( " ccc " , " bbb " , " ... " ) , - EINVAL ) ;
test_path_find_last_component_one ( " //./aaa///.//./.bbb/..///c.//d.dd///..eeee/. " , false , STRV_MAKE ( " ..eeee " , " d.dd " , " c. " ) , - EINVAL ) ;
test_path_find_last_component_one ( NULL , true , NULL , 0 ) ;
test_path_find_last_component_one ( " " , true , NULL , 0 ) ;
test_path_find_last_component_one ( " / " , true , NULL , 0 ) ;
test_path_find_last_component_one ( " . " , true , NULL , 0 ) ;
test_path_find_last_component_one ( " ./ " , true , NULL , 0 ) ;
test_path_find_last_component_one ( " ./. " , true , NULL , 0 ) ;
test_path_find_last_component_one ( " .. " , true , STRV_MAKE ( " .. " ) , 0 ) ;
test_path_find_last_component_one ( " /.. " , true , STRV_MAKE ( " .. " ) , 0 ) ;
test_path_find_last_component_one ( " ./.. " , true , STRV_MAKE ( " .. " ) , 0 ) ;
test_path_find_last_component_one ( " ////./././//. " , true , NULL , 0 ) ;
test_path_find_last_component_one ( " a/b/c " , true , STRV_MAKE ( " c " , " b " , " a " ) , 0 ) ;
test_path_find_last_component_one ( " ././//.///aa./.bbb//./ccc/./.// " , true , STRV_MAKE ( " ccc " , " .bbb " , " aa. " ) , 0 ) ;
test_path_find_last_component_one ( " ././//.///aa/../.../bbb//./ccc/. " , true , STRV_MAKE ( " ccc " , " bbb " , " ... " , " .. " , " aa " ) , 0 ) ;
test_path_find_last_component_one ( " //./aaa///.//./.bbb/..///c.//d.dd///..eeee/. " , true , STRV_MAKE ( " ..eeee " , " d.dd " , " c. " , " .. " , " .bbb " , " aaa " ) , 0 ) ;
memset ( foo , ' a ' , sizeof ( foo ) - 1 ) ;
char_array_0 ( foo ) ;
test_path_find_last_component_one ( foo , false , NULL , - EINVAL ) ;
test_path_find_last_component_one ( foo , true , NULL , - EINVAL ) ;
hoge = strjoin ( foo , " /a/b/c/ " ) ;
assert_se ( hoge ) ;
test_path_find_last_component_one ( hoge , false , STRV_MAKE ( " c " , " b " , " a " ) , - EINVAL ) ;
test_path_find_last_component_one ( hoge , true , STRV_MAKE ( " c " , " b " , " a " ) , - EINVAL ) ;
}
2021-11-24 12:00:02 +01:00
TEST ( last_path_component ) {
2018-10-26 16:06:54 +02:00
assert_se ( last_path_component ( NULL ) = = NULL ) ;
util-lib: use trailing slash in chase_symlinks, fd_is_mount_point, path_is_mount_point
The kernel will reply with -ENOTDIR when we try to access a non-directory under
a name which ends with a slash. But our functions would strip the trailing slash
under various circumstances. Keep the trailing slash, so that
path_is_mount_point("/path/to/file/") return -ENOTDIR when /path/to/file/ is a file.
Tests are added for this change in behaviour.
Also, when called with a trailing slash, path_is_mount_point() would get
"" from basename(), and call name_to_handle_at(3, "", ...), and always
return -ENOENT. Now it'll return -ENOTDIR if the mount point is a file, and
true if it is a directory and a mount point.
v2:
- use strip_trailing_chars()
v3:
- instead of stripping trailing chars(), do the opposite — preserve them.
2017-10-31 11:08:30 +01:00
assert_se ( streq ( last_path_component ( " a/b/c " ) , " c " ) ) ;
assert_se ( streq ( last_path_component ( " a/b/c/ " ) , " c/ " ) ) ;
assert_se ( streq ( last_path_component ( " / " ) , " / " ) ) ;
assert_se ( streq ( last_path_component ( " // " ) , " / " ) ) ;
assert_se ( streq ( last_path_component ( " /// " ) , " / " ) ) ;
assert_se ( streq ( last_path_component ( " . " ) , " . " ) ) ;
assert_se ( streq ( last_path_component ( " ./. " ) , " . " ) ) ;
assert_se ( streq ( last_path_component ( " ././ " ) , " ./ " ) ) ;
assert_se ( streq ( last_path_component ( " ./.// " ) , " .// " ) ) ;
assert_se ( streq ( last_path_component ( " /foo/a " ) , " a " ) ) ;
assert_se ( streq ( last_path_component ( " /foo/a/ " ) , " a/ " ) ) ;
2017-11-30 20:54:31 +01:00
assert_se ( streq ( last_path_component ( " " ) , " " ) ) ;
2018-04-05 18:00:39 +02:00
assert_se ( streq ( last_path_component ( " a " ) , " a " ) ) ;
assert_se ( streq ( last_path_component ( " a/ " ) , " a/ " ) ) ;
assert_se ( streq ( last_path_component ( " /a " ) , " a " ) ) ;
assert_se ( streq ( last_path_component ( " /a/ " ) , " a/ " ) ) ;
util-lib: use trailing slash in chase_symlinks, fd_is_mount_point, path_is_mount_point
The kernel will reply with -ENOTDIR when we try to access a non-directory under
a name which ends with a slash. But our functions would strip the trailing slash
under various circumstances. Keep the trailing slash, so that
path_is_mount_point("/path/to/file/") return -ENOTDIR when /path/to/file/ is a file.
Tests are added for this change in behaviour.
Also, when called with a trailing slash, path_is_mount_point() would get
"" from basename(), and call name_to_handle_at(3, "", ...), and always
return -ENOENT. Now it'll return -ENOTDIR if the mount point is a file, and
true if it is a directory and a mount point.
v2:
- use strip_trailing_chars()
v3:
- instead of stripping trailing chars(), do the opposite — preserve them.
2017-10-31 11:08:30 +01:00
}
2018-10-26 16:07:35 +02:00
static void test_path_extract_filename_one ( const char * input , const char * output , int ret ) {
_cleanup_free_ char * k = NULL ;
int r ;
r = path_extract_filename ( input , & k ) ;
2022-10-07 15:28:05 +02:00
log_info ( " %s → %s/%s [expected: %s/%s] " ,
strnull ( input ) ,
strnull ( k ) , r < 0 ? STRERROR ( r ) : " - " ,
strnull ( output ) , ret < 0 ? STRERROR ( ret ) : " - " ) ;
2018-10-26 16:07:35 +02:00
assert_se ( streq_ptr ( k , output ) ) ;
assert_se ( r = = ret ) ;
}
2021-11-24 12:00:02 +01:00
TEST ( path_extract_filename ) {
2018-10-26 16:07:35 +02:00
test_path_extract_filename_one ( NULL , NULL , - EINVAL ) ;
test_path_extract_filename_one ( " a/b/c " , " c " , 0 ) ;
2021-02-23 16:49:29 +01:00
test_path_extract_filename_one ( " a/b/c/ " , " c " , O_DIRECTORY ) ;
2021-01-25 19:50:47 +01:00
test_path_extract_filename_one ( " / " , NULL , - EADDRNOTAVAIL ) ;
test_path_extract_filename_one ( " // " , NULL , - EADDRNOTAVAIL ) ;
test_path_extract_filename_one ( " /// " , NULL , - EADDRNOTAVAIL ) ;
2021-05-04 14:40:56 +09:00
test_path_extract_filename_one ( " /. " , NULL , - EADDRNOTAVAIL ) ;
test_path_extract_filename_one ( " . " , NULL , - EADDRNOTAVAIL ) ;
test_path_extract_filename_one ( " ./ " , NULL , - EADDRNOTAVAIL ) ;
test_path_extract_filename_one ( " ./. " , NULL , - EADDRNOTAVAIL ) ;
test_path_extract_filename_one ( " ././ " , NULL , - EADDRNOTAVAIL ) ;
test_path_extract_filename_one ( " ./.// " , NULL , - EADDRNOTAVAIL ) ;
2018-10-26 16:07:35 +02:00
test_path_extract_filename_one ( " /foo/a " , " a " , 0 ) ;
2021-02-23 16:49:29 +01:00
test_path_extract_filename_one ( " /foo/a/ " , " a " , O_DIRECTORY ) ;
2018-10-26 16:07:35 +02:00
test_path_extract_filename_one ( " " , NULL , - EINVAL ) ;
test_path_extract_filename_one ( " a " , " a " , 0 ) ;
2021-02-23 16:49:29 +01:00
test_path_extract_filename_one ( " a/ " , " a " , O_DIRECTORY ) ;
2021-05-04 14:40:56 +09:00
test_path_extract_filename_one ( " a/././//. " , " a " , O_DIRECTORY ) ;
2018-10-26 16:07:35 +02:00
test_path_extract_filename_one ( " /a " , " a " , 0 ) ;
2021-02-23 16:49:29 +01:00
test_path_extract_filename_one ( " /a/ " , " a " , O_DIRECTORY ) ;
2021-05-04 14:40:56 +09:00
test_path_extract_filename_one ( " /a//./. " , " a " , O_DIRECTORY ) ;
2021-02-23 16:49:29 +01:00
test_path_extract_filename_one ( " /////////////a///////////// " , " a " , O_DIRECTORY ) ;
2021-05-04 14:40:56 +09:00
test_path_extract_filename_one ( " //./a/.///b./././.c//./d//. " , " d " , O_DIRECTORY ) ;
test_path_extract_filename_one ( " xx/. " , " xx " , O_DIRECTORY ) ;
2018-10-26 16:07:35 +02:00
test_path_extract_filename_one ( " xx/.. " , NULL , - EINVAL ) ;
test_path_extract_filename_one ( " .. " , NULL , - EINVAL ) ;
test_path_extract_filename_one ( " /.. " , NULL , - EINVAL ) ;
test_path_extract_filename_one ( " ../ " , NULL , - EINVAL ) ;
}
2021-01-26 12:28:23 +01:00
static void test_path_extract_directory_one ( const char * input , const char * output , int ret ) {
_cleanup_free_ char * k = NULL ;
int r ;
r = path_extract_directory ( input , & k ) ;
2022-10-07 15:28:05 +02:00
log_info ( " %s → %s/%s [expected: %s/%s] " ,
strnull ( input ) ,
strnull ( k ) , r < 0 ? STRERROR ( r ) : " - " ,
strnull ( output ) , STRERROR ( ret ) ) ;
2021-01-26 12:28:23 +01:00
assert_se ( streq_ptr ( k , output ) ) ;
assert_se ( r = = ret ) ;
/* Extra safety check: let's make sure that if we split out the filename too (and it works) the
* joined parts are identical to the original again */
if ( r > = 0 ) {
_cleanup_free_ char * f = NULL ;
r = path_extract_filename ( input , & f ) ;
if ( r > = 0 ) {
_cleanup_free_ char * j = NULL ;
assert_se ( j = path_join ( k , f ) ) ;
assert_se ( path_equal ( input , j ) ) ;
}
}
}
2021-11-24 12:00:02 +01:00
TEST ( path_extract_directory ) {
2021-01-26 12:28:23 +01:00
test_path_extract_directory_one ( NULL , NULL , - EINVAL ) ;
test_path_extract_directory_one ( " a/b/c " , " a/b " , 0 ) ;
test_path_extract_directory_one ( " a/b/c/ " , " a/b " , 0 ) ;
test_path_extract_directory_one ( " / " , NULL , - EADDRNOTAVAIL ) ;
test_path_extract_directory_one ( " // " , NULL , - EADDRNOTAVAIL ) ;
test_path_extract_directory_one ( " /// " , NULL , - EADDRNOTAVAIL ) ;
2021-05-04 14:40:56 +09:00
test_path_extract_directory_one ( " /. " , NULL , - EADDRNOTAVAIL ) ;
test_path_extract_directory_one ( " . " , NULL , - EADDRNOTAVAIL ) ;
test_path_extract_directory_one ( " ./ " , NULL , - EADDRNOTAVAIL ) ;
test_path_extract_directory_one ( " ./. " , NULL , - EADDRNOTAVAIL ) ;
test_path_extract_directory_one ( " ././ " , NULL , - EADDRNOTAVAIL ) ;
test_path_extract_directory_one ( " ./.// " , NULL , - EADDRNOTAVAIL ) ;
2021-01-26 12:28:23 +01:00
test_path_extract_directory_one ( " /foo/a " , " /foo " , 0 ) ;
test_path_extract_directory_one ( " /foo/a/ " , " /foo " , 0 ) ;
test_path_extract_directory_one ( " " , NULL , - EINVAL ) ;
test_path_extract_directory_one ( " a " , NULL , - EDESTADDRREQ ) ;
test_path_extract_directory_one ( " a/ " , NULL , - EDESTADDRREQ ) ;
2021-05-04 14:40:56 +09:00
test_path_extract_directory_one ( " a/././//. " , NULL , - EDESTADDRREQ ) ;
2021-01-26 12:28:23 +01:00
test_path_extract_directory_one ( " /a " , " / " , 0 ) ;
test_path_extract_directory_one ( " /a/ " , " / " , 0 ) ;
2021-05-04 14:40:56 +09:00
test_path_extract_directory_one ( " /a//./. " , " / " , 0 ) ;
2021-01-26 12:28:23 +01:00
test_path_extract_directory_one ( " /////////////a///////////// " , " / " , 0 ) ;
2021-05-04 14:40:56 +09:00
test_path_extract_directory_one ( " //./a/.///b./././.c//./d//. " , " /a/b./.c " , 0 ) ;
test_path_extract_directory_one ( " xx/. " , NULL , - EDESTADDRREQ ) ;
test_path_extract_directory_one ( " xx/.. " , NULL , - EINVAL ) ;
test_path_extract_directory_one ( " .. " , NULL , - EINVAL ) ;
test_path_extract_directory_one ( " /.. " , NULL , - EINVAL ) ;
test_path_extract_directory_one ( " ../ " , NULL , - EINVAL ) ;
2021-01-26 12:28:23 +01:00
}
2021-11-24 12:00:02 +01:00
TEST ( filename_is_valid ) {
2021-01-25 19:41:59 +01:00
char foo [ NAME_MAX + 2 ] ;
2016-03-02 23:54:35 +01:00
assert_se ( ! filename_is_valid ( " " ) ) ;
assert_se ( ! filename_is_valid ( " /bar/foo " ) ) ;
assert_se ( ! filename_is_valid ( " / " ) ) ;
assert_se ( ! filename_is_valid ( " . " ) ) ;
assert_se ( ! filename_is_valid ( " .. " ) ) ;
2020-09-15 22:49:52 +02:00
assert_se ( ! filename_is_valid ( " bar/foo " ) ) ;
assert_se ( ! filename_is_valid ( " bar/foo/ " ) ) ;
assert_se ( ! filename_is_valid ( " bar// " ) ) ;
2016-03-02 23:54:35 +01:00
2021-01-25 19:41:59 +01:00
memset ( foo , ' a ' , sizeof ( foo ) - 1 ) ;
char_array_0 ( foo ) ;
2016-03-02 23:54:35 +01:00
assert_se ( ! filename_is_valid ( foo ) ) ;
assert_se ( filename_is_valid ( " foo_bar-333 " ) ) ;
assert_se ( filename_is_valid ( " o.o " ) ) ;
}
2021-05-01 02:37:31 +09:00
static void test_path_is_valid_and_safe_one ( const char * p , bool ret ) {
2021-06-15 14:09:29 +09:00
log_debug ( " /* %s( \" %s \" ) */ " , __func__ , strnull ( p ) ) ;
2021-05-01 02:37:31 +09:00
assert_se ( path_is_valid ( p ) = = ret ) ;
if ( ret )
ret = ! streq ( p , " .. " ) & &
! startswith ( p , " ../ " ) & &
! endswith ( p , " /.. " ) & &
! strstr ( p , " /../ " ) ;
assert_se ( path_is_safe ( p ) = = ret ) ;
}
2021-11-24 12:00:02 +01:00
TEST ( path_is_valid_and_safe ) {
2021-01-25 19:41:59 +01:00
char foo [ PATH_MAX + 2 ] ;
const char * c ;
2021-05-01 02:37:31 +09:00
test_path_is_valid_and_safe_one ( " " , false ) ;
test_path_is_valid_and_safe_one ( " /bar/foo " , true ) ;
test_path_is_valid_and_safe_one ( " /bar/foo/ " , true ) ;
test_path_is_valid_and_safe_one ( " /bar/foo/ " , true ) ;
test_path_is_valid_and_safe_one ( " //bar//foo// " , true ) ;
test_path_is_valid_and_safe_one ( " / " , true ) ;
test_path_is_valid_and_safe_one ( " ///// " , true ) ;
test_path_is_valid_and_safe_one ( " /////.///.////...///..//. " , true ) ;
test_path_is_valid_and_safe_one ( " . " , true ) ;
test_path_is_valid_and_safe_one ( " .. " , true ) ;
test_path_is_valid_and_safe_one ( " bar/foo " , true ) ;
test_path_is_valid_and_safe_one ( " bar/foo/ " , true ) ;
test_path_is_valid_and_safe_one ( " bar// " , true ) ;
2021-01-25 19:41:59 +01:00
memset ( foo , ' a ' , sizeof ( foo ) - 1 ) ;
char_array_0 ( foo ) ;
2021-05-01 02:37:31 +09:00
test_path_is_valid_and_safe_one ( foo , false ) ;
2021-01-25 19:41:59 +01:00
c = strjoina ( " /xxx/ " , foo , " /yyy " ) ;
2021-05-01 02:37:31 +09:00
test_path_is_valid_and_safe_one ( c , false ) ;
2021-01-25 19:41:59 +01:00
2021-05-01 02:37:31 +09:00
test_path_is_valid_and_safe_one ( " foo_bar-333 " , true ) ;
test_path_is_valid_and_safe_one ( " o.o " , true ) ;
2021-01-25 19:41:59 +01:00
}
2021-11-24 12:00:02 +01:00
TEST ( hidden_or_backup_file ) {
2016-04-28 08:24:25 -04:00
assert_se ( hidden_or_backup_file ( " .hidden " ) ) ;
assert_se ( hidden_or_backup_file ( " ..hidden " ) ) ;
assert_se ( ! hidden_or_backup_file ( " hidden. " ) ) ;
assert_se ( hidden_or_backup_file ( " backup~ " ) ) ;
assert_se ( hidden_or_backup_file ( " .backup~ " ) ) ;
assert_se ( hidden_or_backup_file ( " lost+found " ) ) ;
assert_se ( hidden_or_backup_file ( " aquota.user " ) ) ;
assert_se ( hidden_or_backup_file ( " aquota.group " ) ) ;
assert_se ( hidden_or_backup_file ( " test.rpmnew " ) ) ;
assert_se ( hidden_or_backup_file ( " test.dpkg-old " ) ) ;
assert_se ( hidden_or_backup_file ( " test.dpkg-remove " ) ) ;
assert_se ( hidden_or_backup_file ( " test.swp " ) ) ;
assert_se ( ! hidden_or_backup_file ( " test.rpmnew. " ) ) ;
assert_se ( ! hidden_or_backup_file ( " test.dpkg-old.foo " ) ) ;
}
2021-11-24 12:00:02 +01:00
TEST ( skip_dev_prefix ) {
2017-08-09 19:01:18 +02:00
assert_se ( streq ( skip_dev_prefix ( " / " ) , " / " ) ) ;
assert_se ( streq ( skip_dev_prefix ( " /dev " ) , " " ) ) ;
assert_se ( streq ( skip_dev_prefix ( " /dev/ " ) , " " ) ) ;
assert_se ( streq ( skip_dev_prefix ( " /dev/foo " ) , " foo " ) ) ;
assert_se ( streq ( skip_dev_prefix ( " /dev/foo/bar " ) , " foo/bar " ) ) ;
assert_se ( streq ( skip_dev_prefix ( " //dev " ) , " " ) ) ;
assert_se ( streq ( skip_dev_prefix ( " //dev// " ) , " " ) ) ;
assert_se ( streq ( skip_dev_prefix ( " /dev///foo " ) , " foo " ) ) ;
assert_se ( streq ( skip_dev_prefix ( " ///dev///foo///bar " ) , " foo///bar " ) ) ;
assert_se ( streq ( skip_dev_prefix ( " //foo " ) , " //foo " ) ) ;
assert_se ( streq ( skip_dev_prefix ( " foo " ) , " foo " ) ) ;
}
2021-11-24 12:00:02 +01:00
TEST ( empty_or_root ) {
2018-04-18 14:20:49 +02:00
assert_se ( empty_or_root ( NULL ) ) ;
assert_se ( empty_or_root ( " " ) ) ;
assert_se ( empty_or_root ( " / " ) ) ;
assert_se ( empty_or_root ( " // " ) ) ;
assert_se ( empty_or_root ( " /// " ) ) ;
assert_se ( empty_or_root ( " ///////////////// " ) ) ;
assert_se ( ! empty_or_root ( " xxx " ) ) ;
assert_se ( ! empty_or_root ( " /xxx " ) ) ;
assert_se ( ! empty_or_root ( " /xxx/ " ) ) ;
assert_se ( ! empty_or_root ( " //yy// " ) ) ;
}
2021-11-24 12:00:02 +01:00
TEST ( path_startswith_set ) {
2018-11-23 16:50:39 +01:00
assert_se ( streq_ptr ( PATH_STARTSWITH_SET ( " /foo/bar " , " /foo/quux " , " /foo/bar " , " /zzz " ) , " " ) ) ;
assert_se ( streq_ptr ( PATH_STARTSWITH_SET ( " /foo/bar " , " /foo/quux " , " /foo/ " , " /zzz " ) , " bar " ) ) ;
assert_se ( streq_ptr ( PATH_STARTSWITH_SET ( " /foo/bar " , " /foo/quux " , " /foo " , " /zzz " ) , " bar " ) ) ;
assert_se ( streq_ptr ( PATH_STARTSWITH_SET ( " /foo/bar " , " /foo/quux " , " / " , " /zzz " ) , " foo/bar " ) ) ;
assert_se ( streq_ptr ( PATH_STARTSWITH_SET ( " /foo/bar " , " /foo/quux " , " " , " /zzz " ) , NULL ) ) ;
assert_se ( streq_ptr ( PATH_STARTSWITH_SET ( " /foo/bar2 " , " /foo/quux " , " /foo/bar " , " /zzz " ) , NULL ) ) ;
assert_se ( streq_ptr ( PATH_STARTSWITH_SET ( " /foo/bar2 " , " /foo/quux " , " /foo/ " , " /zzz " ) , " bar2 " ) ) ;
assert_se ( streq_ptr ( PATH_STARTSWITH_SET ( " /foo/bar2 " , " /foo/quux " , " /foo " , " /zzz " ) , " bar2 " ) ) ;
assert_se ( streq_ptr ( PATH_STARTSWITH_SET ( " /foo/bar2 " , " /foo/quux " , " / " , " /zzz " ) , " foo/bar2 " ) ) ;
assert_se ( streq_ptr ( PATH_STARTSWITH_SET ( " /foo/bar2 " , " /foo/quux " , " " , " /zzz " ) , NULL ) ) ;
assert_se ( streq_ptr ( PATH_STARTSWITH_SET ( " /foo2/bar " , " /foo/quux " , " /foo/bar " , " /zzz " ) , NULL ) ) ;
assert_se ( streq_ptr ( PATH_STARTSWITH_SET ( " /foo2/bar " , " /foo/quux " , " /foo/ " , " /zzz " ) , NULL ) ) ;
assert_se ( streq_ptr ( PATH_STARTSWITH_SET ( " /foo2/bar " , " /foo/quux " , " /foo " , " /zzz " ) , NULL ) ) ;
assert_se ( streq_ptr ( PATH_STARTSWITH_SET ( " /foo2/bar " , " /foo/quux " , " / " , " /zzz " ) , " foo2/bar " ) ) ;
assert_se ( streq_ptr ( PATH_STARTSWITH_SET ( " /foo2/bar " , " /foo/quux " , " " , " /zzz " ) , NULL ) ) ;
}
2021-11-24 12:00:02 +01:00
TEST ( path_startswith_strv ) {
2019-03-28 22:35:46 +01:00
assert_se ( streq_ptr ( path_startswith_strv ( " /foo/bar " , STRV_MAKE ( " /foo/quux " , " /foo/bar " , " /zzz " ) ) , " " ) ) ;
assert_se ( streq_ptr ( path_startswith_strv ( " /foo/bar " , STRV_MAKE ( " /foo/quux " , " /foo/ " , " /zzz " ) ) , " bar " ) ) ;
assert_se ( streq_ptr ( path_startswith_strv ( " /foo/bar " , STRV_MAKE ( " /foo/quux " , " /foo " , " /zzz " ) ) , " bar " ) ) ;
assert_se ( streq_ptr ( path_startswith_strv ( " /foo/bar " , STRV_MAKE ( " /foo/quux " , " / " , " /zzz " ) ) , " foo/bar " ) ) ;
assert_se ( streq_ptr ( path_startswith_strv ( " /foo/bar " , STRV_MAKE ( " /foo/quux " , " " , " /zzz " ) ) , NULL ) ) ;
assert_se ( streq_ptr ( path_startswith_strv ( " /foo/bar2 " , STRV_MAKE ( " /foo/quux " , " /foo/bar " , " /zzz " ) ) , NULL ) ) ;
assert_se ( streq_ptr ( path_startswith_strv ( " /foo/bar2 " , STRV_MAKE ( " /foo/quux " , " /foo/ " , " /zzz " ) ) , " bar2 " ) ) ;
assert_se ( streq_ptr ( path_startswith_strv ( " /foo/bar2 " , STRV_MAKE ( " /foo/quux " , " /foo " , " /zzz " ) ) , " bar2 " ) ) ;
assert_se ( streq_ptr ( path_startswith_strv ( " /foo/bar2 " , STRV_MAKE ( " /foo/quux " , " / " , " /zzz " ) ) , " foo/bar2 " ) ) ;
assert_se ( streq_ptr ( path_startswith_strv ( " /foo/bar2 " , STRV_MAKE ( " /foo/quux " , " " , " /zzz " ) ) , NULL ) ) ;
assert_se ( streq_ptr ( path_startswith_strv ( " /foo2/bar " , STRV_MAKE ( " /foo/quux " , " /foo/bar " , " /zzz " ) ) , NULL ) ) ;
assert_se ( streq_ptr ( path_startswith_strv ( " /foo2/bar " , STRV_MAKE ( " /foo/quux " , " /foo/ " , " /zzz " ) ) , NULL ) ) ;
assert_se ( streq_ptr ( path_startswith_strv ( " /foo2/bar " , STRV_MAKE ( " /foo/quux " , " /foo " , " /zzz " ) ) , NULL ) ) ;
assert_se ( streq_ptr ( path_startswith_strv ( " /foo2/bar " , STRV_MAKE ( " /foo/quux " , " / " , " /zzz " ) ) , " foo2/bar " ) ) ;
assert_se ( streq_ptr ( path_startswith_strv ( " /foo2/bar " , STRV_MAKE ( " /foo/quux " , " " , " /zzz " ) ) , NULL ) ) ;
}
2022-08-17 06:43:37 +09:00
static void test_path_glob_can_match_one ( const char * pattern , const char * prefix , const char * expected ) {
_cleanup_free_ char * result = NULL ;
log_debug ( " %s(%s, %s, %s) " , __func__ , pattern , prefix , strnull ( expected ) ) ;
assert_se ( path_glob_can_match ( pattern , prefix , & result ) = = ! ! expected ) ;
assert_se ( streq_ptr ( result , expected ) ) ;
}
TEST ( path_glob_can_match ) {
test_path_glob_can_match_one ( " /foo/hoge/aaa " , " /foo/hoge/aaa/bbb " , NULL ) ;
test_path_glob_can_match_one ( " /foo/hoge/aaa " , " /foo/hoge/aaa " , " /foo/hoge/aaa " ) ;
test_path_glob_can_match_one ( " /foo/hoge/aaa " , " /foo/hoge " , " /foo/hoge/aaa " ) ;
test_path_glob_can_match_one ( " /foo/hoge/aaa " , " /foo " , " /foo/hoge/aaa " ) ;
test_path_glob_can_match_one ( " /foo/hoge/aaa " , " / " , " /foo/hoge/aaa " ) ;
test_path_glob_can_match_one ( " /foo/*/aaa " , " /foo/hoge/aaa/bbb " , NULL ) ;
test_path_glob_can_match_one ( " /foo/*/aaa " , " /foo/hoge/aaa " , " /foo/hoge/aaa " ) ;
test_path_glob_can_match_one ( " /foo/*/aaa " , " /foo/hoge " , " /foo/hoge/aaa " ) ;
test_path_glob_can_match_one ( " /foo/*/aaa " , " /foo " , " /foo/*/aaa " ) ;
test_path_glob_can_match_one ( " /foo/*/aaa " , " / " , " /foo/*/aaa " ) ;
test_path_glob_can_match_one ( " /foo/*/*/aaa " , " /foo/xxx/yyy/aaa/bbb " , NULL ) ;
test_path_glob_can_match_one ( " /foo/*/*/aaa " , " /foo/xxx/yyy/aaa " , " /foo/xxx/yyy/aaa " ) ;
test_path_glob_can_match_one ( " /foo/*/*/aaa " , " /foo/xxx/yyy " , " /foo/xxx/yyy/aaa " ) ;
test_path_glob_can_match_one ( " /foo/*/*/aaa " , " /foo/xxx " , " /foo/xxx/*/aaa " ) ;
test_path_glob_can_match_one ( " /foo/*/*/aaa " , " /foo " , " /foo/*/*/aaa " ) ;
test_path_glob_can_match_one ( " /foo/*/*/aaa " , " / " , " /foo/*/*/aaa " ) ;
test_path_glob_can_match_one ( " /foo/*/aaa/* " , " /foo/xxx/aaa/bbb/ccc " , NULL ) ;
test_path_glob_can_match_one ( " /foo/*/aaa/* " , " /foo/xxx/aaa/bbb " , " /foo/xxx/aaa/bbb " ) ;
test_path_glob_can_match_one ( " /foo/*/aaa/* " , " /foo/xxx/ccc " , NULL ) ;
test_path_glob_can_match_one ( " /foo/*/aaa/* " , " /foo/xxx/aaa " , " /foo/xxx/aaa/* " ) ;
test_path_glob_can_match_one ( " /foo/*/aaa/* " , " /foo/xxx " , " /foo/xxx/aaa/* " ) ;
test_path_glob_can_match_one ( " /foo/*/aaa/* " , " /foo " , " /foo/*/aaa/* " ) ;
test_path_glob_can_match_one ( " /foo/*/aaa/* " , " / " , " /foo/*/aaa/* " ) ;
}
2021-11-24 12:00:02 +01:00
TEST ( print_MAX ) {
2021-03-08 22:45:03 +01:00
log_info ( " PATH_MAX=%zu \n "
" FILENAME_MAX=%zu \n "
" NAME_MAX=%zu " ,
( size_t ) PATH_MAX ,
( size_t ) FILENAME_MAX ,
( size_t ) NAME_MAX ) ;
assert_cc ( FILENAME_MAX = = PATH_MAX ) ;
2013-03-28 22:03:53 -04:00
}
2021-11-24 12:00:02 +01:00
DEFINE_TEST_MAIN ( LOG_DEBUG ) ;