]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/fs-util.c
2 This file is part of systemd.
4 Copyright 2010 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
26 #include <linux/magic.h>
30 #include "alloc-util.h"
31 #include "dirent-util.h"
39 #include "parse-util.h"
40 #include "path-util.h"
41 #include "stat-util.h"
42 #include "stdio-util.h"
43 #include "string-util.h"
45 #include "time-util.h"
46 #include "user-util.h"
49 int unlink_noerrno ( const char * path
) {
60 int rmdir_parents ( const char * path
, const char * stop
) {
69 /* Skip trailing slashes */
70 while ( l
> 0 && path
[ l
- 1 ] == '/' )
76 /* Skip last component */
77 while ( l
> 0 && path
[ l
- 1 ] != '/' )
80 /* Skip trailing slashes */
81 while ( l
> 0 && path
[ l
- 1 ] == '/' )
91 if ( path_startswith ( stop
, t
)) {
107 int rename_noreplace ( int olddirfd
, const char * oldpath
, int newdirfd
, const char * newpath
) {
111 ret
= renameat2 ( olddirfd
, oldpath
, newdirfd
, newpath
, RENAME_NOREPLACE
);
115 /* renameat2() exists since Linux 3.15, btrfs added support for it later.
116 * If it is not implemented, fallback to another method. */
117 if (! IN_SET ( errno
, EINVAL
, ENOSYS
))
120 /* The link()/unlink() fallback does not work on directories. But
121 * renameat() without RENAME_NOREPLACE gives the same semantics on
122 * directories, except when newpath is an *empty* directory. This is
124 ret
= fstatat ( olddirfd
, oldpath
, & buf
, AT_SYMLINK_NOFOLLOW
);
125 if ( ret
>= 0 && S_ISDIR ( buf
. st_mode
)) {
126 ret
= renameat ( olddirfd
, oldpath
, newdirfd
, newpath
);
127 return ret
>= 0 ? 0 : - errno
;
130 /* If it is not a directory, use the link()/unlink() fallback. */
131 ret
= linkat ( olddirfd
, oldpath
, newdirfd
, newpath
, 0 );
135 ret
= unlinkat ( olddirfd
, oldpath
, 0 );
137 /* backup errno before the following unlinkat() alters it */
139 ( void ) unlinkat ( newdirfd
, newpath
, 0 );
147 int readlinkat_malloc ( int fd
, const char * p
, char ** ret
) {
162 n
= readlinkat ( fd
, p
, c
, l
- 1 );
169 if (( size_t ) n
< l
- 1 ) {
180 int readlink_malloc ( const char * p
, char ** ret
) {
181 return readlinkat_malloc ( AT_FDCWD
, p
, ret
);
184 int readlink_value ( const char * p
, char ** ret
) {
185 _cleanup_free_
char * link
= NULL
;
189 r
= readlink_malloc ( p
, & link
);
193 value
= basename ( link
);
197 value
= strdup ( value
);
206 int readlink_and_make_absolute ( const char * p
, char ** r
) {
207 _cleanup_free_
char * target
= NULL
;
214 j
= readlink_malloc ( p
, & target
);
218 k
= file_in_same_dir ( p
, target
);
226 int readlink_and_canonicalize ( const char * p
, const char * root
, char ** ret
) {
233 r
= readlink_and_make_absolute ( p
, & t
);
237 r
= chase_symlinks ( t
, root
, 0 , & s
);
239 /* If we can't follow up, then let's return the original string, slightly cleaned up. */
240 * ret
= path_kill_slashes ( t
);
249 int readlink_and_make_absolute_root ( const char * root
, const char * path
, char ** ret
) {
250 _cleanup_free_
char * target
= NULL
, * t
= NULL
;
254 full
= prefix_roota ( root
, path
);
255 r
= readlink_malloc ( full
, & target
);
259 t
= file_in_same_dir ( path
, target
);
269 int chmod_and_chown ( const char * path
, mode_t mode
, uid_t uid
, gid_t gid
) {
272 /* Under the assumption that we are running privileged we
273 * first change the access mode and only then hand out
274 * ownership to avoid a window where access is too open. */
276 if ( mode
!= MODE_INVALID
)
277 if ( chmod ( path
, mode
) < 0 )
280 if ( uid
!= UID_INVALID
|| gid
!= GID_INVALID
)
281 if ( chown ( path
, uid
, gid
) < 0 )
287 int fchmod_umask ( int fd
, mode_t m
) {
292 r
= fchmod ( fd
, m
& (~ u
)) < 0 ? - errno
: 0 ;
298 int fd_warn_permissions ( const char * path
, int fd
) {
301 if ( fstat ( fd
, & st
) < 0 )
304 if ( st
. st_mode
& 0111 )
305 log_warning ( "Configuration file %s is marked executable. Please remove executable permission bits. Proceeding anyway." , path
);
307 if ( st
. st_mode
& 0002 )
308 log_warning ( "Configuration file %s is marked world-writable. Please remove world writability permission bits. Proceeding anyway." , path
);
310 if ( getpid_cached () == 1 && ( st
. st_mode
& 0044 ) != 0044 )
311 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
);
316 int touch_file ( const char * path
, bool parents
, usec_t stamp
, uid_t uid
, gid_t gid
, mode_t mode
) {
317 _cleanup_close_
int fd
;
323 mkdir_parents ( path
, 0755 );
325 fd
= open ( path
, O_WRONLY
| O_CREAT
| O_CLOEXEC
| O_NOCTTY
,
326 IN_SET ( mode
, 0 , MODE_INVALID
) ? 0644 : mode
);
330 if ( mode
!= MODE_INVALID
) {
331 r
= fchmod ( fd
, mode
);
336 if ( uid
!= UID_INVALID
|| gid
!= GID_INVALID
) {
337 r
= fchown ( fd
, uid
, gid
);
342 if ( stamp
!= USEC_INFINITY
) {
343 struct timespec ts
[ 2 ];
345 timespec_store (& ts
[ 0 ], stamp
);
347 r
= futimens ( fd
, ts
);
349 r
= futimens ( fd
, NULL
);
356 int touch ( const char * path
) {
357 return touch_file ( path
, false , USEC_INFINITY
, UID_INVALID
, GID_INVALID
, MODE_INVALID
);
360 int symlink_idempotent ( const char * from
, const char * to
) {
366 if ( symlink ( from
, to
) < 0 ) {
367 _cleanup_free_
char * p
= NULL
;
372 r
= readlink_malloc ( to
, & p
);
373 if ( r
== - EINVAL
) /* Not a symlink? In that case return the original error we encountered: -EEXIST */
375 if ( r
< 0 ) /* Any other error? In that case propagate it as is */
378 if (! streq ( p
, from
)) /* Not the symlink we want it to be? In that case, propagate the original -EEXIST */
385 int symlink_atomic ( const char * from
, const char * to
) {
386 _cleanup_free_
char * t
= NULL
;
392 r
= tempfn_random ( to
, NULL
, & t
);
396 if ( symlink ( from
, t
) < 0 )
399 if ( rename ( t
, to
) < 0 ) {
407 int mknod_atomic ( const char * path
, mode_t mode
, dev_t dev
) {
408 _cleanup_free_
char * t
= NULL
;
413 r
= tempfn_random ( path
, NULL
, & t
);
417 if ( mknod ( t
, mode
, dev
) < 0 )
420 if ( rename ( t
, path
) < 0 ) {
428 int mkfifo_atomic ( const char * path
, mode_t mode
) {
429 _cleanup_free_
char * t
= NULL
;
434 r
= tempfn_random ( path
, NULL
, & t
);
438 if ( mkfifo ( t
, mode
) < 0 )
441 if ( rename ( t
, path
) < 0 ) {
449 int get_files_in_directory ( const char * path
, char *** list
) {
450 _cleanup_closedir_
DIR * d
= NULL
;
452 size_t bufsize
= 0 , n
= 0 ;
453 _cleanup_strv_free_
char ** l
= NULL
;
457 /* Returns all files in a directory in *list, and the number
458 * of files as return value. If list is NULL returns only the
465 FOREACH_DIRENT_ALL ( de
, d
, return - errno
) {
466 dirent_ensure_type ( d
, de
);
468 if (! dirent_is_file ( de
))
472 /* one extra slot is needed for the terminating NULL */
473 if (! GREEDY_REALLOC ( l
, bufsize
, n
+ 2 ))
476 l
[ n
] = strdup ( de
-> d_name
);
487 l
= NULL
; /* avoid freeing */
493 static int getenv_tmp_dir ( const char ** ret_path
) {
499 /* We use the same order of environment variables python uses in tempfile.gettempdir():
500 * https://docs.python.org/3/library/tempfile.html#tempfile.gettempdir */
501 FOREACH_STRING ( n
, "TMPDIR" , "TEMP" , "TMP" ) {
504 e
= secure_getenv ( n
);
507 if (! path_is_absolute ( e
)) {
511 if (! path_is_safe ( e
)) {
528 /* Remember first error, to make this more debuggable */
540 static int tmp_dir_internal ( const char * def
, const char ** ret
) {
547 r
= getenv_tmp_dir (& e
);
553 k
= is_dir ( def
, true );
557 return r
< 0 ? r
: k
;
563 int var_tmp_dir ( const char ** ret
) {
565 /* Returns the location for "larger" temporary files, that is backed by physical storage if available, and thus
566 * even might survive a boot: /var/tmp. If $TMPDIR (or related environment variables) are set, its value is
567 * returned preferably however. Note that both this function and tmp_dir() below are affected by $TMPDIR,
568 * making it a variable that overrides all temporary file storage locations. */
570 return tmp_dir_internal ( "/var/tmp" , ret
);
573 int tmp_dir ( const char ** ret
) {
575 /* Similar to var_tmp_dir() above, but returns the location for "smaller" temporary files, which is usually
576 * backed by an in-memory file system: /tmp. */
578 return tmp_dir_internal ( "/tmp" , ret
);
581 int inotify_add_watch_fd ( int fd
, int what
, uint32_t mask
) {
582 char path
[ strlen ( "/proc/self/fd/" ) + DECIMAL_STR_MAX ( int ) + 1 ];
585 /* This is like inotify_add_watch(), except that the file to watch is not referenced by a path, but by an fd */
586 xsprintf ( path
, "/proc/self/fd/%i" , what
);
588 r
= inotify_add_watch ( fd
, path
, mask
);
595 int chase_symlinks ( const char * path
, const char * original_root
, unsigned flags
, char ** ret
) {
596 _cleanup_free_
char * buffer
= NULL
, * done
= NULL
, * root
= NULL
;
597 _cleanup_close_
int fd
= - 1 ;
598 unsigned max_follow
= 32 ; /* how many symlinks to follow before giving up and returning ELOOP */
605 /* This is a lot like canonicalize_file_name(), but takes an additional "root" parameter, that allows following
606 * symlinks relative to a root directory, instead of the root of the host.
608 * Note that "root" primarily matters if we encounter an absolute symlink. It is also used when following
609 * relative symlinks to ensure they cannot be used to "escape" the root directory. The path parameter passed is
610 * assumed to be already prefixed by it, except if the CHASE_PREFIX_ROOT flag is set, in which case it is first
611 * prefixed accordingly.
613 * Algorithmically this operates on two path buffers: "done" are the components of the path we already
614 * processed and resolved symlinks, "." and ".." of. "todo" are the components of the path we still need to
615 * process. On each iteration, we move one component from "todo" to "done", processing it's special meaning
616 * each time. The "todo" path always starts with at least one slash, the "done" path always ends in no
617 * slash. We always keep an O_PATH fd to the component we are currently processing, thus keeping lookup races
620 * Suggested usage: whenever you want to canonicalize a path, use this function. Pass the absolute path you got
621 * as-is: fully qualified and relative to your host's root. Optionally, specify the root parameter to tell this
622 * function what to do when encountering a symlink with an absolute path as directory: prefix it by the
625 * Note: there's also chase_symlinks_prefix() (see below), which as first step prefixes the passed path by the
629 r
= path_make_absolute_cwd ( original_root
, & root
);
633 if ( flags
& CHASE_PREFIX_ROOT
)
634 path
= prefix_roota ( root
, path
);
637 r
= path_make_absolute_cwd ( path
, & buffer
);
641 fd
= open ( "/" , O_CLOEXEC
| O_NOFOLLOW
| O_PATH
);
647 _cleanup_free_
char * first
= NULL
;
648 _cleanup_close_
int child
= - 1 ;
652 /* Determine length of first component in the path */
653 n
= strspn ( todo
, "/" ); /* The slashes */
654 m
= n
+ strcspn ( todo
+ n
, "/" ); /* The entire length of the component */
656 /* Extract the first component. */
657 first
= strndup ( todo
, m
);
663 /* Just a single slash? Then we reached the end. */
664 if ( isempty ( first
) || path_equal ( first
, "/" ))
667 /* Just a dot? Then let's eat this up. */
668 if ( path_equal ( first
, "/." ))
671 /* Two dots? Then chop off the last bit of what we already found out. */
672 if ( path_equal ( first
, "/.." )) {
673 _cleanup_free_
char * parent
= NULL
;
676 /* If we already are at the top, then going up will not change anything. This is in-line with
677 * how the kernel handles this. */
678 if ( isempty ( done
) || path_equal ( done
, "/" ))
681 parent
= dirname_malloc ( done
);
685 /* Don't allow this to leave the root dir. */
687 path_startswith ( done
, root
) &&
688 ! path_startswith ( parent
, root
))
691 free_and_replace ( done
, parent
);
693 fd_parent
= openat ( fd
, ".." , O_CLOEXEC
| O_NOFOLLOW
| O_PATH
);
703 /* Otherwise let's see what this is. */
704 child
= openat ( fd
, first
+ n
, O_CLOEXEC
| O_NOFOLLOW
| O_PATH
);
707 if ( errno
== ENOENT
&&
708 ( flags
& CHASE_NONEXISTENT
) &&
709 ( isempty ( todo
) || path_is_safe ( todo
))) {
711 /* If CHASE_NONEXISTENT is set, and the path does not exist, then that's OK, return
712 * what we got so far. But don't allow this if the remaining path contains "../ or "./"
713 * or something else weird. */
715 if (! strextend (& done
, first
, todo
, NULL
))
725 if ( fstat ( child
, & st
) < 0 )
727 if (( flags
& CHASE_NO_AUTOFS
) &&
728 fd_check_fstype ( child
, AUTOFS_SUPER_MAGIC
) > 0 )
731 if ( S_ISLNK ( st
. st_mode
)) {
734 _cleanup_free_
char * destination
= NULL
;
736 /* This is a symlink, in this case read the destination. But let's make sure we don't follow
737 * symlinks without bounds. */
738 if (-- max_follow
<= 0 )
741 r
= readlinkat_malloc ( fd
, first
+ n
, & destination
);
744 if ( isempty ( destination
))
747 if ( path_is_absolute ( destination
)) {
749 /* An absolute destination. Start the loop from the beginning, but use the root
750 * directory as base. */
753 fd
= open ( root
?: "/" , O_CLOEXEC
| O_NOFOLLOW
| O_PATH
);
759 /* Note that we do not revalidate the root, we take it as is. */
768 /* Prefix what's left to do with what we just read, and start the loop again, but
769 * remain in the current directory. */
770 joined
= strjoin ( destination
, todo
);
772 joined
= strjoin ( "/" , destination
, todo
);
777 todo
= buffer
= joined
;
782 /* If this is not a symlink, then let's just add the name we read to what we already verified. */
787 if (! strextend (& done
, first
, NULL
))
791 /* And iterate again, but go one directory further down. */
798 /* Special case, turn the empty string into "/", to indicate the root directory. */
812 int access_fd ( int fd
, int mode
) {
813 char p
[ strlen ( "/proc/self/fd/" ) + DECIMAL_STR_MAX ( fd
) + 1 ];
816 /* Like access() but operates on an already open fd */
818 xsprintf ( p
, "/proc/self/fd/%i" , fd
);