]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/fs-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2010 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
27 #include <linux/magic.h>
31 #include "alloc-util.h"
32 #include "dirent-util.h"
40 #include "parse-util.h"
41 #include "path-util.h"
42 #include "stat-util.h"
43 #include "stdio-util.h"
44 #include "string-util.h"
46 #include "time-util.h"
47 #include "user-util.h"
50 int unlink_noerrno ( const char * path
) {
61 int rmdir_parents ( const char * path
, const char * stop
) {
70 /* Skip trailing slashes */
71 while ( l
> 0 && path
[ l
- 1 ] == '/' )
77 /* Skip last component */
78 while ( l
> 0 && path
[ l
- 1 ] != '/' )
81 /* Skip trailing slashes */
82 while ( l
> 0 && path
[ l
- 1 ] == '/' )
92 if ( path_startswith ( stop
, t
)) {
108 int rename_noreplace ( int olddirfd
, const char * oldpath
, int newdirfd
, const char * newpath
) {
112 ret
= renameat2 ( olddirfd
, oldpath
, newdirfd
, newpath
, RENAME_NOREPLACE
);
116 /* renameat2() exists since Linux 3.15, btrfs added support for it later.
117 * If it is not implemented, fallback to another method. */
118 if (! IN_SET ( errno
, EINVAL
, ENOSYS
))
121 /* The link()/unlink() fallback does not work on directories. But
122 * renameat() without RENAME_NOREPLACE gives the same semantics on
123 * directories, except when newpath is an *empty* directory. This is
125 ret
= fstatat ( olddirfd
, oldpath
, & buf
, AT_SYMLINK_NOFOLLOW
);
126 if ( ret
>= 0 && S_ISDIR ( buf
. st_mode
)) {
127 ret
= renameat ( olddirfd
, oldpath
, newdirfd
, newpath
);
128 return ret
>= 0 ? 0 : - errno
;
131 /* If it is not a directory, use the link()/unlink() fallback. */
132 ret
= linkat ( olddirfd
, oldpath
, newdirfd
, newpath
, 0 );
136 ret
= unlinkat ( olddirfd
, oldpath
, 0 );
138 /* backup errno before the following unlinkat() alters it */
140 ( void ) unlinkat ( newdirfd
, newpath
, 0 );
148 int readlinkat_malloc ( int fd
, const char * p
, char ** ret
) {
163 n
= readlinkat ( fd
, p
, c
, l
- 1 );
170 if (( size_t ) n
< l
- 1 ) {
181 int readlink_malloc ( const char * p
, char ** ret
) {
182 return readlinkat_malloc ( AT_FDCWD
, p
, ret
);
185 int readlink_value ( const char * p
, char ** ret
) {
186 _cleanup_free_
char * link
= NULL
;
190 r
= readlink_malloc ( p
, & link
);
194 value
= basename ( link
);
198 value
= strdup ( value
);
207 int readlink_and_make_absolute ( const char * p
, char ** r
) {
208 _cleanup_free_
char * target
= NULL
;
215 j
= readlink_malloc ( p
, & target
);
219 k
= file_in_same_dir ( p
, target
);
227 int readlink_and_canonicalize ( const char * p
, const char * root
, char ** ret
) {
234 r
= readlink_and_make_absolute ( p
, & t
);
238 r
= chase_symlinks ( t
, root
, 0 , & s
);
240 /* If we can't follow up, then let's return the original string, slightly cleaned up. */
241 * ret
= path_kill_slashes ( t
);
250 int readlink_and_make_absolute_root ( const char * root
, const char * path
, char ** ret
) {
251 _cleanup_free_
char * target
= NULL
, * t
= NULL
;
255 full
= prefix_roota ( root
, path
);
256 r
= readlink_malloc ( full
, & target
);
260 t
= file_in_same_dir ( path
, target
);
270 int chmod_and_chown ( const char * path
, mode_t mode
, uid_t uid
, gid_t gid
) {
273 /* Under the assumption that we are running privileged we
274 * first change the access mode and only then hand out
275 * ownership to avoid a window where access is too open. */
277 if ( mode
!= MODE_INVALID
)
278 if ( chmod ( path
, mode
) < 0 )
281 if ( uid
!= UID_INVALID
|| gid
!= GID_INVALID
)
282 if ( chown ( path
, uid
, gid
) < 0 )
288 int fchmod_umask ( int fd
, mode_t m
) {
293 r
= fchmod ( fd
, m
& (~ u
)) < 0 ? - errno
: 0 ;
299 int fd_warn_permissions ( const char * path
, int fd
) {
302 if ( fstat ( fd
, & st
) < 0 )
305 if ( st
. st_mode
& 0111 )
306 log_warning ( "Configuration file %s is marked executable. Please remove executable permission bits. Proceeding anyway." , path
);
308 if ( st
. st_mode
& 0002 )
309 log_warning ( "Configuration file %s is marked world-writable. Please remove world writability permission bits. Proceeding anyway." , path
);
311 if ( getpid_cached () == 1 && ( st
. st_mode
& 0044 ) != 0044 )
312 log_warning ( "Configuration file %s is marked world-inaccessible. This has no effect as configuration data is accessible via APIs without restrictions. Proceeding anyway." , path
);
317 int touch_file ( const char * path
, bool parents
, usec_t stamp
, uid_t uid
, gid_t gid
, mode_t mode
) {
318 _cleanup_close_
int fd
;
324 mkdir_parents ( path
, 0755 );
326 fd
= open ( path
, O_WRONLY
| O_CREAT
| O_CLOEXEC
| O_NOCTTY
,
327 IN_SET ( mode
, 0 , MODE_INVALID
) ? 0644 : mode
);
331 if ( mode
!= MODE_INVALID
) {
332 r
= fchmod ( fd
, mode
);
337 if ( uid
!= UID_INVALID
|| gid
!= GID_INVALID
) {
338 r
= fchown ( fd
, uid
, gid
);
343 if ( stamp
!= USEC_INFINITY
) {
344 struct timespec ts
[ 2 ];
346 timespec_store (& ts
[ 0 ], stamp
);
348 r
= futimens ( fd
, ts
);
350 r
= futimens ( fd
, NULL
);
357 int touch ( const char * path
) {
358 return touch_file ( path
, false , USEC_INFINITY
, UID_INVALID
, GID_INVALID
, MODE_INVALID
);
361 int symlink_idempotent ( const char * from
, const char * to
) {
367 if ( symlink ( from
, to
) < 0 ) {
368 _cleanup_free_
char * p
= NULL
;
373 r
= readlink_malloc ( to
, & p
);
374 if ( r
== - EINVAL
) /* Not a symlink? In that case return the original error we encountered: -EEXIST */
376 if ( r
< 0 ) /* Any other error? In that case propagate it as is */
379 if (! streq ( p
, from
)) /* Not the symlink we want it to be? In that case, propagate the original -EEXIST */
386 int symlink_atomic ( const char * from
, const char * to
) {
387 _cleanup_free_
char * t
= NULL
;
393 r
= tempfn_random ( to
, NULL
, & t
);
397 if ( symlink ( from
, t
) < 0 )
400 if ( rename ( t
, to
) < 0 ) {
408 int mknod_atomic ( const char * path
, mode_t mode
, dev_t dev
) {
409 _cleanup_free_
char * t
= NULL
;
414 r
= tempfn_random ( path
, NULL
, & t
);
418 if ( mknod ( t
, mode
, dev
) < 0 )
421 if ( rename ( t
, path
) < 0 ) {
429 int mkfifo_atomic ( const char * path
, mode_t mode
) {
430 _cleanup_free_
char * t
= NULL
;
435 r
= tempfn_random ( path
, NULL
, & t
);
439 if ( mkfifo ( t
, mode
) < 0 )
442 if ( rename ( t
, path
) < 0 ) {
450 int get_files_in_directory ( const char * path
, char *** list
) {
451 _cleanup_closedir_
DIR * d
= NULL
;
453 size_t bufsize
= 0 , n
= 0 ;
454 _cleanup_strv_free_
char ** l
= NULL
;
458 /* Returns all files in a directory in *list, and the number
459 * of files as return value. If list is NULL returns only the
466 FOREACH_DIRENT_ALL ( de
, d
, return - errno
) {
467 dirent_ensure_type ( d
, de
);
469 if (! dirent_is_file ( de
))
473 /* one extra slot is needed for the terminating NULL */
474 if (! GREEDY_REALLOC ( l
, bufsize
, n
+ 2 ))
477 l
[ n
] = strdup ( de
-> d_name
);
488 l
= NULL
; /* avoid freeing */
494 static int getenv_tmp_dir ( const char ** ret_path
) {
500 /* We use the same order of environment variables python uses in tempfile.gettempdir():
501 * https://docs.python.org/3/library/tempfile.html#tempfile.gettempdir */
502 FOREACH_STRING ( n
, "TMPDIR" , "TEMP" , "TMP" ) {
505 e
= secure_getenv ( n
);
508 if (! path_is_absolute ( e
)) {
512 if (! path_is_normalized ( e
)) {
529 /* Remember first error, to make this more debuggable */
541 static int tmp_dir_internal ( const char * def
, const char ** ret
) {
548 r
= getenv_tmp_dir (& e
);
554 k
= is_dir ( def
, true );
558 return r
< 0 ? r
: k
;
564 int var_tmp_dir ( const char ** ret
) {
566 /* Returns the location for "larger" temporary files, that is backed by physical storage if available, and thus
567 * even might survive a boot: /var/tmp. If $TMPDIR (or related environment variables) are set, its value is
568 * returned preferably however. Note that both this function and tmp_dir() below are affected by $TMPDIR,
569 * making it a variable that overrides all temporary file storage locations. */
571 return tmp_dir_internal ( "/var/tmp" , ret
);
574 int tmp_dir ( const char ** ret
) {
576 /* Similar to var_tmp_dir() above, but returns the location for "smaller" temporary files, which is usually
577 * backed by an in-memory file system: /tmp. */
579 return tmp_dir_internal ( "/tmp" , ret
);
582 int inotify_add_watch_fd ( int fd
, int what
, uint32_t mask
) {
583 char path
[ strlen ( "/proc/self/fd/" ) + DECIMAL_STR_MAX ( int ) + 1 ];
586 /* This is like inotify_add_watch(), except that the file to watch is not referenced by a path, but by an fd */
587 xsprintf ( path
, "/proc/self/fd/%i" , what
);
589 r
= inotify_add_watch ( fd
, path
, mask
);
596 int chase_symlinks ( const char * path
, const char * original_root
, unsigned flags
, char ** ret
) {
597 _cleanup_free_
char * buffer
= NULL
, * done
= NULL
, * root
= NULL
;
598 _cleanup_close_
int fd
= - 1 ;
599 unsigned max_follow
= 32 ; /* how many symlinks to follow before giving up and returning ELOOP */
606 /* This is a lot like canonicalize_file_name(), but takes an additional "root" parameter, that allows following
607 * symlinks relative to a root directory, instead of the root of the host.
609 * Note that "root" primarily matters if we encounter an absolute symlink. It is also used when following
610 * relative symlinks to ensure they cannot be used to "escape" the root directory. The path parameter passed is
611 * assumed to be already prefixed by it, except if the CHASE_PREFIX_ROOT flag is set, in which case it is first
612 * prefixed accordingly.
614 * Algorithmically this operates on two path buffers: "done" are the components of the path we already
615 * processed and resolved symlinks, "." and ".." of. "todo" are the components of the path we still need to
616 * process. On each iteration, we move one component from "todo" to "done", processing it's special meaning
617 * each time. The "todo" path always starts with at least one slash, the "done" path always ends in no
618 * slash. We always keep an O_PATH fd to the component we are currently processing, thus keeping lookup races
621 * Suggested usage: whenever you want to canonicalize a path, use this function. Pass the absolute path you got
622 * as-is: fully qualified and relative to your host's root. Optionally, specify the root parameter to tell this
623 * function what to do when encountering a symlink with an absolute path as directory: prefix it by the
626 * Note: there's also chase_symlinks_prefix() (see below), which as first step prefixes the passed path by the
630 r
= path_make_absolute_cwd ( original_root
, & root
);
634 if ( flags
& CHASE_PREFIX_ROOT
)
635 path
= prefix_roota ( root
, path
);
638 r
= path_make_absolute_cwd ( path
, & buffer
);
642 fd
= open ( "/" , O_CLOEXEC
| O_NOFOLLOW
| O_PATH
);
648 _cleanup_free_
char * first
= NULL
;
649 _cleanup_close_
int child
= - 1 ;
653 /* Determine length of first component in the path */
654 n
= strspn ( todo
, "/" ); /* The slashes */
655 m
= n
+ strcspn ( todo
+ n
, "/" ); /* The entire length of the component */
657 /* Extract the first component. */
658 first
= strndup ( todo
, m
);
664 /* Just a single slash? Then we reached the end. */
665 if ( isempty ( first
) || path_equal ( first
, "/" ))
668 /* Just a dot? Then let's eat this up. */
669 if ( path_equal ( first
, "/." ))
672 /* Two dots? Then chop off the last bit of what we already found out. */
673 if ( path_equal ( first
, "/.." )) {
674 _cleanup_free_
char * parent
= NULL
;
677 /* If we already are at the top, then going up will not change anything. This is in-line with
678 * how the kernel handles this. */
679 if ( isempty ( done
) || path_equal ( done
, "/" ))
682 parent
= dirname_malloc ( done
);
686 /* Don't allow this to leave the root dir. */
688 path_startswith ( done
, root
) &&
689 ! path_startswith ( parent
, root
))
692 free_and_replace ( done
, parent
);
694 fd_parent
= openat ( fd
, ".." , O_CLOEXEC
| O_NOFOLLOW
| O_PATH
);
704 /* Otherwise let's see what this is. */
705 child
= openat ( fd
, first
+ n
, O_CLOEXEC
| O_NOFOLLOW
| O_PATH
);
708 if ( errno
== ENOENT
&&
709 ( flags
& CHASE_NONEXISTENT
) &&
710 ( isempty ( todo
) || path_is_normalized ( todo
))) {
712 /* If CHASE_NONEXISTENT is set, and the path does not exist, then that's OK, return
713 * what we got so far. But don't allow this if the remaining path contains "../ or "./"
714 * or something else weird. */
716 if (! strextend (& done
, first
, todo
, NULL
))
726 if ( fstat ( child
, & st
) < 0 )
728 if (( flags
& CHASE_NO_AUTOFS
) &&
729 fd_check_fstype ( child
, AUTOFS_SUPER_MAGIC
) > 0 )
732 if ( S_ISLNK ( st
. st_mode
)) {
735 _cleanup_free_
char * destination
= NULL
;
737 /* This is a symlink, in this case read the destination. But let's make sure we don't follow
738 * symlinks without bounds. */
739 if (-- max_follow
<= 0 )
742 r
= readlinkat_malloc ( fd
, first
+ n
, & destination
);
745 if ( isempty ( destination
))
748 if ( path_is_absolute ( destination
)) {
750 /* An absolute destination. Start the loop from the beginning, but use the root
751 * directory as base. */
754 fd
= open ( root
?: "/" , O_CLOEXEC
| O_NOFOLLOW
| O_PATH
);
760 /* Note that we do not revalidate the root, we take it as is. */
769 /* Prefix what's left to do with what we just read, and start the loop again, but
770 * remain in the current directory. */
771 joined
= strjoin ( destination
, todo
);
773 joined
= strjoin ( "/" , destination
, todo
);
778 todo
= buffer
= joined
;
783 /* If this is not a symlink, then let's just add the name we read to what we already verified. */
788 if (! strextend (& done
, first
, NULL
))
792 /* And iterate again, but go one directory further down. */
799 /* Special case, turn the empty string into "/", to indicate the root directory. */
813 int access_fd ( int fd
, int mode
) {
814 char p
[ strlen ( "/proc/self/fd/" ) + DECIMAL_STR_MAX ( fd
) + 1 ];
817 /* Like access() but operates on an already open fd */
819 xsprintf ( p
, "/proc/self/fd/%i" , fd
);