示例#1
0
int path_is_os_tree(const char *path) {
        int r;

        assert(path);

        /* Does the path exist at all? If not, generate an error immediately. This is useful so that a missing root dir
         * always results in -ENOENT, and we can properly distuingish the case where the whole root doesn't exist from
         * the case where just the os-release file is missing. */
        if (laccess(path, F_OK) < 0)
                return -errno;

        /* We use /usr/lib/os-release as flag file if something is an OS */
        r = chase_symlinks("/usr/lib/os-release", path, CHASE_PREFIX_ROOT, NULL);
        if (r == -ENOENT) {

                /* Also check for the old location in /etc, just in case. */
                r = chase_symlinks("/etc/os-release", path, CHASE_PREFIX_ROOT, NULL);
                if (r == -ENOENT)
                        return 0; /* We got nothing */
        }
        if (r < 0)
                return r;

        return 1;
}
示例#2
0
文件: delta.c 项目: OpenDZ/systemd
static int equivalent(const char *a, const char *b) {
        _cleanup_free_ char *x = NULL, *y = NULL;
        int r;

        r = chase_symlinks(a, NULL, 0, &x);
        if (r < 0)
                return r;

        r = chase_symlinks(b, NULL, 0, &y);
        if (r < 0)
                return r;

        return path_equal(x, y);
}
示例#3
0
static int determine_image(const char *image, bool permit_non_existing, char **ret) {
        int r;

        /* If the specified name is a valid image name, we pass it as-is to portabled, which will search for it in the
         * usual search directories. Otherwise we presume it's a path, and will normalize it on the client's side
         * (among other things, to make the path independent of the client's working directory) before passing it
         * over. */

        if (image_name_is_valid(image)) {
                char *c;

                if (!arg_quiet && laccess(image, F_OK) >= 0)
                        log_warning("Ambiguous invocation: current working directory contains file matching non-path argument '%s', ignoring. "
                                    "Prefix argument with './' to force reference to file in current working directory.", image);

                c = strdup(image);
                if (!c)
                        return log_oom();

                *ret = c;
                return 0;
        }

        if (arg_transport != BUS_TRANSPORT_LOCAL)
                return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
                                       "Operations on images by path not supported when connecting to remote systems.");

        r = chase_symlinks(image, NULL, CHASE_TRAIL_SLASH | (permit_non_existing ? CHASE_NONEXISTENT : 0), ret);
        if (r < 0)
                return log_error_errno(r, "Cannot normalize specified image path '%s': %m", image);

        return 0;
}
示例#4
0
int device_path_make_canonical(mode_t mode, dev_t devno, char **ret) {
        _cleanup_free_ char *p = NULL;
        int r;

        /* Finds the canonical path for a device, i.e. resolves the /dev/{char|block}/MAJOR:MINOR path to the end. */

        assert(ret);

        if (major(devno) == 0 && minor(devno) == 0) {
                char *s;

                /* A special hack to make sure our 'inaccessible' device nodes work. They won't have symlinks in
                 * /dev/block/ and /dev/char/, hence we handle them specially here. */

                if (S_ISCHR(mode))
                        s = strdup("/run/systemd/inaccessible/chr");
                else if (S_ISBLK(mode))
                        s = strdup("/run/systemd/inaccessible/blk");
                else
                        return -ENODEV;

                if (!s)
                        return -ENOMEM;

                *ret = s;
                return 0;
        }

        r = device_path_make_major_minor(mode, devno, &p);
        if (r < 0)
                return r;

        return chase_symlinks(p, NULL, 0, ret);
}
示例#5
0
static int unit_file_find_dir(
                const char *original_root,
                const char *path,
                char ***dirs) {

        _cleanup_free_ char *chased = NULL;
        int r;

        assert(path);

        r = chase_symlinks(path, original_root, 0, &chased);
        if (r == -ENOENT) /* Ignore -ENOENT, after all most units won't have a drop-in dir. */
                return 0;
        if (r == -ENAMETOOLONG) {
                /* Also, ignore -ENAMETOOLONG but log about it. After all, users are not even able to create the
                 * drop-in dir in such case. This mostly happens for device units with an overly long /sys path. */
                log_debug_errno(r, "Path '%s' too long, couldn't canonicalize, ignoring.", path);
                return 0;
        }
        if (r < 0)
                return log_warning_errno(r, "Failed to canonicalize path '%s': %m", path);

        r = strv_push(dirs, chased);
        if (r < 0)
                return log_oom();

        chased = NULL;
        return 0;
}
示例#6
0
static const char *
init_file_tmp_name (void)
{
  static char *file = 0;
  if (!file)
    {
      const char *name = init_file_name();
      const char *suffix = ".tmp";

      char *n2 = chase_symlinks (name);
      if (n2) name = n2;

      if (!name || !*name)
	file = "";
      else
	{
	  file = (char *) malloc(strlen(name) + strlen(suffix) + 2);
	  strcpy(file, name);
	  strcat(file, suffix);
	}

      if (n2) free (n2);
    }

  if (file && *file)
    return file;
  else
    return 0;
}
示例#7
0
        STRV_FOREACH_PAIR(link, p, links) {
                _cleanup_free_ char *target, *f, *l;

                assert_se(f = strjoin(original_dir, *p));
                assert_se(l = strjoin(copy_dir, *link));

                assert_se(chase_symlinks(l, NULL, 0, &target) == 1);
                assert_se(path_equal(f, target));
        }
