Пример #1
0
/*
 * Given a bdev (presumably blockdev-based), detect the fstype
 * by trying mounting (in a private mntns) it.
 * @bdev: bdev to investigate
 * @type: preallocated char* in which to write the fstype
 * @len: length of passed in char*
 * Returns length of fstype, of -1 on error
 */
static int detect_fs(struct bdev *bdev, char *type, int len)
{
	int  p[2], ret;
	size_t linelen;
	pid_t pid;
	FILE *f;
	char *sp1, *sp2, *sp3, *line = NULL;

	if (!bdev || !bdev->src || !bdev->dest)
		return -1;

	if (pipe(p) < 0)
		return -1;
	if ((pid = fork()) < 0)
		return -1;
	if (pid > 0) {
		int status;
		close(p[1]);
		memset(type, 0, len);
		ret = read(p[0], type, len-1);
		close(p[0]);
		if (ret < 0) {
			SYSERROR("error reading from pipe");
			wait(&status);
			return -1;
		} else if (ret == 0) {
			ERROR("child exited early - fstype not found");
			wait(&status);
			return -1;
		}
		wait(&status);
		type[len-1] = '\0';
		INFO("detected fstype %s for %s", type, bdev->src);
		return ret;
	}

	if (unshare(CLONE_NEWNS) < 0)
		exit(1);

	ret = mount_unknow_fs(bdev->src, bdev->dest, 0);
	if (ret < 0) {
		ERROR("failed mounting %s onto %s to detect fstype", bdev->src, bdev->dest);
		exit(1);
	}
	// if symlink, get the real dev name
	char devpath[MAXPATHLEN];
	char *l = linkderef(bdev->src, devpath);
	if (!l)
		exit(1);
	f = fopen("/proc/self/mounts", "r");
	if (!f)
		exit(1);
	while (getline(&line, &linelen, f) != -1) {
		sp1 = index(line, ' ');
		if (!sp1)
			exit(1);
		*sp1 = '\0';
		if (strcmp(line, l))
			continue;
		sp2 = index(sp1+1, ' ');
		if (!sp2)
			exit(1);
		*sp2 = '\0';
		sp3 = index(sp2+1, ' ');
		if (!sp3)
			exit(1);
		*sp3 = '\0';
		sp2++;
		if (write(p[1], sp2, strlen(sp2)) != strlen(sp2))
			exit(1);
		exit(0);
	}
	exit(1);
}
Пример #2
0
/*
 * Given a lxc_storage (presumably blockdev-based), detect the fstype
 * by trying mounting (in a private mntns) it.
 * @lxc_storage: bdev to investigate
 * @type: preallocated char* in which to write the fstype
 * @len: length of passed in char*
 * Returns length of fstype, of -1 on error
 */
