Ejemplo n.º 1
0
static int check_btrfs(void) {
        struct statfs sfs;

        if (statfs("/var/lib/machines", &sfs) < 0) {
                if (errno != ENOENT)
                        return -errno;

                if (statfs("/var/lib", &sfs) < 0)
                        return -errno;
        }

        return F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC);
}
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) {
                        struct statfs sfs;

                        if (fstatfs(fd, &sfs) < 0)
                                return -errno;

                        if (F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC)) {
                                BtrfsSubvolInfo info;
                                BtrfsQuotaInfo quota;

                                /* It's a btrfs subvolume */

                                r = btrfs_subvol_get_info_fd(fd, &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;

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

                                        (*ret)->limit = quota.referred_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;
}
Ejemplo n.º 3
0
static int switchroot(const char *newroot)
{
	/*  Don't try to unmount the old "/", there's no way to do it. */
	const char *umounts[] = { "/dev", "/proc", "/sys", "/run", NULL };
	int i;
	int cfd;
	pid_t pid;
	struct stat newroot_stat, sb;

	if (stat(newroot, &newroot_stat) != 0) {
		warn(_("stat failed %s"), newroot);
		return -1;
	}

	for (i = 0; umounts[i] != NULL; i++) {
		char newmount[PATH_MAX];

		snprintf(newmount, sizeof(newmount), "%s%s", newroot, umounts[i]);

		if ((stat(newmount, &sb) != 0) || (sb.st_dev != newroot_stat.st_dev)) {
			/* mount point seems to be mounted already or stat failed */
			umount2(umounts[i], MNT_DETACH);
			continue;
		}

		if (mount(umounts[i], newmount, NULL, MS_MOVE, NULL) < 0) {
			warn(_("failed to mount moving %s to %s"),
				umounts[i], newmount);
			warnx(_("forcing unmount of %s"), umounts[i]);
			umount2(umounts[i], MNT_FORCE);
		}
	}

	if (chdir(newroot)) {
		warn(_("failed to change directory to %s"), newroot);
		return -1;
	}

	cfd = open("/", O_RDONLY);
	if (cfd < 0) {
		warn(_("cannot open %s"), "/");
		return -1;
	}

	if (mount(newroot, "/", NULL, MS_MOVE, NULL) < 0) {
		close(cfd);
		warn(_("failed to mount moving %s to /"), newroot);
		return -1;
	}

	if (chroot(".")) {
		close(cfd);
		warn(_("failed to change root"));
		return -1;
	}

	if (cfd >= 0) {
		pid = fork();
		if (pid <= 0) {
			struct statfs stfs;
			if (fstatfs(cfd, &stfs) == 0 &&
			    (F_TYPE_EQUAL(stfs.f_type, STATFS_RAMFS_MAGIC) ||
			     F_TYPE_EQUAL(stfs.f_type, STATFS_TMPFS_MAGIC)))
				recursiveRemove(cfd);
			else
				warn(_("old root filesystem is not an initramfs"));

			if (pid == 0)
				exit(EXIT_SUCCESS);
		}
		close(cfd);
	}
	return 0;
}
Ejemplo n.º 4
0
bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) {
        assert(s);
        assert_cc(sizeof(statfs_f_type_t) >= sizeof(s->f_type));

        return F_TYPE_EQUAL(s->f_type, magic_value);
}