示例#8
0
static int make_volatile(const char *path) {
        _cleanup_free_ char *old_usr = NULL;
        int r;

        assert(path);

        r = chase_symlinks("/usr", path, CHASE_PREFIX_ROOT, &old_usr);
        if (r < 0)
                return log_error_errno(r, "/usr not available in old root: %m");

        r = mkdir_p("/run/systemd/volatile-sysroot", 0700);
        if (r < 0)
                return log_error_errno(r, "Couldn't generate volatile sysroot directory: %m");

        r = mount_verbose(LOG_ERR, "tmpfs", "/run/systemd/volatile-sysroot", "tmpfs", MS_STRICTATIME, "mode=755");
        if (r < 0)
                goto finish_rmdir;

        if (mkdir("/run/systemd/volatile-sysroot/usr", 0755) < 0) {
                r = log_error_errno(errno, "Failed to create /usr directory: %m");
                goto finish_umount;
        }

        r = mount_verbose(LOG_ERR, old_usr, "/run/systemd/volatile-sysroot/usr", NULL, MS_BIND|MS_REC, NULL);
        if (r < 0)
                goto finish_umount;

        r = bind_remount_recursive("/run/systemd/volatile-sysroot/usr", true, NULL);
        if (r < 0) {
                log_error_errno(r, "Failed to remount /usr read-only: %m");
                goto finish_umount;
        }

        r = umount_recursive(path, 0);
        if (r < 0) {
                log_error_errno(r, "Failed to unmount %s: %m", path);
                goto finish_umount;
        }

        if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) < 0)
                log_warning_errno(errno, "Failed to remount %s MS_SLAVE|MS_REC, ignoring: %m", path);

        r = mount_verbose(LOG_ERR, "/run/systemd/volatile-sysroot", path, NULL, MS_MOVE, NULL);

finish_umount:
        (void) umount_recursive("/run/systemd/volatile-sysroot", 0);