int detect_fs(struct lxc_storage *bdev, char *type, int len)
{
	int ret;
	int p[2];
	size_t linelen;
	pid_t pid;
	FILE *f;
	char *sp1, *sp2, *sp3;
	const char *l, *srcdev;
	char devpath[PATH_MAX];
	char *line = NULL;

	if (!bdev || !bdev->src || !bdev->dest)
		return -1;

	srcdev = lxc_storage_get_path(bdev->src, bdev->type);

	ret = pipe(p);
	if (ret < 0) {
		SYSERROR("Failed to create pipe");
		return -1;
	}

	pid = fork();
	if (pid < 0) {
		SYSERROR("Failed to fork process");
		return -1;
	}

	if (pid > 0) {
		int status;

		close(p[1]);
		memset(type, 0, len);

		ret = read(p[0], type, len - 1);
		if (ret < 0) {
			SYSERROR("Failed to read FSType from pipe");
		} else if (ret == 0) {
			ERROR("FSType not found - child exited early");
			ret = -1;
		}

		close(p[0]);
		wait(&status);

		if (ret < 0)
			return ret;

		type[len - 1] = '\0';
		INFO("Detected FSType \"%s\" for \"%s\"", type, srcdev);

		return ret;
	}

	if (unshare(CLONE_NEWNS) < 0)
		_exit(EXIT_FAILURE);

	if (detect_shared_rootfs())
		if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL)) {
			SYSERROR("Failed to make / rslave");
			ERROR("Continuing...");
		}

	ret = mount_unknown_fs(srcdev, bdev->dest, bdev->mntopts);
	if (ret < 0) {
		ERROR("Failed to mount \"%s\" onto \"%s\" to detect FSType", srcdev,
		      bdev->dest);
		_exit(EXIT_FAILURE);
	}

	l = linkderef(srcdev, devpath);
	if (!l)
		_exit(EXIT_FAILURE);

	f = fopen("/proc/self/mounts", "r");
	if (!f)
		_exit(EXIT_FAILURE);

	while (getline(&line, &linelen, f) != -1) {
		sp1 = strchr(line, ' ');
		if (!sp1)
			_exit(EXIT_FAILURE);

		*sp1 = '\0';
		if (strcmp(line, l))
			continue;

		sp2 = strchr(sp1 + 1, ' ');
		if (!sp2)
			_exit(EXIT_FAILURE);
		*sp2 = '\0';

		sp3 = strchr(sp2 + 1, ' ');
		if (!sp3)
			_exit(EXIT_FAILURE);
		*sp3 = '\0';

		sp2++;
		if (write(p[1], sp2, strlen(sp2)) != strlen(sp2))
			_exit(EXIT_FAILURE);

		_exit(EXIT_SUCCESS);
	}

	_exit(EXIT_FAILURE);
}
Пример #3
0
/*
 * Given a lxc_storage (presumably blockdev-based), detect the fstype
 * by trying mounting (in a private mntns) it.
 * @lxc_storage: bdev to investigate
 * @type: preallocated char* in which to write the fstype
 * @len: length of passed in char*
 * Returns length of fstype, of -1 on error
 */
int detect_fs(struct lxc_storage *bdev, char *type, int len)
{
	int ret;
	int p[2];
	size_t linelen;
	pid_t pid;
	FILE *f;
	char *sp1, *sp2, *sp3;
	const char *l, *srcdev;
	char devpath[PATH_MAX];
	char *line = NULL;

	if (!bdev || !bdev->src || !bdev->dest)
		return -1;

	srcdev = lxc_storage_get_path(bdev->src, bdev->type);

	ret = pipe(p);
	if (ret < 0)
		return -1;

	if ((pid = fork()) < 0)
		return -1;

	if (pid > 0) {
		int status;
		close(p[1]);
		memset(type, 0, len);
		ret = read(p[0], type, len - 1);
		close(p[0]);
		if (ret < 0) {
			SYSERROR("error reading from pipe");
			wait(&status);
			return -1;
		} else if (ret == 0) {
			ERROR("child exited early - fstype not found");
			wait(&status);
			return -1;
		}
		wait(&status);
		type[len - 1] = '\0';
		INFO("detected fstype %s for %s", type, srcdev);
		return ret;
	}

	if (unshare(CLONE_NEWNS) < 0)
		exit(1);

	if (detect_shared_rootfs()) {
		if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL)) {
			SYSERROR("Failed to make / rslave");
			ERROR("Continuing...");
		}
	}

	ret = mount_unknown_fs(srcdev, bdev->dest, bdev->mntopts);
	if (ret < 0) {
		ERROR("failed mounting %s onto %s to detect fstype", srcdev,
		      bdev->dest);
		exit(1);
	}

	l = linkderef(srcdev, devpath);
	if (!l)
		exit(1);
	f = fopen("/proc/self/mounts", "r");
	if (!f)
		exit(1);

	while (getline(&line, &linelen, f) != -1) {
		sp1 = strchr(line, ' ');
		if (!sp1)
			exit(1);
		*sp1 = '\0';
		if (strcmp(line, l))
			continue;
		sp2 = strchr(sp1 + 1, ' ');
		if (!sp2)
			exit(1);
		*sp2 = '\0';
		sp3 = strchr(sp2 + 1, ' ');
		if (!sp3)
			exit(1);
		*sp3 = '\0';
		sp2++;
		if (write(p[1], sp2, strlen(sp2)) != strlen(sp2))
			exit(1);

		exit(0);
	}

	exit(1);
}