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"
38 //#include "missing.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 /// Additional includes needed by elogind
51 #include "process-util.h"
53 int unlink_noerrno(const char *path) {
64 #if 0 /// UNNEEDED by elogind
65 int rmdir_parents(const char *path, const char *stop) {
74 /* Skip trailing slashes */
75 while (l > 0 && path[l-1] == '/')
81 /* Skip last component */
82 while (l > 0 && path[l-1] != '/')
85 /* Skip trailing slashes */
86 while (l > 0 && path[l-1] == '/')
96 if (path_startswith(stop, t)) {
112 int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) {
116 ret = renameat2(olddirfd, oldpath, newdirfd, newpath, RENAME_NOREPLACE);
120 /* renameat2() exists since Linux 3.15, btrfs added support for it later.
121 * If it is not implemented, fallback to another method. */
122 if (!IN_SET(errno, EINVAL, ENOSYS))
125 /* The link()/unlink() fallback does not work on directories. But
126 * renameat() without RENAME_NOREPLACE gives the same semantics on
127 * directories, except when newpath is an *empty* directory. This is
129 ret = fstatat(olddirfd, oldpath, &buf, AT_SYMLINK_NOFOLLOW);
130 if (ret >= 0 && S_ISDIR(buf.st_mode)) {
131 ret = renameat(olddirfd, oldpath, newdirfd, newpath);
132 return ret >= 0 ? 0 : -errno;
135 /* If it is not a directory, use the link()/unlink() fallback. */
136 ret = linkat(olddirfd, oldpath, newdirfd, newpath, 0);
140 ret = unlinkat(olddirfd, oldpath, 0);
142 /* backup errno before the following unlinkat() alters it */
144 (void) unlinkat(newdirfd, newpath, 0);
153 int readlinkat_malloc(int fd, const char *p, char **ret) {
168 n = readlinkat(fd, p, c, l-1);
175 if ((size_t) n < l-1) {
186 int readlink_malloc(const char *p, char **ret) {
187 return readlinkat_malloc(AT_FDCWD, p, ret);
190 #if 0 /// UNNEEDED by elogind
191 int readlink_value(const char *p, char **ret) {
192 _cleanup_free_ char *link = NULL;
196 r = readlink_malloc(p, &link);
200 value = basename(link);
204 value = strdup(value);
214 int readlink_and_make_absolute(const char *p, char **r) {
215 _cleanup_free_ char *target = NULL;
222 j = readlink_malloc(p, &target);
226 k = file_in_same_dir(p, target);
234 #if 0 /// UNNEEDED by elogind
235 int readlink_and_canonicalize(const char *p, const char *root, char **ret) {
242 r = readlink_and_make_absolute(p, &t);
246 r = chase_symlinks(t, root, 0, &s);
248 /* If we can't follow up, then let's return the original string, slightly cleaned up. */
249 *ret = path_kill_slashes(t);
258 int readlink_and_make_absolute_root(const char *root, const char *path, char **ret) {
259 _cleanup_free_ char *target = NULL, *t = NULL;
263 full = prefix_roota(root, path);
264 r = readlink_malloc(full, &target);
268 t = file_in_same_dir(path, target);
279 int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
282 /* Under the assumption that we are running privileged we
283 * first change the access mode and only then hand out
284 * ownership to avoid a window where access is too open. */
286 if (mode != MODE_INVALID)
287 if (chmod(path, mode) < 0)
290 if (uid != UID_INVALID || gid != GID_INVALID)
291 if (chown(path, uid, gid) < 0)
297 int fchmod_umask(int fd, mode_t m) {
302 r = fchmod(fd, m & (~u)) < 0 ? -errno : 0;
308 int fd_warn_permissions(const char *path, int fd) {
311 if (fstat(fd, &st) < 0)
314 if (st.st_mode & 0111)
315 log_warning("Configuration file %s is marked executable. Please remove executable permission bits. Proceeding anyway.", path);
317 if (st.st_mode & 0002)
318 log_warning("Configuration file %s is marked world-writable. Please remove world writability permission bits. Proceeding anyway.", path);
320 if (getpid_cached() == 1 && (st.st_mode & 0044) != 0044)
321 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);
326 int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode) {
327 _cleanup_close_ int fd;
333 mkdir_parents(path, 0755);
335 fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY,
336 IN_SET(mode, 0, MODE_INVALID) ? 0644 : mode);
340 if (mode != MODE_INVALID) {
341 r = fchmod(fd, mode);
346 if (uid != UID_INVALID || gid != GID_INVALID) {
347 r = fchown(fd, uid, gid);
352 if (stamp != USEC_INFINITY) {
353 struct timespec ts[2];
355 timespec_store(&ts[0], stamp);
357 r = futimens(fd, ts);
359 r = futimens(fd, NULL);
366 int touch(const char *path) {
367 return touch_file(path, false, USEC_INFINITY, UID_INVALID, GID_INVALID, MODE_INVALID);
370 #if 0 /// UNNEEDED by elogind
371 int symlink_idempotent(const char *from, const char *to) {
377 if (symlink(from, to) < 0) {
378 _cleanup_free_ char *p = NULL;
383 r = readlink_malloc(to, &p);
384 if (r == -EINVAL) /* Not a symlink? In that case return the original error we encountered: -EEXIST */
386 if (r < 0) /* Any other error? In that case propagate it as is */
389 if (!streq(p, from)) /* Not the symlink we want it to be? In that case, propagate the original -EEXIST */
396 int symlink_atomic(const char *from, const char *to) {
397 _cleanup_free_ char *t = NULL;
403 r = tempfn_random(to, NULL, &t);
407 if (symlink(from, t) < 0)
410 if (rename(t, to) < 0) {
418 int mknod_atomic(const char *path, mode_t mode, dev_t dev) {
419 _cleanup_free_ char *t = NULL;
424 r = tempfn_random(path, NULL, &t);
428 if (mknod(t, mode, dev) < 0)
431 if (rename(t, path) < 0) {
439 int mkfifo_atomic(const char *path, mode_t mode) {
440 _cleanup_free_ char *t = NULL;
445 r = tempfn_random(path, NULL, &t);
449 if (mkfifo(t, mode) < 0)
452 if (rename(t, path) < 0) {
461 int get_files_in_directory(const char *path, char ***list) {
462 _cleanup_closedir_ DIR *d = NULL;
464 size_t bufsize = 0, n = 0;
465 _cleanup_strv_free_ char **l = NULL;
469 /* Returns all files in a directory in *list, and the number
470 * of files as return value. If list is NULL returns only the
477 FOREACH_DIRENT_ALL(de, d, return -errno) {
478 dirent_ensure_type(d, de);
480 if (!dirent_is_file(de))
484 /* one extra slot is needed for the terminating NULL */
485 if (!GREEDY_REALLOC(l, bufsize, n + 2))
488 l[n] = strdup(de->d_name);
499 l = NULL; /* avoid freeing */
505 static int getenv_tmp_dir(const char **ret_path) {
511 /* We use the same order of environment variables python uses in tempfile.gettempdir():
512 * https://docs.python.org/3/library/tempfile.html#tempfile.gettempdir */
513 FOREACH_STRING(n, "TMPDIR", "TEMP", "TMP") {
516 e = secure_getenv(n);
519 if (!path_is_absolute(e)) {
523 if (!path_is_normalized(e)) {
540 /* Remember first error, to make this more debuggable */
552 static int tmp_dir_internal(const char *def, const char **ret) {
559 r = getenv_tmp_dir(&e);
565 k = is_dir(def, true);
569 return r < 0 ? r : k;
575 #if 0 /// UNNEEDED by elogind
576 int var_tmp_dir(const char **ret) {
578 /* Returns the location for "larger" temporary files, that is backed by physical storage if available, and thus
579 * even might survive a boot: /var/tmp. If $TMPDIR (or related environment variables) are set, its value is
580 * returned preferably however. Note that both this function and tmp_dir() below are affected by $TMPDIR,
581 * making it a variable that overrides all temporary file storage locations. */
583 return tmp_dir_internal("/var/tmp", ret);
587 int tmp_dir(const char **ret) {
589 /* Similar to var_tmp_dir() above, but returns the location for "smaller" temporary files, which is usually
590 * backed by an in-memory file system: /tmp. */
592 return tmp_dir_internal("/tmp", ret);
595 #if 0 /// UNNEEDED by elogind
596 int inotify_add_watch_fd(int fd, int what, uint32_t mask) {
597 char path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
600 /* This is like inotify_add_watch(), except that the file to watch is not referenced by a path, but by an fd */
601 xsprintf(path, "/proc/self/fd/%i", what);
603 r = inotify_add_watch(fd, path, mask);
611 int chase_symlinks(const char *path, const char *original_root, unsigned flags, char **ret) {
612 _cleanup_free_ char *buffer = NULL, *done = NULL, *root = NULL;
613 _cleanup_close_ int fd = -1;
614 unsigned max_follow = 32; /* how many symlinks to follow before giving up and returning ELOOP */
621 /* This is a lot like canonicalize_file_name(), but takes an additional "root" parameter, that allows following
622 * symlinks relative to a root directory, instead of the root of the host.
624 * Note that "root" primarily matters if we encounter an absolute symlink. It is also used when following
625 * relative symlinks to ensure they cannot be used to "escape" the root directory. The path parameter passed is
626 * assumed to be already prefixed by it, except if the CHASE_PREFIX_ROOT flag is set, in which case it is first
627 * prefixed accordingly.
629 * Algorithmically this operates on two path buffers: "done" are the components of the path we already
630 * processed and resolved symlinks, "." and ".." of. "todo" are the components of the path we still need to
631 * process. On each iteration, we move one component from "todo" to "done", processing it's special meaning
632 * each time. The "todo" path always starts with at least one slash, the "done" path always ends in no
633 * slash. We always keep an O_PATH fd to the component we are currently processing, thus keeping lookup races
636 * Suggested usage: whenever you want to canonicalize a path, use this function. Pass the absolute path you got
637 * as-is: fully qualified and relative to your host's root. Optionally, specify the root parameter to tell this
638 * function what to do when encountering a symlink with an absolute path as directory: prefix it by the
642 r = path_make_absolute_cwd(original_root, &root);
646 if (flags & CHASE_PREFIX_ROOT)
647 path = prefix_roota(root, path);
650 r = path_make_absolute_cwd(path, &buffer);
654 fd = open("/", O_CLOEXEC|O_NOFOLLOW|O_PATH);
660 _cleanup_free_ char *first = NULL;
661 _cleanup_close_ int child = -1;
665 /* Determine length of first component in the path */
666 n = strspn(todo, "/"); /* The slashes */
667 m = n + strcspn(todo + n, "/"); /* The entire length of the component */
669 /* Extract the first component. */
670 first = strndup(todo, m);
676 /* Empty? Then we reached the end. */
680 /* Just a single slash? Then we reached the end. */
681 if (path_equal(first, "/")) {
682 /* Preserve the trailing slash */
683 if (!strextend(&done, "/", NULL))
689 /* Just a dot? Then let's eat this up. */
690 if (path_equal(first, "/."))
693 /* Two dots? Then chop off the last bit of what we already found out. */
694 if (path_equal(first, "/..")) {
695 _cleanup_free_ char *parent = NULL;
698 /* If we already are at the top, then going up will not change anything. This is in-line with
699 * how the kernel handles this. */
700 if (isempty(done) || path_equal(done, "/"))
703 parent = dirname_malloc(done);
707 /* Don't allow this to leave the root dir. */
709 path_startswith(done, root) &&
710 !path_startswith(parent, root))
713 free_and_replace(done, parent);
715 fd_parent = openat(fd, "..", O_CLOEXEC|O_NOFOLLOW|O_PATH);
725 /* Otherwise let's see what this is. */
726 child = openat(fd, first + n, O_CLOEXEC|O_NOFOLLOW|O_PATH);
729 if (errno == ENOENT &&
730 (flags & CHASE_NONEXISTENT) &&
731 (isempty(todo) || path_is_normalized(todo))) {
733 /* If CHASE_NONEXISTENT is set, and the path does not exist, then that's OK, return
734 * what we got so far. But don't allow this if the remaining path contains "../ or "./"
735 * or something else weird. */
737 /* If done is "/", as first also contains slash at the head, then remove this redundant slash. */
738 if (streq_ptr(done, "/"))
741 if (!strextend(&done, first, todo, NULL))
751 if (fstat(child, &st) < 0)
753 if ((flags & CHASE_NO_AUTOFS) &&
754 fd_is_fs_type(child, AUTOFS_SUPER_MAGIC) > 0)
757 if (S_ISLNK(st.st_mode)) {
760 _cleanup_free_ char *destination = NULL;
762 /* This is a symlink, in this case read the destination. But let's make sure we don't follow
763 * symlinks without bounds. */
764 if (--max_follow <= 0)
767 r = readlinkat_malloc(fd, first + n, &destination);
770 if (isempty(destination))
773 if (path_is_absolute(destination)) {
775 /* An absolute destination. Start the loop from the beginning, but use the root
776 * directory as base. */
779 fd = open(root ?: "/", O_CLOEXEC|O_NOFOLLOW|O_PATH);
785 /* Note that we do not revalidate the root, we take it as is. */
794 /* Prefix what's left to do with what we just read, and start the loop again, but
795 * remain in the current directory. */
796 joined = strjoin(destination, todo);
798 joined = strjoin("/", destination, todo);
803 todo = buffer = joined;
808 /* If this is not a symlink, then let's just add the name we read to what we already verified. */
813 /* If done is "/", as first also contains slash at the head, then remove this redundant slash. */
814 if (streq(done, "/"))
817 if (!strextend(&done, first, NULL))
821 /* And iterate again, but go one directory further down. */
828 /* Special case, turn the empty string into "/", to indicate the root directory. */
842 int access_fd(int fd, int mode) {
843 char p[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1];
846 /* Like access() but operates on an already open fd */
848 xsprintf(p, "/proc/self/fd/%i", fd);