finish_rmdir:
        (void) rmdir("/run/systemd/volatile-sysroot");

        return r;
}
示例#9
0
static int directory_image_get_os_release(Image *image, char ***ret, sd_bus_error *error) {

        _cleanup_free_ char *path = NULL;
        int r;

        assert(image);
        assert(ret);

        r = chase_symlinks("/etc/os-release", image->path, CHASE_PREFIX_ROOT, &path);
        if (r == -ENOENT)
                r = chase_symlinks("/usr/lib/os-release", image->path, CHASE_PREFIX_ROOT, &path);
        if (r == -ENOENT)
                return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Image does not contain OS release information");
        if (r < 0)
                return sd_bus_error_set_errnof(error, r, "Failed to resolve %s: %m", image->path);

        r = load_env_file_pairs(NULL, path, NULL, ret);
        if (r < 0)
                return sd_bus_error_set_errnof(error, r, "Failed to open %s: %m", path);

        return 0;
}
示例#10
0
文件: mkdir.c 项目: Werkov/systemd
int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, bool follow_symlink, mkdir_func_t _mkdir) {
        struct stat st;
        int r;

        assert(_mkdir != mkdir);

        if (_mkdir(path, mode) >= 0) {
                r = chmod_and_chown(path, mode, uid, gid);
                if (r < 0)
                        return r;
        }

        if (lstat(path, &st) < 0)
                return -errno;

        if (follow_symlink && S_ISLNK(st.st_mode)) {
                _cleanup_free_ char *p = NULL;

                r = chase_symlinks(path, NULL, CHASE_NONEXISTENT, &p);
                if (r < 0)
                        return r;
                if (r == 0)
                        return mkdir_safe_internal(p, mode, uid, gid, false, _mkdir);

                if (lstat(p, &st) < 0)
                        return -errno;
        }

        if ((st.st_mode & 0007) > (mode & 0007) ||
            (st.st_mode & 0070) > (mode & 0070) ||
            (st.st_mode & 0700) > (mode & 0700) ||
            (uid != UID_INVALID && st.st_uid != uid) ||
            (gid != GID_INVALID && st.st_gid != gid) ||
            !S_ISDIR(st.st_mode))
                return -EEXIST;

        return 0;
}
示例#11
0
static void test_chase_symlinks(void) {
        _cleanup_free_ char *result = NULL;
        char temp[] = "/tmp/test-chase.XXXXXX";
        const char *top, *p, *q;
        int r;

        assert_se(mkdtemp(temp));

        top = strjoina(temp, "/top");
        assert_se(mkdir(top, 0700) >= 0);

        p = strjoina(top, "/dot");
        assert_se(symlink(".", p) >= 0);

        p = strjoina(top, "/dotdot");
        assert_se(symlink("..", p) >= 0);

        p = strjoina(top, "/dotdota");
        assert_se(symlink("../a", p) >= 0);

        p = strjoina(temp, "/a");
        assert_se(symlink("b", p) >= 0);

        p = strjoina(temp, "/b");
        assert_se(symlink("/usr", p) >= 0);

        p = strjoina(temp, "/start");
        assert_se(symlink("top/dot/dotdota", p) >= 0);

        /* Paths that use symlinks underneath the "root" */

        r = chase_symlinks(p, NULL, 0, &result);
        assert_se(r > 0);
        assert_se(path_equal(result, "/usr"));

        result = mfree(result);
        r = chase_symlinks(p, temp, 0, &result);
        assert_se(r == -ENOENT);

        q = strjoina(temp, "/usr");

        r = chase_symlinks(p, temp, CHASE_NONEXISTENT, &result);
        assert_se(r == 0);
        assert_se(path_equal(result, q));

        assert_se(mkdir(q, 0700) >= 0);

        r = chase_symlinks(p, temp, 0, &result);
        assert_se(r > 0);
        assert_se(path_equal(result, q));

        p = strjoina(temp, "/slash");
        assert_se(symlink("/", p) >= 0);

        result = mfree(result);
        r = chase_symlinks(p, NULL, 0, &result);
        assert_se(r > 0);
        assert_se(path_equal(result, "/"));

        result = mfree(result);
        r = chase_symlinks(p, temp, 0, &result);
        assert_se(r > 0);
        assert_se(path_equal(result, temp));

        /* Paths that would "escape" outside of the "root" */

        p = strjoina(temp, "/6dots");
        assert_se(symlink("../../..", p) >= 0);

        result = mfree(result);
        r = chase_symlinks(p, temp, 0, &result);
        assert_se(r > 0 && path_equal(result, temp));

        p = strjoina(temp, "/6dotsusr");
        assert_se(symlink("../../../usr", p) >= 0);

        result = mfree(result);
        r = chase_symlinks(p, temp, 0, &result);
        assert_se(r > 0 && path_equal(result, q));

        p = strjoina(temp, "/top/8dotsusr");
        assert_se(symlink("../../../../usr", p) >= 0);

        result = mfree(result);
        r = chase_symlinks(p, temp, 0, &result);
        assert_se(r > 0 && path_equal(result, q));

        /* Paths that contain repeated slashes */

        p = strjoina(temp, "/slashslash");
        assert_se(symlink("///usr///", p) >= 0);

        result = mfree(result);
        r = chase_symlinks(p, NULL, 0, &result);
        assert_se(r > 0);
        assert_se(path_equal(result, "/usr"));

        result = mfree(result);
        r = chase_symlinks(p, temp, 0, &result);
        assert_se(r > 0);
        assert_se(path_equal(result, q));

        /* Paths using . */

        result = mfree(result);
        r = chase_symlinks("/etc/./.././", NULL, 0, &result);
        assert_se(r > 0);
        assert_se(path_equal(result, "/"));

        result = mfree(result);
        r = chase_symlinks("/etc/./.././", "/etc", 0, &result);
        assert_se(r > 0 && path_equal(result, "/etc"));

        result = mfree(result);
        r = chase_symlinks("/etc/machine-id/foo", NULL, 0, &result);
        assert_se(r == -ENOTDIR);

        /* Path that loops back to self */

        result = mfree(result);
        p = strjoina(temp, "/recursive-symlink");
        assert_se(symlink("recursive-symlink", p) >= 0);
        r = chase_symlinks(p, NULL, 0, &result);
        assert_se(r == -ELOOP);

        /* Path which doesn't exist */

        p = strjoina(temp, "/idontexist");
        r = chase_symlinks(p, NULL, 0, &result);
        assert_se(r == -ENOENT);

        r = chase_symlinks(p, NULL, CHASE_NONEXISTENT, &result);
        assert_se(r == 0);
        assert_se(path_equal(result, p));
        result = mfree(result);

        p = strjoina(temp, "/idontexist/meneither");
        r = chase_symlinks(p, NULL, 0, &result);
        assert_se(r == -ENOENT);

        r = chase_symlinks(p, NULL, CHASE_NONEXISTENT, &result);
        assert_se(r == 0);
        assert_se(path_equal(result, p));
        result = mfree(result);

        /* Path which doesn't exist, but contains weird stuff */

        p = strjoina(temp, "/idontexist/..");
        r = chase_symlinks(p, NULL, 0, &result);
        assert_se(r == -ENOENT);

        r = chase_symlinks(p, NULL, CHASE_NONEXISTENT, &result);
        assert_se(r == -ENOENT);

        assert_se(rm_rf(temp, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
}