コード例 #1
0
ファイル: udevadm-util.c プロジェクト: htejun/systemd
int find_device(const char *id, const char *prefix, sd_device **ret) {
        _cleanup_free_ char *buf = NULL;

        assert(id);
        assert(ret);

        if (prefix && !path_startswith(id, prefix)) {
                buf = path_join(NULL, prefix, id);
                if (!buf)
                        return -ENOMEM;
                id = buf;
        }

        if (path_startswith(id, "/sys/"))
                return sd_device_new_from_syspath(ret, id);

        if (path_startswith(id, "/dev/")) {
                struct stat st;

                if (stat(id, &st) < 0)
                        return -errno;

                return device_new_from_stat_rdev(ret, &st);
        }

        return -EINVAL;
}
コード例 #2
0
ファイル: udevadm-util.c プロジェクト: halfline/systemd
struct udev_device *find_device(const char *id,
                                const char *prefix) {

        assert(id);

        if (prefix && !startswith(id, prefix))
                id = strjoina(prefix, id);

        if (path_startswith(id, "/dev/")) {
                struct stat statbuf;
                char type;

                if (stat(id, &statbuf) < 0)
                        return NULL;

                if (S_ISBLK(statbuf.st_mode))
                        type = 'b';
                else if (S_ISCHR(statbuf.st_mode))
                        type = 'c';
                else
                        return NULL;

                return udev_device_new_from_devnum(NULL, type, statbuf.st_rdev);
        } else if (path_startswith(id, "/sys/"))
                return udev_device_new_from_syspath(NULL, id);
        else
                return NULL;
}
コード例 #3
0
ファイル: mkdir.c プロジェクト: ahills/eudev
int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir) {
        const char *p, *e;
        int r;

        assert(path);

        if (prefix && !path_startswith(path, prefix))
                return -ENOTDIR;

        /* return immediately if directory exists */
        e = strrchr(path, '/');
        if (!e)
                return -EINVAL;

        if (e == path)
                return 0;

	char buf[PATH_MAX + 1];
	p = buf;
	assert(e-path < sizeof(buf));
	memcpy(buf, path, e-path);
	buf[e-path] = 0;

        r = is_dir(p, true);
        if (r > 0)
                return 0;
        if (r == 0)
                return -ENOTDIR;

        /* create every parent directory in the path, except the last component */
        p = path + strspn(path, "/");
        for (;;) {
                char t[strlen(path) + 1];

                e = p + strcspn(p, "/");
                p = e + strspn(e, "/");

                /* Is this the last component? If so, then we're
                 * done */
                if (*p == 0)
                        return 0;

                memcpy(t, path, e - path);
                t[e-path] = 0;

                if (prefix && path_startswith(prefix, t))
                        continue;

                r = _mkdir(t, mode);
                if (r < 0 && errno != EEXIST)
                        return -errno;
        }
}
コード例 #4
0
ファイル: mkdir.c プロジェクト: andymg/android-udev
static int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, bool apply) {
        const char *p, *e;
        int r;

        assert(path);

        if (prefix && !path_startswith(path, prefix))
                return -ENOTDIR;

        /* return immediately if directory exists */
        e = strrchr(path, '/');
        if (!e)
                return -EINVAL;

        if (e == path)
                return 0;

        p = strndupa(path, e - path);
        r = is_dir(p);
        if (r > 0)
                return 0;
        if (r == 0)
                return -ENOTDIR;

        /* create every parent directory in the path, except the last component */
        p = path + strspn(path, "/");
        for (;;) {
                char t[strlen(path) + 1];

                e = p + strcspn(p, "/");
                p = e + strspn(e, "/");

                /* Is this the last component? If so, then we're
                 * done */
                if (*p == 0)
                        return 0;

                memcpy(t, path, e - path);
                t[e-path] = 0;

                if (prefix && path_startswith(prefix, t))
                        continue;

                r = label_mkdir(t, mode, apply);
                if (r < 0 && errno != EEXIST)
                        return -errno;
        }
}
コード例 #5
0
ファイル: namespace.c プロジェクト: heftig/systemd
static void drop_outside_root(const char *root_directory, MountEntry *m, unsigned *n) {
        MountEntry *f, *t;

        assert(m);
        assert(n);

        /* Nothing to do */
        if (!root_directory)
                return;

        /* Drops all mounts that are outside of the root directory. */

        for (f = m, t = m; f < m + *n; f++) {

                if (!path_startswith(mount_entry_path(f), root_directory)) {
                        log_debug("%s is outside of root directory.", mount_entry_path(f));
                        mount_entry_done(f);
                        continue;
                }

                *t = *f;
                t++;
        }

        *n = t - m;
}
コード例 #6
0
int cg_fix_path(const char *path, char **result) {
        char *t, *c, *p;
        int r;

        assert(path);
        assert(result);

        /* First check if it already is a filesystem path */
        if (path_is_absolute(path) &&
            path_startswith(path, "/sys/fs/cgroup") &&
            access(path, F_OK) >= 0) {

                if (!(t = strdup(path)))
                        return -ENOMEM;

                *result = t;
                return 0;
        }

        /* Otherwise treat it as cg spec */
        if ((r = cg_split_spec(path, &c, &p)) < 0)
                return r;

        r = cg_get_path(c ? c : SYSTEMD_CGROUP_CONTROLLER, p ? p : "/", NULL, result);
        free(c);
        free(p);

        return r;
}
コード例 #7
0
ファイル: tests.c プロジェクト: heftig/systemd
const char* get_testdata_dir(const char *suffix) {
        const char *env;
        /* convenience: caller does not need to free result */
        static char testdir[PATH_MAX];

        /* if the env var is set, use that */
        env = getenv("SYSTEMD_TEST_DATA");
        testdir[sizeof(testdir) - 1] = '\0';
        if (env) {
                if (access(env, F_OK) < 0) {
                        fputs("ERROR: $SYSTEMD_TEST_DATA directory does not exist\n", stderr);
                        exit(1);
                }
                strncpy(testdir, env, sizeof(testdir) - 1);
        } else {
                _cleanup_free_ char *exedir = NULL;
                assert_se(readlink_and_make_absolute("/proc/self/exe", &exedir) >= 0);

                /* Check if we're running from the builddir. If so, use the compiled in path. */
                if (path_startswith(exedir, ABS_BUILD_DIR))
                        assert_se(snprintf(testdir, sizeof(testdir), "%s/test", ABS_SRC_DIR) > 0);
                else
                        /* Try relative path, according to the install-test layout */
                        assert_se(snprintf(testdir, sizeof(testdir), "%s/testdata", dirname(exedir)) > 0);

                /* test this without the suffix, as it may contain a glob */
                if (access(testdir, F_OK) < 0) {
                        fputs("ERROR: Cannot find testdata directory, set $SYSTEMD_TEST_DATA\n", stderr);
                        exit(1);
                }
        }

        strncpy(testdir + strlen(testdir), suffix, sizeof(testdir) - strlen(testdir) - 1);
        return testdir;
}
コード例 #8
0
ファイル: namespace.c プロジェクト: heftig/systemd
static void drop_inaccessible(MountEntry *m, unsigned *n) {
        MountEntry *f, *t;
        const char *clear = NULL;

        assert(m);
        assert(n);

        /* Drops all entries obstructed by another entry further up the tree. Expects that the array is properly
         * ordered already. */

        for (f = m, t = m; f < m + *n; f++) {

                /* If we found a path set for INACCESSIBLE earlier, and this entry has it as prefix we should drop
                 * it, as inaccessible paths really should drop the entire subtree. */
                if (clear && path_startswith(mount_entry_path(f), clear)) {
                        log_debug("%s is masked by %s.", mount_entry_path(f), clear);
                        mount_entry_done(f);
                        continue;
                }

                clear = f->mode == INACCESSIBLE ? mount_entry_path(f) : NULL;

                *t = *f;
                t++;
        }

        *n = t - m;
}
コード例 #9
0
ファイル: smack-util.c プロジェクト: jsynacek/systemd-rhel
int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {

#ifdef HAVE_SMACK
        struct stat st;
#endif
        int r = 0;

        assert(path);

#ifdef HAVE_SMACK
        if (!mac_smack_use())
                return 0;

        /*
         * Path must be in /dev and must exist
         */
        if (!path_startswith(path, "/dev"))
                return 0;

        r = lstat(path, &st);
        if (r >= 0) {
                const char *label;

                /*
                 * Label directories and character devices "*".
                 * Label symlinks "_".
                 * Don't change anything else.
                 */

                if (S_ISDIR(st.st_mode))
                        label = SMACK_STAR_LABEL;
                else if (S_ISLNK(st.st_mode))
                        label = SMACK_FLOOR_LABEL;
                else if (S_ISCHR(st.st_mode))
                        label = SMACK_STAR_LABEL;
                else
                        return 0;

                r = lsetxattr(path, "security.SMACK64", label, strlen(label), 0);

                /* If the FS doesn't support labels, then exit without warning */
                if (r < 0 && errno == ENOTSUP)
                        return 0;
        }

        if (r < 0) {
                /* Ignore ENOENT in some cases */
                if (ignore_enoent && errno == ENOENT)
                        return 0;

                if (ignore_erofs && errno == EROFS)
                        return 0;

                r = log_debug_errno(errno, "Unable to fix SMACK label of %s: %m", path);
        }
#endif

        return r;
}
コード例 #10
0
ファイル: pull-dkr.c プロジェクト: shaded-enmity/systemd
int dkr_pull_new(
                DkrPull **ret,
                sd_event *event,
                const char *index_url,
                const char *image_root,
                DkrPullFinished on_finished,
                void *userdata) {

        _cleanup_(dkr_pull_unrefp) DkrPull *i = NULL;
        char *e;
        int r;

        assert(ret);
        assert(index_url);

        if (!http_url_is_valid(index_url))
                return -EINVAL;

        i = new0(DkrPull, 1);
        if (!i)
                return -ENOMEM;

        i->on_finished = on_finished;
        i->userdata = userdata;

        i->image_root = strdup(image_root ?: "/var/lib/machines");
        if (!i->image_root)
                return -ENOMEM;

        i->grow_machine_directory = path_startswith(i->image_root, "/var/lib/machines");

        i->index_url = strdup(index_url);
        if (!i->index_url)
                return -ENOMEM;

        e = endswith(i->index_url, "/");
        if (e)
                *e = 0;

        if (event)
                i->event = sd_event_ref(event);
        else {
                r = sd_event_default(&i->event);
                if (r < 0)
                        return r;
        }

        r = curl_glue_new(&i->glue, i->event);
        if (r < 0)
                return r;

        i->glue->on_finished = pull_job_curl_on_finished;
        i->glue->userdata = i;

        *ret = i;
        i = NULL;

        return 0;
}
コード例 #11
0
int device_path_parse_major_minor(const char *path, mode_t *ret_mode, dev_t *ret_devno) {
        mode_t mode;
        dev_t devno;
        int r;

        /* Tries to extract the major/minor directly from the device path if we can. Handles /dev/block/ and /dev/char/
         * paths, as well out synthetic inaccessible device nodes. Never goes to disk. Returns -ENODEV if the device
         * path cannot be parsed like this.  */

        if (path_equal(path, "/run/systemd/inaccessible/chr")) {
                mode = S_IFCHR;
                devno = makedev(0, 0);
        } else if (path_equal(path, "/run/systemd/inaccessible/blk")) {
                mode = S_IFBLK;
                devno = makedev(0, 0);
        } else {
                const char *w;

                w = path_startswith(path, "/dev/block/");
                if (w)
                        mode = S_IFBLK;
                else {
                        w = path_startswith(path, "/dev/char/");
                        if (!w)
                                return -ENODEV;

                        mode = S_IFCHR;
                }

                r = parse_dev(w, &devno);
                if (r < 0)
                        return r;
        }

        if (ret_mode)
                *ret_mode = mode;
        if (ret_devno)
                *ret_devno = devno;

        return 0;
}
コード例 #12
0
ファイル: mount-setup.c プロジェクト: banada/systemd
bool mount_point_is_api(const char *path) {
        unsigned i;

        /* Checks if this mount point is considered "API", and hence
         * should be ignored */

        for (i = 0; i < ELEMENTSOF(mount_table); i ++)
                if (path_equal(path, mount_table[i].where))
                        return true;

        return path_startswith(path, "/sys/fs/cgroup/");
}
コード例 #13
0
ファイル: logind-utmp.c プロジェクト: halfline/systemd
bool logind_wall_tty_filter(const char *tty, void *userdata) {
        Manager *m = userdata;
        const char *p;

        assert(m);

        if (!m->scheduled_shutdown_tty)
                return true;

        p = path_startswith(tty, "/dev/");
        if (!p)
                return true;

        return !streq(p, m->scheduled_shutdown_tty);
}
コード例 #14
0
ファイル: pull-tar.c プロジェクト: AlexBaranosky/systemd
int tar_pull_new(
                TarPull **ret,
                sd_event *event,
                const char *image_root,
                TarPullFinished on_finished,
                void *userdata) {

        _cleanup_(tar_pull_unrefp) TarPull *i = NULL;
        int r;

        assert(ret);
        assert(event);

        i = new0(TarPull, 1);
        if (!i)
                return -ENOMEM;

        i->on_finished = on_finished;
        i->userdata = userdata;

        i->image_root = strdup(image_root ?: "/var/lib/machines");
        if (!i->image_root)
                return -ENOMEM;

        i->grow_machine_directory = path_startswith(i->image_root, "/var/lib/machines");

        if (event)
                i->event = sd_event_ref(event);
        else {
                r = sd_event_default(&i->event);
                if (r < 0)
                        return r;
        }

        r = curl_glue_new(&i->glue, i->event);
        if (r < 0)
                return r;

        i->glue->on_finished = pull_job_curl_on_finished;
        i->glue->userdata = i;

        *ret = i;
        i = NULL;

        return 0;
}
コード例 #15
0
ファイル: import-tar.c プロジェクト: rachari/systemd
int tar_import_new(
                TarImport **ret,
                sd_event *event,
                const char *image_root,
                TarImportFinished on_finished,
                void *userdata) {

        _cleanup_(tar_import_unrefp) TarImport *i = NULL;
        int r;

        assert(ret);

        i = new0(TarImport, 1);
        if (!i)
                return -ENOMEM;

        i->input_fd = i->tar_fd = -1;
        i->on_finished = on_finished;
        i->userdata = userdata;

        RATELIMIT_INIT(i->progress_rate_limit, 100 * USEC_PER_MSEC, 1);
        i->last_percent = (unsigned) -1;

        i->image_root = strdup(image_root ?: "/var/lib/machines");
        if (!i->image_root)
                return -ENOMEM;

        i->grow_machine_directory = path_startswith(i->image_root, "/var/lib/machines");

        if (event)
                i->event = sd_event_ref(event);
        else {
                r = sd_event_default(&i->event);
                if (r < 0)
                        return r;
        }

        *ret = i;
        i = NULL;

        return 0;
}
コード例 #16
0
ファイル: namespace.c プロジェクト: heftig/systemd
static void drop_nop(MountEntry *m, unsigned *n) {
        MountEntry *f, *t;

        assert(m);
        assert(n);

        /* Drops all entries which have an immediate parent that has the same type, as they are redundant. Assumes the
         * list is ordered by prefixes. */

        for (f = m, t = m; f < m + *n; f++) {

                /* Only suppress such subtrees for READONLY and READWRITE entries */
                if (IN_SET(f->mode, READONLY, READWRITE)) {
                        MountEntry *p;
                        bool found = false;

                        /* Now let's find the first parent of the entry we are looking at. */
                        for (p = t-1; p >= m; p--) {
                                if (path_startswith(mount_entry_path(f), mount_entry_path(p))) {
                                        found = true;
                                        break;
                                }
                        }

                        /* We found it, let's see if it's the same mode, if so, we can drop this entry */
                        if (found && p->mode == f->mode) {
                                log_debug("%s is redundant by %s", mount_entry_path(f), mount_entry_path(p));
                                mount_entry_done(f);
                                continue;
                        }
                }

                *t = *f;
                t++;
        }

        *n = t - m;
}
コード例 #17
0
ファイル: getty-generator.c プロジェクト: nmartensen/systemd
int main(int argc, char *argv[]) {

        static const char virtualization_consoles[] =
                "hvc0\0"
                "xvc0\0"
                "hvsi0\0"
                "sclp_line0\0"
                "ttysclp0\0"
                "3270!tty1\0";

        _cleanup_free_ char *active = NULL;
        const char *j;
        int r;

        if (argc > 1 && argc != 4) {
                log_error("This program takes three or no arguments.");
                return EXIT_FAILURE;
        }

        if (argc > 1)
                arg_dest = argv[1];

        log_set_target(LOG_TARGET_SAFE);
        log_parse_environment();
        log_open();

        umask(0022);

        if (detect_container() > 0) {
                _cleanup_free_ char *container_ttys = NULL;

                log_debug("Automatically adding console shell.");

                if (add_symlink("console-getty.service", "console-getty.service") < 0)
                        return EXIT_FAILURE;

                /* When $container_ttys is set for PID 1, spawn
                 * gettys on all ptys named therein. Note that despite
                 * the variable name we only support ptys here. */

                r = getenv_for_pid(1, "container_ttys", &container_ttys);
                if (r > 0) {
                        const char *word, *state;
                        size_t l;

                        FOREACH_WORD(word, l, container_ttys, state) {
                                const char *t;
                                char tty[l + 1];

                                memcpy(tty, word, l);
                                tty[l] = 0;

                                /* First strip off /dev/ if it is specified */
                                t = path_startswith(tty, "/dev/");
                                if (!t)
                                        t = tty;

                                /* Then, make sure it's actually a pty */
                                t = path_startswith(t, "pts/");
                                if (!t)
                                        continue;

                                if (add_container_getty(t) < 0)
                                        return EXIT_FAILURE;
                        }
                }

                /* Don't add any further magic if we are in a container */
                return EXIT_SUCCESS;
        }
コード例 #18
0
ファイル: cgls.c プロジェクト: michich/systemd
int main(int argc, char *argv[]) {
        int r, output_flags;

        log_parse_environment();
        log_open();

        r = parse_argv(argc, argv);
        if (r <= 0)
                goto finish;

        if (!arg_no_pager) {
                r = pager_open(false);
                if (r > 0 && arg_full < 0)
                        arg_full = true;
        }

        output_flags =
                arg_all * OUTPUT_SHOW_ALL |
                (arg_full > 0) * OUTPUT_FULL_WIDTH;

        if (optind < argc) {
                _cleanup_free_ char *root = NULL;
                int i;

                r = get_cgroup_root(&root);
                if (r < 0)
                        goto finish;

                for (i = optind; i < argc; i++) {
                        int q;

                        if (path_startswith(argv[i], "/sys/fs/cgroup")) {

                                printf("Directory %s:\n", argv[i]);
                                fflush(stdout);

                                q = show_cgroup_by_path(argv[i], NULL, 0, arg_kernel_threads, output_flags);
                        } else {
                                _cleanup_free_ char *c = NULL, *p = NULL, *j = NULL;
                                const char *controller, *path;

                                r = cg_split_spec(argv[i], &c, &p);
                                if (r < 0) {
                                        log_error_errno(r, "Failed to split argument %s: %m", argv[i]);
                                        goto finish;
                                }

                                controller = c ?: SYSTEMD_CGROUP_CONTROLLER;
                                if (p) {
                                        j = strjoin(root, "/", p, NULL);
                                        if (!j) {
                                                r = log_oom();
                                                goto finish;
                                        }

                                        path_kill_slashes(j);
                                        path = j;
                                } else
                                        path = root;

                                show_cg_info(controller, path);

                                q = show_cgroup(controller, path, NULL, 0, arg_kernel_threads, output_flags);
                        }

                        if (q < 0)
                                r = q;
                }

        } else {
コード例 #19
0
ファイル: machine-image.c プロジェクト: SimonPe/systemd
static int image_make(
                const char *pretty,
                int dfd,
                const char *path,
                const char *filename,
                Image **ret) {

        struct stat st;
        bool read_only;
        int r;

        assert(filename);

        /* We explicitly *do* follow symlinks here, since we want to
         * allow symlinking trees into /var/lib/machines/, and treat
         * them normally. */

        if (fstatat(dfd, filename, &st, 0) < 0)
                return -errno;

        read_only =
                (path && path_startswith(path, "/usr")) ||
                (faccessat(dfd, filename, W_OK, AT_EACCESS) < 0 && errno == EROFS);

        if (S_ISDIR(st.st_mode)) {
                _cleanup_close_ int fd = -1;
                unsigned file_attr = 0;

                if (!ret)
                        return 1;

                if (!pretty)
                        pretty = filename;

                fd = openat(dfd, filename, O_CLOEXEC|O_NOCTTY|O_DIRECTORY);
                if (fd < 0)
                        return -errno;

                /* btrfs subvolumes have inode 256 */
                if (st.st_ino == 256) {

                        r = btrfs_is_filesystem(fd);
                        if (r < 0)
                                return r;
                        if (r) {
                                BtrfsSubvolInfo info;

                                /* It's a btrfs subvolume */

                                r = btrfs_subvol_get_info_fd(fd, 0, &info);
                                if (r < 0)
                                        return r;

                                r = image_new(IMAGE_SUBVOLUME,
                                              pretty,
                                              path,
                                              filename,
                                              info.read_only || read_only,
                                              info.otime,
                                              0,
                                              ret);
                                if (r < 0)
                                        return r;

                                if (btrfs_quota_scan_ongoing(fd) == 0) {
                                        BtrfsQuotaInfo quota;

                                        r = btrfs_subvol_get_subtree_quota_fd(fd, 0, &quota);
                                        if (r >= 0) {
                                                (*ret)->usage = quota.referenced;
                                                (*ret)->usage_exclusive = quota.exclusive;

                                                (*ret)->limit = quota.referenced_max;
                                                (*ret)->limit_exclusive = quota.exclusive_max;
                                        }
                                }

                                return 1;
                        }
                }

                /* If the IMMUTABLE bit is set, we consider the
                 * directory read-only. Since the ioctl is not
                 * supported everywhere we ignore failures. */
                (void) read_attr_fd(fd, &file_attr);

                /* It's just a normal directory. */
                r = image_new(IMAGE_DIRECTORY,
                              pretty,
                              path,
                              filename,
                              read_only || (file_attr & FS_IMMUTABLE_FL),
                              0,
                              0,
                              ret);
                if (r < 0)
                        return r;

                return 1;

        } else if (S_ISREG(st.st_mode) && endswith(filename, ".raw")) {
                usec_t crtime = 0;

                /* It's a RAW disk image */

                if (!ret)
                        return 1;

                fd_getcrtime_at(dfd, filename, &crtime, 0);

                if (!pretty)
                        pretty = strndupa(filename, strlen(filename) - 4);

                r = image_new(IMAGE_RAW,
                              pretty,
                              path,
                              filename,
                              !(st.st_mode & 0222) || read_only,
                              crtime,
                              timespec_load(&st.st_mtim),
                              ret);
                if (r < 0)
                        return r;

                (*ret)->usage = (*ret)->usage_exclusive = st.st_blocks * 512;
                (*ret)->limit = (*ret)->limit_exclusive = st.st_size;

                return 1;
        }

        return 0;
}
コード例 #20
0
ファイル: mount-util.c プロジェクト: dm0-/systemd
int umount_recursive(const char *prefix, int flags) {
        int n = 0, r;
        bool again;

        /* Try to umount everything recursively below a
         * directory. Also, take care of stacked mounts, and keep
         * unmounting them until they are gone. */

        do {
                _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;

                again = false;
                r = 0;

                proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
                if (!proc_self_mountinfo)
                        return -errno;

                (void) __fsetlocking(proc_self_mountinfo, FSETLOCKING_BYCALLER);

                for (;;) {
                        _cleanup_free_ char *path = NULL, *p = NULL;
                        int k;

                        k = fscanf(proc_self_mountinfo,
                                   "%*s "       /* (1) mount id */
                                   "%*s "       /* (2) parent id */
                                   "%*s "       /* (3) major:minor */
                                   "%*s "       /* (4) root */
                                   "%ms "       /* (5) mount point */
                                   "%*s"        /* (6) mount options */
                                   "%*[^-]"     /* (7) optional fields */
                                   "- "         /* (8) separator */
                                   "%*s "       /* (9) file system type */
                                   "%*s"        /* (10) mount source */
                                   "%*s"        /* (11) mount options 2 */
                                   "%*[^\n]",   /* some rubbish at the end */
                                   &path);
                        if (k != 1) {
                                if (k == EOF)
                                        break;

                                continue;
                        }

                        k = cunescape(path, UNESCAPE_RELAX, &p);
                        if (k < 0)
                                return k;

                        if (!path_startswith(p, prefix))
                                continue;

                        if (umount2(p, flags) < 0) {
                                r = log_debug_errno(errno, "Failed to umount %s: %m", p);
                                continue;
                        }

                        log_debug("Successfully unmounted %s", p);

                        again = true;
                        n++;

                        break;
                }

        } while (again);

        return r < 0 ? r : n;
}
コード例 #21
0
ファイル: mount-util.c プロジェクト: dm0-/systemd
/* Use this function only if you do not have direct access to /proc/self/mountinfo but the caller can open it
 * for you. This is the case when /proc is masked or not mounted. Otherwise, use bind_remount_recursive. */
int bind_remount_recursive_with_mountinfo(
                const char *prefix,
                unsigned long new_flags,
                unsigned long flags_mask,
                char **blacklist,
                FILE *proc_self_mountinfo) {

        _cleanup_set_free_free_ Set *done = NULL;
        _cleanup_free_ char *cleaned = NULL;
        int r;

        assert(proc_self_mountinfo);

        /* Recursively remount a directory (and all its submounts) read-only or read-write. If the directory is already
         * mounted, we reuse the mount and simply mark it MS_BIND|MS_RDONLY (or remove the MS_RDONLY for read-write
         * operation). If it isn't we first make it one. Afterwards we apply MS_BIND|MS_RDONLY (or remove MS_RDONLY) to
         * all submounts we can access, too. When mounts are stacked on the same mount point we only care for each
         * individual "top-level" mount on each point, as we cannot influence/access the underlying mounts anyway. We
         * do not have any effect on future submounts that might get propagated, they migt be writable. This includes
         * future submounts that have been triggered via autofs.
         *
         * If the "blacklist" parameter is specified it may contain a list of subtrees to exclude from the
         * remount operation. Note that we'll ignore the blacklist for the top-level path. */

        cleaned = strdup(prefix);
        if (!cleaned)
                return -ENOMEM;

        path_simplify(cleaned, false);

        done = set_new(&path_hash_ops);
        if (!done)
                return -ENOMEM;

        for (;;) {
                _cleanup_set_free_free_ Set *todo = NULL;
                bool top_autofs = false;
                char *x;
                unsigned long orig_flags;

                todo = set_new(&path_hash_ops);
                if (!todo)
                        return -ENOMEM;

                rewind(proc_self_mountinfo);

                for (;;) {
                        _cleanup_free_ char *path = NULL, *p = NULL, *type = NULL;
                        int k;

                        k = fscanf(proc_self_mountinfo,
                                   "%*s "       /* (1) mount id */
                                   "%*s "       /* (2) parent id */
                                   "%*s "       /* (3) major:minor */
                                   "%*s "       /* (4) root */
                                   "%ms "       /* (5) mount point */
                                   "%*s"        /* (6) mount options (superblock) */
                                   "%*[^-]"     /* (7) optional fields */
                                   "- "         /* (8) separator */
                                   "%ms "       /* (9) file system type */
                                   "%*s"        /* (10) mount source */
                                   "%*s"        /* (11) mount options (bind mount) */
                                   "%*[^\n]",   /* some rubbish at the end */
                                   &path,
                                   &type);
                        if (k != 2) {
                                if (k == EOF)
                                        break;

                                continue;
                        }

                        r = cunescape(path, UNESCAPE_RELAX, &p);
                        if (r < 0)
                                return r;

                        if (!path_startswith(p, cleaned))
                                continue;

                        /* Ignore this mount if it is blacklisted, but only if it isn't the top-level mount we shall
                         * operate on. */
                        if (!path_equal(cleaned, p)) {
                                bool blacklisted = false;
                                char **i;

                                STRV_FOREACH(i, blacklist) {

                                        if (path_equal(*i, cleaned))
                                                continue;

                                        if (!path_startswith(*i, cleaned))
                                                continue;

                                        if (path_startswith(p, *i)) {
                                                blacklisted = true;
                                                log_debug("Not remounting %s blacklisted by %s, called for %s", p, *i, cleaned);
                                                break;
                                        }
                                }
                                if (blacklisted)
                                        continue;
                        }

                        /* Let's ignore autofs mounts.  If they aren't
                         * triggered yet, we want to avoid triggering
                         * them, as we don't make any guarantees for
                         * future submounts anyway.  If they are
                         * already triggered, then we will find
                         * another entry for this. */
                        if (streq(type, "autofs")) {
                                top_autofs = top_autofs || path_equal(cleaned, p);
                                continue;
                        }

                        if (!set_contains(done, p)) {
                                r = set_consume(todo, p);
                                p = NULL;
                                if (r == -EEXIST)
                                        continue;
                                if (r < 0)
                                        return r;
                        }
                }

                /* If we have no submounts to process anymore and if
                 * the root is either already done, or an autofs, we
                 * are done */
                if (set_isempty(todo) &&
                    (top_autofs || set_contains(done, cleaned)))
                        return 0;

                if (!set_contains(done, cleaned) &&
                    !set_contains(todo, cleaned)) {
                        /* The prefix directory itself is not yet a mount, make it one. */
                        if (mount(cleaned, cleaned, NULL, MS_BIND|MS_REC, NULL) < 0)
                                return -errno;

                        orig_flags = 0;
                        (void) get_mount_flags(cleaned, &orig_flags);
                        orig_flags &= ~MS_RDONLY;

                        if (mount(NULL, cleaned, NULL, (orig_flags & ~flags_mask)|MS_BIND|MS_REMOUNT|new_flags, NULL) < 0)
                                return -errno;

                        log_debug("Made top-level directory %s a mount point.", prefix);

                        r = set_put_strdup(done, cleaned);
                        if (r < 0)
                                return r;
                }

                while ((x = set_steal_first(todo))) {

                        r = set_consume(done, x);
                        if (IN_SET(r, 0, -EEXIST))
                                continue;
                        if (r < 0)
                                return r;

                        /* Deal with mount points that are obstructed by a later mount */
                        r = path_is_mount_point(x, NULL, 0);
                        if (IN_SET(r, 0, -ENOENT))
                                continue;
                        if (IN_SET(r, -EACCES, -EPERM)) {
                                /* Even if root user invoke this, submounts under private FUSE or NFS mount points
                                 * may not be acceessed. E.g.,
                                 *
                                 * $ bindfs --no-allow-other ~/mnt/mnt ~/mnt/mnt
                                 * $ bindfs --no-allow-other ~/mnt ~/mnt
                                 *
                                 * Then, root user cannot access the mount point ~/mnt/mnt.
                                 * In such cases, the submounts are ignored, as we have no way to manage them. */
                                log_debug_errno(r, "Failed to determine '%s' is mount point or not, ignoring: %m", x);
                                continue;
                        }
                        if (r < 0)
                                return r;

                        /* Try to reuse the original flag set */
                        orig_flags = 0;
                        (void) get_mount_flags(x, &orig_flags);
                        orig_flags &= ~MS_RDONLY;

                        if (mount(NULL, x, NULL, (orig_flags & ~flags_mask)|MS_BIND|MS_REMOUNT|new_flags, NULL) < 0)
                                return -errno;

                        log_debug("Remounted %s read-only.", x);
                }
        }
コード例 #22
0
ファイル: cgtop.c プロジェクト: g33s3/systemmd
static int group_compare(const void*a, const void *b) {
        const Group *x = *(Group**)a, *y = *(Group**)b;

        if (path_startswith(y->path, x->path))
                return -1;
        if (path_startswith(x->path, y->path))
                return 1;

        if (arg_order == ORDER_CPU) {
                if (arg_cpu_type == CPU_PERCENT) {
                        if (x->cpu_valid && y->cpu_valid) {
                                if (x->cpu_fraction > y->cpu_fraction)
                                        return -1;
                                else if (x->cpu_fraction < y->cpu_fraction)
                                        return 1;
                        } else if (x->cpu_valid)
                                return -1;
                        else if (y->cpu_valid)
                                return 1;
                } else {
                        if (x->cpu_usage > y->cpu_usage)
                                return -1;
                        else if (x->cpu_usage < y->cpu_usage)
                                return 1;
                }
        }

        if (arg_order == ORDER_TASKS) {

                if (x->n_tasks_valid && y->n_tasks_valid) {
                        if (x->n_tasks > y->n_tasks)
                                return -1;
                        else if (x->n_tasks < y->n_tasks)
                                return 1;
                } else if (x->n_tasks_valid)
                        return -1;
                else if (y->n_tasks_valid)
                        return 1;
        }

        if (arg_order == ORDER_MEMORY) {
                if (x->memory_valid && y->memory_valid) {
                        if (x->memory > y->memory)
                                return -1;
                        else if (x->memory < y->memory)
                                return 1;
                } else if (x->memory_valid)
                        return -1;
                else if (y->memory_valid)
                        return 1;
        }

        if (arg_order == ORDER_IO) {
                if (x->io_valid && y->io_valid) {
                        if (x->io_input_bps + x->io_output_bps > y->io_input_bps + y->io_output_bps)
                                return -1;
                        else if (x->io_input_bps + x->io_output_bps < y->io_input_bps + y->io_output_bps)
                                return 1;
                } else if (x->io_valid)
                        return -1;
                else if (y->io_valid)
                        return 1;
        }

        return strcmp(x->path, y->path);
}
コード例 #23
0
ファイル: sysfs-show.c プロジェクト: cee1/systemd
static int show_sysfs_one(
                struct udev *udev,
                const char *seat,
                struct udev_list_entry **item,
                const char *sub,
                const char *prefix,
                unsigned n_columns) {

        assert(udev);
        assert(seat);
        assert(item);
        assert(prefix);

        while (*item) {
                struct udev_list_entry *next, *lookahead;
                struct udev_device *d;
                const char *sn, *name, *sysfs, *subsystem, *sysname;
                char *l, *k;
                bool is_master;

                sysfs = udev_list_entry_get_name(*item);
                if (!path_startswith(sysfs, sub))
                        return 0;

                d = udev_device_new_from_syspath(udev, sysfs);
                if (!d) {
                        *item = udev_list_entry_get_next(*item);
                        continue;
                }

                sn = udev_device_get_property_value(d, "ID_SEAT");
                if (isempty(sn))
                        sn = "seat0";

                /* Explicitly also check for tag 'seat' here */
                if (!streq(seat, sn) || !udev_device_has_tag(d, "seat")) {
                        udev_device_unref(d);
                        *item = udev_list_entry_get_next(*item);
                        continue;
                }

                is_master = udev_device_has_tag(d, "seat-master");

                name = udev_device_get_sysattr_value(d, "name");
                if (!name)
                        name = udev_device_get_sysattr_value(d, "id");
                subsystem = udev_device_get_subsystem(d);
                sysname = udev_device_get_sysname(d);

                /* Look if there's more coming after this */
                lookahead = next = udev_list_entry_get_next(*item);
                while (lookahead) {
                        const char *lookahead_sysfs;

                        lookahead_sysfs = udev_list_entry_get_name(lookahead);

                        if (path_startswith(lookahead_sysfs, sub) &&
                            !path_startswith(lookahead_sysfs, sysfs)) {
                                struct udev_device *lookahead_d;

                                lookahead_d = udev_device_new_from_syspath(udev, lookahead_sysfs);
                                if (lookahead_d) {
                                        const char *lookahead_sn;
                                        bool found;

                                        lookahead_sn = udev_device_get_property_value(d, "ID_SEAT");
                                        if (isempty(lookahead_sn))
                                                lookahead_sn = "seat0";

                                        found = streq(seat, lookahead_sn) && udev_device_has_tag(lookahead_d, "seat");
                                        udev_device_unref(lookahead_d);

                                        if (found)
                                                break;
                                }
                        }

                        lookahead = udev_list_entry_get_next(lookahead);
                }

                k = ellipsize(sysfs, n_columns, 20);
                printf("%s%s%s\n", prefix, draw_special_char(lookahead ? DRAW_TREE_BRANCH : DRAW_TREE_RIGHT),
                                   k ? k : sysfs);
                free(k);

                if (asprintf(&l,
                             "%s%s:%s%s%s%s",
                             is_master ? "[MASTER] " : "",
                             subsystem, sysname,
                             name ? " \"" : "", name ? name : "", name ? "\"" : "") < 0) {
                        udev_device_unref(d);
                        return -ENOMEM;
                }

                k = ellipsize(l, n_columns, 70);
                printf("%s%s%s\n", prefix, lookahead ? draw_special_char(DRAW_TREE_VERT) : "  ",
                                   k ? k : l);
                free(k);
                free(l);

                *item = next;
                if (*item) {
                        char *p;

                        p = strappend(prefix, lookahead ? draw_special_char(DRAW_TREE_VERT) : "  ");
                        show_sysfs_one(udev, seat, item, sysfs, p ? p : prefix, n_columns - 2);
                        free(p);
                }

                udev_device_unref(d);
        }

        return 0;
}
コード例 #24
0
ファイル: cgls.c プロジェクト: banada/systemd
int main(int argc, char *argv[]) {
        int r = 0, retval = EXIT_FAILURE;
        int output_flags;

        log_parse_environment();
        log_open();

        r = parse_argv(argc, argv);
        if (r < 0)
                goto finish;
        else if (r == 0) {
                retval = EXIT_SUCCESS;
                goto finish;
        }

        if (!arg_no_pager) {
                r = pager_open(false);
                if (r > 0) {
                        if (arg_full == -1)
                                arg_full = true;
                }
        }

        output_flags =
                arg_all * OUTPUT_SHOW_ALL |
                (arg_full > 0) * OUTPUT_FULL_WIDTH;

        if (optind < argc) {
                unsigned i;

                for (i = (unsigned) optind; i < (unsigned) argc; i++) {
                        int q;
                        printf("%s:\n", argv[i]);

                        q = show_cgroup_by_path(argv[i], NULL, 0,
                                                arg_kernel_threads, output_flags);
                        if (q < 0)
                                r = q;
                }

        } else {
                char _cleanup_free_ *p;

                p = get_current_dir_name();
                if (!p) {
                        log_error("Cannot determine current working directory: %m");
                        goto finish;
                }

                if (path_startswith(p, "/sys/fs/cgroup")) {
                        printf("Working Directory %s:\n", p);
                        r = show_cgroup_by_path(p, NULL, 0,
                                                arg_kernel_threads, output_flags);
                } else {
                        char _cleanup_free_ *root = NULL;
                        const char *t = NULL;

                        r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 1, &root);
                        if (r < 0)
                                t = "/";
                        else {
                                if (endswith(root, "/system"))
                                        root[strlen(root)-7] = 0;

                                t = root[0] ? root : "/";
                        }

                        r = show_cgroup(SYSTEMD_CGROUP_CONTROLLER, t, NULL, 0,
                                        arg_kernel_threads, output_flags);
                }
        }

        if (r < 0)
                log_error("Failed to list cgroup tree: %s", strerror(-r));

        retval = EXIT_SUCCESS;

finish:
        pager_close();

        return retval;
}
コード例 #25
0
ファイル: journald-native.c プロジェクト: teg/systemd
void server_process_native_file(
                Server *s,
                int fd,
                const struct ucred *ucred,
                const struct timeval *tv,
                const char *label, size_t label_len) {

        struct stat st;
        bool sealed;
        int r;

        /* Data is in the passed fd, since it didn't fit in a
         * datagram. */

        assert(s);
        assert(fd >= 0);

        /* If it's a memfd, check if it is sealed. If so, we can just
         * use map it and use it, and do not need to copy the data
         * out. */
        sealed = memfd_get_sealed(fd) > 0;

        if (!sealed && (!ucred || ucred->uid != 0)) {
                _cleanup_free_ char *sl = NULL, *k = NULL;
                const char *e;

                /* If this is not a sealed memfd, and the peer is unknown or
                 * unprivileged, then verify the path. */

                if (asprintf(&sl, "/proc/self/fd/%i", fd) < 0) {
                        log_oom();
                        return;
                }

                r = readlink_malloc(sl, &k);
                if (r < 0) {
                        log_error_errno(r, "readlink(%s) failed: %m", sl);
                        return;
                }

                e = path_startswith(k, "/dev/shm/");
                if (!e)
                        e = path_startswith(k, "/tmp/");
                if (!e)
                        e = path_startswith(k, "/var/tmp/");
                if (!e) {
                        log_error("Received file outside of allowed directories. Refusing.");
                        return;
                }

                if (!filename_is_valid(e)) {
                        log_error("Received file in subdirectory of allowed directories. Refusing.");
                        return;
                }
        }

        if (fstat(fd, &st) < 0) {
                log_error_errno(errno, "Failed to stat passed file, ignoring: %m");
                return;
        }

        if (!S_ISREG(st.st_mode)) {
                log_error("File passed is not regular. Ignoring.");
                return;
        }

        if (st.st_size <= 0)
                return;

        if (st.st_size > ENTRY_SIZE_MAX) {
                log_error("File passed too large. Ignoring.");
                return;
        }

        if (sealed) {
                void *p;
                size_t ps;

                /* The file is sealed, we can just map it and use it. */

                ps = PAGE_ALIGN(st.st_size);
                p = mmap(NULL, ps, PROT_READ, MAP_PRIVATE, fd, 0);
                if (p == MAP_FAILED) {
                        log_error_errno(errno, "Failed to map memfd, ignoring: %m");
                        return;
                }

                server_process_native_message(s, p, st.st_size, ucred, tv, label, label_len);
                assert_se(munmap(p, ps) >= 0);
        } else {
                _cleanup_free_ void *p = NULL;
                struct statvfs vfs;
                ssize_t n;

                if (fstatvfs(fd, &vfs) < 0) {
                        log_error_errno(errno, "Failed to stat file system of passed file, ignoring: %m");
                        return;
                }

                /* Refuse operating on file systems that have
                 * mandatory locking enabled, see:
                 *
                 * https://github.com/systemd/systemd/issues/1822
                 */
                if (vfs.f_flag & ST_MANDLOCK) {
                        log_error("Received file descriptor from file system with mandatory locking enable, refusing.");
                        return;
                }

                /* Make the fd non-blocking. On regular files this has
                 * the effect of bypassing mandatory locking. Of
                 * course, this should normally not be necessary given
                 * the check above, but let's better be safe than
                 * sorry, after all NFS is pretty confusing regarding
                 * file system flags, and we better don't trust it,
                 * and so is SMB. */
                r = fd_nonblock(fd, true);
                if (r < 0) {
                        log_error_errno(r, "Failed to make fd non-blocking, ignoring: %m");
                        return;
                }

                /* The file is not sealed, we can't map the file here, since
                 * clients might then truncate it and trigger a SIGBUS for
                 * us. So let's stupidly read it */

                p = malloc(st.st_size);
                if (!p) {
                        log_oom();
                        return;
                }

                n = pread(fd, p, st.st_size, 0);
                if (n < 0)
                        log_error_errno(errno, "Failed to read file, ignoring: %m");
                else if (n > 0)
                        server_process_native_message(s, p, n, ucred, tv, label, label_len);
        }
}
コード例 #26
0
static int group_compare(const void*a, const void *b) {
        const Group *x = *(Group**)a, *y = *(Group**)b;

        if (arg_order != ORDER_TASKS || arg_recursive) {
                /* Let's make sure that the parent is always before
                 * the child. Except when ordering by tasks and
                 * recursive summing is off, since that is actually
                 * not accumulative for all children. */

                if (path_startswith(y->path, x->path))
                        return -1;
                if (path_startswith(x->path, y->path))
                        return 1;
        }

        switch (arg_order) {

        case ORDER_PATH:
                break;

        case ORDER_CPU:
                if (arg_cpu_type == CPU_PERCENT) {
                        if (x->cpu_valid && y->cpu_valid) {
                                if (x->cpu_fraction > y->cpu_fraction)
                                        return -1;
                                else if (x->cpu_fraction < y->cpu_fraction)
                                        return 1;
                        } else if (x->cpu_valid)
                                return -1;
                        else if (y->cpu_valid)
                                return 1;
                } else {
                        if (x->cpu_usage > y->cpu_usage)
                                return -1;
                        else if (x->cpu_usage < y->cpu_usage)
                                return 1;
                }

                break;

        case ORDER_TASKS:
                if (x->n_tasks_valid && y->n_tasks_valid) {
                        if (x->n_tasks > y->n_tasks)
                                return -1;
                        else if (x->n_tasks < y->n_tasks)
                                return 1;
                } else if (x->n_tasks_valid)
                        return -1;
                else if (y->n_tasks_valid)
                        return 1;

                break;

        case ORDER_MEMORY:
                if (x->memory_valid && y->memory_valid) {
                        if (x->memory > y->memory)
                                return -1;
                        else if (x->memory < y->memory)
                                return 1;
                } else if (x->memory_valid)
                        return -1;
                else if (y->memory_valid)
                        return 1;

                break;

        case ORDER_IO:
                if (x->io_valid && y->io_valid) {
                        if (x->io_input_bps + x->io_output_bps > y->io_input_bps + y->io_output_bps)
                                return -1;
                        else if (x->io_input_bps + x->io_output_bps < y->io_input_bps + y->io_output_bps)
                                return 1;
                } else if (x->io_valid)
                        return -1;
                else if (y->io_valid)
                        return 1;
        }

        return path_compare(x->path, y->path);
}
コード例 #27
0
int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignment) {
        const char *eq, *field;
        int r;

        assert(m);
        assert(assignment);

        eq = strchr(assignment, '=');
        if (!eq) {
                log_error("Not an assignment: %s", assignment);
                return -EINVAL;
        }

        field = strndupa(assignment, eq - assignment);
        eq ++;

        if (streq(field, "CPUQuota")) {

                if (isempty(eq)) {

                        r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
                        if (r < 0)
                                return bus_log_create_error(r);

                        r = sd_bus_message_append(m, "v", "t", USEC_INFINITY);

                } else if (endswith(eq, "%")) {
                        double percent;

                        if (sscanf(eq, "%lf%%", &percent) != 1 || percent <= 0) {
                                log_error("CPU quota '%s' invalid.", eq);
                                return -EINVAL;
                        }

                        r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
                        if (r < 0)
                                return bus_log_create_error(r);

                        r = sd_bus_message_append(m, "v", "t", (usec_t) percent * USEC_PER_SEC / 100);
                } else {
                        log_error("CPU quota needs to be in percent.");
                        return -EINVAL;
                }

                if (r < 0)
                        return bus_log_create_error(r);

                return 0;
        }

        r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
        if (r < 0)
                return bus_log_create_error(r);

        if (STR_IN_SET(field,
                       "CPUAccounting", "MemoryAccounting", "BlockIOAccounting",
                       "SendSIGHUP", "SendSIGKILL")) {

                r = parse_boolean(eq);
                if (r < 0) {
                        log_error("Failed to parse boolean assignment %s.", assignment);
                        return -EINVAL;
                }

                r = sd_bus_message_append(m, "v", "b", r);

        } else if (streq(field, "MemoryLimit")) {
                off_t bytes;

                r = parse_size(eq, 1024, &bytes);
                if (r < 0) {
                        log_error("Failed to parse bytes specification %s", assignment);
                        return -EINVAL;
                }

                r = sd_bus_message_append(m, "v", "t", (uint64_t) bytes);

        } else if (STR_IN_SET(field, "CPUShares", "BlockIOWeight")) {
                uint64_t u;

                r = safe_atou64(eq, &u);
                if (r < 0) {
                        log_error("Failed to parse %s value %s.", field, eq);
                        return -EINVAL;
                }

                r = sd_bus_message_append(m, "v", "t", u);

        } else if (STR_IN_SET(field, "User", "Group", "DevicePolicy", "KillMode"))
                r = sd_bus_message_append(m, "v", "s", eq);

        else if (streq(field, "DeviceAllow")) {

                if (isempty(eq))
                        r = sd_bus_message_append(m, "v", "a(ss)", 0);
                else {
                        const char *path, *rwm, *e;

                        e = strchr(eq, ' ');
                        if (e) {
                                path = strndupa(eq, e - eq);
                                rwm = e+1;
                        } else {
                                path = eq;
                                rwm = "";
                        }

                        if (!path_startswith(path, "/dev")) {
                                log_error("%s is not a device file in /dev.", path);
                                return -EINVAL;
                        }

                        r = sd_bus_message_append(m, "v", "a(ss)", 1, path, rwm);
                }

        } else if (STR_IN_SET(field, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {

                if (isempty(eq))
                        r = sd_bus_message_append(m, "v", "a(st)", 0);
                else {
                        const char *path, *bandwidth, *e;
                        off_t bytes;

                        e = strchr(eq, ' ');
                        if (e) {
                                path = strndupa(eq, e - eq);
                                bandwidth = e+1;
                        } else {
                                log_error("Failed to parse %s value %s.", field, eq);
                                return -EINVAL;
                        }

                        if (!path_startswith(path, "/dev")) {
                                log_error("%s is not a device file in /dev.", path);
                                return -EINVAL;
                        }

                        r = parse_size(bandwidth, 1000, &bytes);
                        if (r < 0) {
                                log_error("Failed to parse byte value %s.", bandwidth);
                                return -EINVAL;
                        }

                        r = sd_bus_message_append(m, "v", "a(st)", 1, path, (uint64_t) bytes);
                }

        } else if (streq(field, "BlockIODeviceWeight")) {

                if (isempty(eq))
                        r = sd_bus_message_append(m, "v", "a(st)", 0);
                else {
                        const char *path, *weight, *e;
                        uint64_t u;

                        e = strchr(eq, ' ');
                        if (e) {
                                path = strndupa(eq, e - eq);
                                weight = e+1;
                        } else {
                                log_error("Failed to parse %s value %s.", field, eq);
                                return -EINVAL;
                        }

                        if (!path_startswith(path, "/dev")) {
                                log_error("%s is not a device file in /dev.", path);
                                return -EINVAL;
                        }

                        r = safe_atou64(weight, &u);
                        if (r < 0) {
                                log_error("Failed to parse %s value %s.", field, weight);
                                return -EINVAL;
                        }
                        r = sd_bus_message_append(m, "v", "a(st)", path, u);
                }

        } else if (rlimit_from_string(field) >= 0) {
                uint64_t rl;

                if (streq(eq, "infinity"))
                        rl = (uint64_t) -1;
                else {
                        r = safe_atou64(eq, &rl);
                        if (r < 0) {
                                log_error("Invalid resource limit: %s", eq);
                                return -EINVAL;
                        }
                }

                r = sd_bus_message_append(m, "v", "t", rl);

        } else if (streq(field, "Nice")) {
                int32_t i;

                r = safe_atoi32(eq, &i);
                if (r < 0) {
                        log_error("Failed to parse %s value %s.", field, eq);
                        return -EINVAL;
                }

                r = sd_bus_message_append(m, "v", "i", i);

        } else if (streq(field, "Environment")) {

                r = sd_bus_message_append(m, "v", "as", 1, eq);

        } else if (streq(field, "KillSignal")) {
                int sig;

                sig = signal_from_string_try_harder(eq);
                if (sig < 0) {
                        log_error("Failed to parse %s value %s.", field, eq);
                        return -EINVAL;
                }

                r = sd_bus_message_append(m, "v", "i", sig);

        } else {
                log_error("Unknown assignment %s.", assignment);
                return -EINVAL;
        }

        if (r < 0)
                return bus_log_create_error(r);

        return 0;
}
コード例 #28
0
ファイル: cgls.c プロジェクト: AlexBaranosky/systemd
int main(int argc, char *argv[]) {
        int r = 0, retval = EXIT_FAILURE;
        int output_flags;
        _cleanup_free_ char *root = NULL;
        _cleanup_bus_close_unref_ sd_bus *bus = NULL;

        log_parse_environment();
        log_open();

        r = parse_argv(argc, argv);
        if (r < 0)
                goto finish;
        else if (r == 0) {
                retval = EXIT_SUCCESS;
                goto finish;
        }

        if (!arg_no_pager) {
                r = pager_open(false);
                if (r > 0) {
                        if (arg_full == -1)
                                arg_full = true;
                }
        }

        output_flags =
                arg_all * OUTPUT_SHOW_ALL |
                (arg_full > 0) * OUTPUT_FULL_WIDTH;

        r = bus_open_transport(BUS_TRANSPORT_LOCAL, NULL, false, &bus);
        if (r < 0) {
                log_error_errno(r, "Failed to create bus connection: %m");
                goto finish;
        }

        if (optind < argc) {
                int i;

                for (i = optind; i < argc; i++) {
                        int q;

                        fprintf(stdout, "%s:\n", argv[i]);
                        fflush(stdout);

                        if (arg_machine)
                                root = strjoin("machine/", arg_machine, "/", argv[i], NULL);
                        else
                                root = strdup(argv[i]);
                        if (!root)
                                return log_oom();

                        q = show_cgroup_by_path(root, NULL, 0,
                                                arg_kernel_threads, output_flags);
                        if (q < 0)
                                r = q;
                }

        } else {
                _cleanup_free_ char *p;

                p = get_current_dir_name();
                if (!p) {
                        log_error_errno(errno, "Cannot determine current working directory: %m");
                        goto finish;
                }

                if (path_startswith(p, "/sys/fs/cgroup") && !arg_machine) {
                        printf("Working Directory %s:\n", p);
                        r = show_cgroup_by_path(p, NULL, 0,
                                                arg_kernel_threads, output_flags);
                } else {
                        if (arg_machine) {
                                char *m;
                                const char *cgroup;
                                _cleanup_free_ char *scope = NULL;
                                _cleanup_free_ char *path = NULL;
                                _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
                                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;

                                m = strjoina("/run/systemd/machines/", arg_machine);
                                r = parse_env_file(m, NEWLINE, "SCOPE", &scope, NULL);
                                if (r < 0) {
                                        log_error_errno(r, "Failed to get machine path: %m");
                                        goto finish;
                                }

                                path = unit_dbus_path_from_name(scope);
                                if (!path) {
                                        log_oom();
                                        goto finish;
                                }

                                r = sd_bus_get_property(
                                                bus,
                                                "org.freedesktop.systemd1",
                                                path,
                                                "org.freedesktop.systemd1.Scope",
                                                "ControlGroup",
                                                &error,
                                                &reply,
                                                "s");

                                if (r < 0) {
                                        log_error("Failed to query ControlGroup: %s", bus_error_message(&error, -r));
                                        goto finish;
                                }

                                r = sd_bus_message_read(reply, "s", &cgroup);
                                if (r < 0) {
                                        bus_log_parse_error(r);
                                        goto finish;
                                }

                                root = strdup(cgroup);
                                if (!root) {
                                        log_oom();
                                        goto finish;
                                }

                        } else
                                r = cg_get_root_path(&root);
                        if (r < 0) {
                                log_error_errno(r, "Failed to get %s path: %m",
                                                arg_machine ? "machine" : "root");
                                goto finish;
                        }

                        r = show_cgroup(SYSTEMD_CGROUP_CONTROLLER, root, NULL, 0,
                                        arg_kernel_threads, output_flags);
                }
        }

        if (r < 0) {
                log_error_errno(r, "Failed to list cgroup tree %s: %m", root);
                retval = EXIT_FAILURE;
        } else
                retval = EXIT_SUCCESS;

finish:
        pager_close();

        return retval;
}
コード例 #29
0
ファイル: machine-image.c プロジェクト: Keruspe/systemd
static int image_make(
                const char *pretty,
                int dfd,
                const char *path,
                const char *filename,
                const struct stat *st,
                Image **ret) {

        _cleanup_free_ char *pretty_buffer = NULL;
        struct stat stbuf;
        bool read_only;
        int r;

        assert(dfd >= 0 || dfd == AT_FDCWD);
        assert(filename);

        /* We explicitly *do* follow symlinks here, since we want to allow symlinking trees, raw files and block
         * devices into /var/lib/machines/, and treat them normally.
         *
         * This function returns -ENOENT if we can't find the image after all, and -EMEDIUMTYPE if it's not a file we
         * recognize. */

        if (!st) {
                if (fstatat(dfd, filename, &stbuf, 0) < 0)
                        return -errno;

                st = &stbuf;
        }

        read_only =
                (path && path_startswith(path, "/usr")) ||
                (faccessat(dfd, filename, W_OK, AT_EACCESS) < 0 && errno == EROFS);

        if (S_ISDIR(st->st_mode)) {
                _cleanup_close_ int fd = -1;
                unsigned file_attr = 0;

                if (!ret)
                        return 0;

                if (!pretty) {
                        r = extract_pretty(filename, NULL, &pretty_buffer);
                        if (r < 0)
                                return r;

                        pretty = pretty_buffer;
                }

                fd = openat(dfd, filename, O_CLOEXEC|O_NOCTTY|O_DIRECTORY);
                if (fd < 0)
                        return -errno;

                /* btrfs subvolumes have inode 256 */
                if (st->st_ino == 256) {

                        r = btrfs_is_filesystem(fd);
                        if (r < 0)
                                return r;
                        if (r) {
                                BtrfsSubvolInfo info;

                                /* It's a btrfs subvolume */

                                r = btrfs_subvol_get_info_fd(fd, 0, &info);
                                if (r < 0)
                                        return r;

                                r = image_new(IMAGE_SUBVOLUME,
                                              pretty,
                                              path,
                                              filename,
                                              info.read_only || read_only,
                                              info.otime,
                                              0,
                                              ret);
                                if (r < 0)
                                        return r;

                                if (btrfs_quota_scan_ongoing(fd) == 0) {
                                        BtrfsQuotaInfo quota;

                                        r = btrfs_subvol_get_subtree_quota_fd(fd, 0, &quota);
                                        if (r >= 0) {
                                                (*ret)->usage = quota.referenced;
                                                (*ret)->usage_exclusive = quota.exclusive;

                                                (*ret)->limit = quota.referenced_max;
                                                (*ret)->limit_exclusive = quota.exclusive_max;
                                        }
                                }

                                return 0;
                        }
                }

                /* If the IMMUTABLE bit is set, we consider the
                 * directory read-only. Since the ioctl is not
                 * supported everywhere we ignore failures. */
                (void) read_attr_fd(fd, &file_attr);

                /* It's just a normal directory. */
                r = image_new(IMAGE_DIRECTORY,
                              pretty,
                              path,
                              filename,
                              read_only || (file_attr & FS_IMMUTABLE_FL),
                              0,
                              0,
                              ret);
                if (r < 0)
                        return r;

                return 0;

        } else if (S_ISREG(st->st_mode) && endswith(filename, ".raw")) {
                usec_t crtime = 0;

                /* It's a RAW disk image */

                if (!ret)
                        return 0;

                (void) fd_getcrtime_at(dfd, filename, &crtime, 0);

                if (!pretty) {
                        r = extract_pretty(filename, ".raw", &pretty_buffer);
                        if (r < 0)
                                return r;

                        pretty = pretty_buffer;
                }

                r = image_new(IMAGE_RAW,
                              pretty,
                              path,
                              filename,
                              !(st->st_mode & 0222) || read_only,
                              crtime,
                              timespec_load(&st->st_mtim),
                              ret);
                if (r < 0)
                        return r;

                (*ret)->usage = (*ret)->usage_exclusive = st->st_blocks * 512;
                (*ret)->limit = (*ret)->limit_exclusive = st->st_size;

                return 0;

        } else if (S_ISBLK(st->st_mode)) {
                _cleanup_close_ int block_fd = -1;
                uint64_t size = UINT64_MAX;

                /* A block device */

                if (!ret)
                        return 0;

                if (!pretty) {
                        r = extract_pretty(filename, NULL, &pretty_buffer);
                        if (r < 0)
                                return r;

                        pretty = pretty_buffer;
                }

                block_fd = openat(dfd, filename, O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY);
                if (block_fd < 0)
                        log_debug_errno(errno, "Failed to open block device %s/%s, ignoring: %m", path, filename);
                else {
                        /* Refresh stat data after opening the node */
                        if (fstat(block_fd, &stbuf) < 0)
                                return -errno;
                        st = &stbuf;

                        if (!S_ISBLK(st->st_mode)) /* Verify that what we opened is actually what we think it is */
                                return -ENOTTY;

                        if (!read_only) {
                                int state = 0;

                                if (ioctl(block_fd, BLKROGET, &state) < 0)
                                        log_debug_errno(errno, "Failed to issue BLKROGET on device %s/%s, ignoring: %m", path, filename);
                                else if (state)
                                        read_only = true;
                        }

                        if (ioctl(block_fd, BLKGETSIZE64, &size) < 0)
                                log_debug_errno(errno, "Failed to issue BLKGETSIZE64 on device %s/%s, ignoring: %m", path, filename);

                        block_fd = safe_close(block_fd);
                }

                r = image_new(IMAGE_BLOCK,
                              pretty,
                              path,
                              filename,
                              !(st->st_mode & 0222) || read_only,
                              0,
                              0,
                              ret);
                if (r < 0)
                        return r;

                if (size != 0 && size != UINT64_MAX)
                        (*ret)->usage = (*ret)->usage_exclusive = (*ret)->limit = (*ret)->limit_exclusive = size;

                return 0;
        }

        return -EMEDIUMTYPE;
}
コード例 #30
0
ファイル: udevadm-test-builtin.c プロジェクト: Werkov/systemd
static int adm_builtin(struct udev *udev, int argc, char *argv[]) {
        static const struct option options[] = {
                { "version", no_argument, NULL, 'V' },
                { "help",    no_argument, NULL, 'h' },
                {}
        };
        char *command = NULL;
        char *syspath = NULL;
        char filename[UTIL_PATH_SIZE];
        struct udev_device *dev = NULL;
        enum udev_builtin_cmd cmd;
        int rc = EXIT_SUCCESS, c;

        while ((c = getopt_long(argc, argv, "Vh", options, NULL)) >= 0)
                switch (c) {
                case 'V':
                        print_version();
                        goto out;
                case 'h':
                        help(udev);
                        goto out;
                }

        command = argv[optind++];
        if (command == NULL) {
                fprintf(stderr, "command missing\n");
                help(udev);
                rc = 2;
                goto out;
        }

        syspath = argv[optind++];
        if (syspath == NULL) {
                fprintf(stderr, "syspath missing\n");
                rc = 3;
                goto out;
        }

        udev_builtin_init(udev);

        cmd = udev_builtin_lookup(command);
        if (cmd >= UDEV_BUILTIN_MAX) {
                fprintf(stderr, "unknown command '%s'\n", command);
                help(udev);
                rc = 5;
                goto out;
        }

        /* add /sys if needed */
        if (!path_startswith(syspath, "/sys"))
                strscpyl(filename, sizeof(filename), "/sys", syspath, NULL);
        else
                strscpy(filename, sizeof(filename), syspath);
        delete_trailing_chars(filename, "/");

        dev = udev_device_new_from_syspath(udev, filename);
        if (dev == NULL) {
                fprintf(stderr, "unable to open device '%s'\n\n", filename);
                rc = 4;
                goto out;
        }

        rc = udev_builtin_run(dev, cmd, command, true);
        if (rc < 0) {
                fprintf(stderr, "error executing '%s', exit code %i\n\n", command, rc);
                rc = 6;
        }
out:
        udev_device_unref(dev);
        udev_builtin_exit(udev);
        return rc;
}