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 "process-util.h"
43 #include "stat-util.h"
44 #include "stdio-util.h"
45 #include "string-util.h"
47 //#include "time-util.h"
48 #include "user-util.h"
51 /// Additional includes needed by elogind
52 #include "process-util.h"
54 int unlink_noerrno(const char *path) {
65 #if 0 /// UNNEEDED by elogind
66 int rmdir_parents(const char *path, const char *stop) {
75 /* Skip trailing slashes */
76 while (l > 0 && path[l-1] == '/')
82 /* Skip last component */
83 while (l > 0 && path[l-1] != '/')
86 /* Skip trailing slashes */
87 while (l > 0 && path[l-1] == '/')
97 if (path_startswith(stop, t)) {
113 int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) {
117 ret = renameat2(olddirfd, oldpath, newdirfd, newpath, RENAME_NOREPLACE);
121 /* renameat2() exists since Linux 3.15, btrfs added support for it later.
122 * If it is not implemented, fallback to another method. */
123 if (!IN_SET(errno, EINVAL, ENOSYS))
126 /* The link()/unlink() fallback does not work on directories. But
127 * renameat() without RENAME_NOREPLACE gives the same semantics on
128 * directories, except when newpath is an *empty* directory. This is
130 ret = fstatat(olddirfd, oldpath, &buf, AT_SYMLINK_NOFOLLOW);
131 if (ret >= 0 && S_ISDIR(buf.st_mode)) {
132 ret = renameat(olddirfd, oldpath, newdirfd, newpath);
133 return ret >= 0 ? 0 : -errno;
136 /* If it is not a directory, use the link()/unlink() fallback. */
137 ret = linkat(olddirfd, oldpath, newdirfd, newpath, 0);
141 ret = unlinkat(olddirfd, oldpath, 0);
143 /* backup errno before the following unlinkat() alters it */
145 (void) unlinkat(newdirfd, newpath, 0);
154 int readlinkat_malloc(int fd, const char *p, char **ret) {
169 n = readlinkat(fd, p, c, l-1);
176 if ((size_t) n < l-1) {
187 int readlink_malloc(const char *p, char **ret) {
188 return readlinkat_malloc(AT_FDCWD, p, ret);
191 #if 0 /// UNNEEDED by elogind
192 int readlink_value(const char *p, char **ret) {
193 _cleanup_free_ char *link = NULL;
197 r = readlink_malloc(p, &link);
201 value = basename(link);
205 value = strdup(value);
215 int readlink_and_make_absolute(const char *p, char **r) {
216 _cleanup_free_ char *target = NULL;
223 j = readlink_malloc(p, &target);
227 k = file_in_same_dir(p, target);
235 #if 0 /// UNNEEDED by elogind
236 int readlink_and_canonicalize(const char *p, const char *root, char **ret) {
243 r = readlink_and_make_absolute(p, &t);
247 r = chase_symlinks(t, root, 0, &s);
249 /* If we can't follow up, then let's return the original string, slightly cleaned up. */
250 *ret = path_kill_slashes(t);
259 int readlink_and_make_absolute_root(const char *root, const char *path, char **ret) {
260 _cleanup_free_ char *target = NULL, *t = NULL;
264 full = prefix_roota(root, path);
265 r = readlink_malloc(full, &target);
269 t = file_in_same_dir(path, target);
280 int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
283 /* Under the assumption that we are running privileged we
284 * first change the access mode and only then hand out
285 * ownership to avoid a window where access is too open. */
287 if (mode != MODE_INVALID)
288 if (chmod(path, mode) < 0)
291 if (uid != UID_INVALID || gid != GID_INVALID)
292 if (chown(path, uid, gid) < 0)
298 int fchmod_umask(int fd, mode_t m) {
303 r = fchmod(fd, m & (~u)) < 0 ? -errno : 0;
309 int fd_warn_permissions(const char *path, int fd) {
312 if (fstat(fd, &st) < 0)
315 if (st.st_mode & 0111)
316 log_warning("Configuration file %s is marked executable. Please remove executable permission bits. Proceeding anyway.", path);
318 if (st.st_mode & 0002)
319 log_warning("Configuration file %s is marked world-writable. Please remove world writability permission bits. Proceeding anyway.", path);
321 if (getpid_cached() == 1 && (st.st_mode & 0044) != 0044)
322 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);
327 int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode) {
328 char fdpath[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
329 _cleanup_close_ int fd = -1;
334 /* Note that touch_file() does not follow symlinks: if invoked on an existing symlink, then it is the symlink
335 * itself which is updated, not its target
337 * Returns the first error we encounter, but tries to apply as much as possible. */
340 (void) mkdir_parents(path, 0755);
342 /* Initially, we try to open the node with O_PATH, so that we get a reference to the node. This is useful in
343 * case the path refers to an existing device or socket node, as we can open it successfully in all cases, and
344 * won't trigger any driver magic or so. */
345 fd = open(path, O_PATH|O_CLOEXEC|O_NOFOLLOW);
350 /* if the node doesn't exist yet, we create it, but with O_EXCL, so that we only create a regular file
351 * here, and nothing else */
352 fd = open(path, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, IN_SET(mode, 0, MODE_INVALID) ? 0644 : mode);
357 /* Let's make a path from the fd, and operate on that. With this logic, we can adjust the access mode,
358 * ownership and time of the file node in all cases, even if the fd refers to an O_PATH object — which is
359 * something fchown(), fchmod(), futimensat() don't allow. */
360 xsprintf(fdpath, "/proc/self/fd/%i", fd);
362 if (mode != MODE_INVALID)
363 if (chmod(fdpath, mode) < 0)
366 if (uid_is_valid(uid) || gid_is_valid(gid))
367 if (chown(fdpath, uid, gid) < 0 && ret >= 0)
370 if (stamp != USEC_INFINITY) {
371 struct timespec ts[2];
373 timespec_store(&ts[0], stamp);
375 r = utimensat(AT_FDCWD, fdpath, ts, 0);
377 r = utimensat(AT_FDCWD, fdpath, NULL, 0);
378 if (r < 0 && ret >= 0)
384 int touch(const char *path) {
385 return touch_file(path, false, USEC_INFINITY, UID_INVALID, GID_INVALID, MODE_INVALID);
388 #if 0 /// UNNEEDED by elogind
389 int symlink_idempotent(const char *from, const char *to) {
395 if (symlink(from, to) < 0) {
396 _cleanup_free_ char *p = NULL;
401 r = readlink_malloc(to, &p);
402 if (r == -EINVAL) /* Not a symlink? In that case return the original error we encountered: -EEXIST */
404 if (r < 0) /* Any other error? In that case propagate it as is */
407 if (!streq(p, from)) /* Not the symlink we want it to be? In that case, propagate the original -EEXIST */
414 int symlink_atomic(const char *from, const char *to) {
415 _cleanup_free_ char *t = NULL;
421 r = tempfn_random(to, NULL, &t);
425 if (symlink(from, t) < 0)
428 if (rename(t, to) < 0) {
436 int mknod_atomic(const char *path, mode_t mode, dev_t dev) {
437 _cleanup_free_ char *t = NULL;
442 r = tempfn_random(path, NULL, &t);
446 if (mknod(t, mode, dev) < 0)
449 if (rename(t, path) < 0) {
457 int mkfifo_atomic(const char *path, mode_t mode) {
458 _cleanup_free_ char *t = NULL;
463 r = tempfn_random(path, NULL, &t);
467 if (mkfifo(t, mode) < 0)
470 if (rename(t, path) < 0) {
479 int get_files_in_directory(const char *path, char ***list) {
480 _cleanup_closedir_ DIR *d = NULL;
482 size_t bufsize = 0, n = 0;
483 _cleanup_strv_free_ char **l = NULL;
487 /* Returns all files in a directory in *list, and the number
488 * of files as return value. If list is NULL returns only the
495 FOREACH_DIRENT_ALL(de, d, return -errno) {
496 dirent_ensure_type(d, de);
498 if (!dirent_is_file(de))
502 /* one extra slot is needed for the terminating NULL */
503 if (!GREEDY_REALLOC(l, bufsize, n + 2))
506 l[n] = strdup(de->d_name);
517 l = NULL; /* avoid freeing */
523 static int getenv_tmp_dir(const char **ret_path) {
529 /* We use the same order of environment variables python uses in tempfile.gettempdir():
530 * https://docs.python.org/3/library/tempfile.html#tempfile.gettempdir */
531 FOREACH_STRING(n, "TMPDIR", "TEMP", "TMP") {
534 e = secure_getenv(n);
537 if (!path_is_absolute(e)) {
541 if (!path_is_normalized(e)) {
558 /* Remember first error, to make this more debuggable */
570 static int tmp_dir_internal(const char *def, const char **ret) {
577 r = getenv_tmp_dir(&e);
583 k = is_dir(def, true);
587 return r < 0 ? r : k;
593 #if 0 /// UNNEEDED by elogind
594 int var_tmp_dir(const char **ret) {
596 /* Returns the location for "larger" temporary files, that is backed by physical storage if available, and thus
597 * even might survive a boot: /var/tmp. If $TMPDIR (or related environment variables) are set, its value is
598 * returned preferably however. Note that both this function and tmp_dir() below are affected by $TMPDIR,
599 * making it a variable that overrides all temporary file storage locations. */
601 return tmp_dir_internal("/var/tmp", ret);
605 int tmp_dir(const char **ret) {
607 /* Similar to var_tmp_dir() above, but returns the location for "smaller" temporary files, which is usually
608 * backed by an in-memory file system: /tmp. */
610 return tmp_dir_internal("/tmp", ret);
613 #if 0 /// UNNEEDED by elogind
614 int inotify_add_watch_fd(int fd, int what, uint32_t mask) {
615 char path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
618 /* This is like inotify_add_watch(), except that the file to watch is not referenced by a path, but by an fd */
619 xsprintf(path, "/proc/self/fd/%i", what);
621 r = inotify_add_watch(fd, path, mask);
629 int chase_symlinks(const char *path, const char *original_root, unsigned flags, char **ret) {
630 _cleanup_free_ char *buffer = NULL, *done = NULL, *root = NULL;
631 _cleanup_close_ int fd = -1;
632 unsigned max_follow = 32; /* how many symlinks to follow before giving up and returning ELOOP */
639 /* This is a lot like canonicalize_file_name(), but takes an additional "root" parameter, that allows following
640 * symlinks relative to a root directory, instead of the root of the host.
642 * Note that "root" primarily matters if we encounter an absolute symlink. It is also used when following
643 * relative symlinks to ensure they cannot be used to "escape" the root directory. The path parameter passed is
644 * assumed to be already prefixed by it, except if the CHASE_PREFIX_ROOT flag is set, in which case it is first
645 * prefixed accordingly.
647 * Algorithmically this operates on two path buffers: "done" are the components of the path we already
648 * processed and resolved symlinks, "." and ".." of. "todo" are the components of the path we still need to
649 * process. On each iteration, we move one component from "todo" to "done", processing it's special meaning
650 * each time. The "todo" path always starts with at least one slash, the "done" path always ends in no
651 * slash. We always keep an O_PATH fd to the component we are currently processing, thus keeping lookup races
654 * Suggested usage: whenever you want to canonicalize a path, use this function. Pass the absolute path you got
655 * as-is: fully qualified and relative to your host's root. Optionally, specify the root parameter to tell this
656 * function what to do when encountering a symlink with an absolute path as directory: prefix it by the
660 r = path_make_absolute_cwd(original_root, &root);
664 if (flags & CHASE_PREFIX_ROOT)
665 path = prefix_roota(root, path);
668 r = path_make_absolute_cwd(path, &buffer);
672 fd = open("/", O_CLOEXEC|O_NOFOLLOW|O_PATH);
678 _cleanup_free_ char *first = NULL;
679 _cleanup_close_ int child = -1;
683 /* Determine length of first component in the path */
684 n = strspn(todo, "/"); /* The slashes */
685 m = n + strcspn(todo + n, "/"); /* The entire length of the component */
687 /* Extract the first component. */
688 first = strndup(todo, m);
694 /* Empty? Then we reached the end. */
698 /* Just a single slash? Then we reached the end. */
699 if (path_equal(first, "/")) {
700 /* Preserve the trailing slash */
701 if (!strextend(&done, "/", NULL))
707 /* Just a dot? Then let's eat this up. */
708 if (path_equal(first, "/."))
711 /* Two dots? Then chop off the last bit of what we already found out. */
712 if (path_equal(first, "/..")) {
713 _cleanup_free_ char *parent = NULL;
716 /* If we already are at the top, then going up will not change anything. This is in-line with
717 * how the kernel handles this. */
718 if (isempty(done) || path_equal(done, "/"))
721 parent = dirname_malloc(done);
725 /* Don't allow this to leave the root dir. */
727 path_startswith(done, root) &&
728 !path_startswith(parent, root))
731 free_and_replace(done, parent);
733 fd_parent = openat(fd, "..", O_CLOEXEC|O_NOFOLLOW|O_PATH);
743 /* Otherwise let's see what this is. */
744 child = openat(fd, first + n, O_CLOEXEC|O_NOFOLLOW|O_PATH);
747 if (errno == ENOENT &&
748 (flags & CHASE_NONEXISTENT) &&
749 (isempty(todo) || path_is_normalized(todo))) {
751 /* If CHASE_NONEXISTENT is set, and the path does not exist, then that's OK, return
752 * what we got so far. But don't allow this if the remaining path contains "../ or "./"
753 * or something else weird. */
755 /* If done is "/", as first also contains slash at the head, then remove this redundant slash. */
756 if (streq_ptr(done, "/"))
759 if (!strextend(&done, first, todo, NULL))
769 if (fstat(child, &st) < 0)
771 if ((flags & CHASE_NO_AUTOFS) &&
772 fd_is_fs_type(child, AUTOFS_SUPER_MAGIC) > 0)
775 if (S_ISLNK(st.st_mode)) {
778 _cleanup_free_ char *destination = NULL;
780 /* This is a symlink, in this case read the destination. But let's make sure we don't follow
781 * symlinks without bounds. */
782 if (--max_follow <= 0)
785 r = readlinkat_malloc(fd, first + n, &destination);
788 if (isempty(destination))
791 if (path_is_absolute(destination)) {
793 /* An absolute destination. Start the loop from the beginning, but use the root
794 * directory as base. */
797 fd = open(root ?: "/", O_CLOEXEC|O_NOFOLLOW|O_PATH);
803 /* Note that we do not revalidate the root, we take it as is. */
812 /* Prefix what's left to do with what we just read, and start the loop again, but
813 * remain in the current directory. */
814 joined = strjoin(destination, todo);
816 joined = strjoin("/", destination, todo);
821 todo = buffer = joined;
826 /* If this is not a symlink, then let's just add the name we read to what we already verified. */
831 /* If done is "/", as first also contains slash at the head, then remove this redundant slash. */
832 if (streq(done, "/"))
835 if (!strextend(&done, first, NULL))
839 /* And iterate again, but go one directory further down. */
846 /* Special case, turn the empty string into "/", to indicate the root directory. */
860 int access_fd(int fd, int mode) {
861 char p[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1];
864 /* Like access() but operates on an already open fd */
866 xsprintf(p, "/proc/self/fd/%i", fd);