All of lore.kernel.org
 help / color / mirror / Atom feed
From: Octavian Purdila <octavian.purdila@intel.com>
To: linux-arch@vger.kernel.org
Cc: linux-kernel@vger.kernel.org, thehajime@gmail.com,
	Octavian Purdila <octavian.purdila@intel.com>
Subject: [RFC PATCH 24/28] lkl tools: tool that reads/writes to/from a filesystem image
Date: Tue,  3 Nov 2015 22:20:55 +0200	[thread overview]
Message-ID: <1446582059-17355-25-git-send-email-octavian.purdila@intel.com> (raw)
In-Reply-To: <1446582059-17355-1-git-send-email-octavian.purdila@intel.com>

Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
---
 tools/lkl/.gitignore |   2 +
 tools/lkl/Makefile   |   6 +-
 tools/lkl/cptofs.c   | 467 +++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 474 insertions(+), 1 deletion(-)
 create mode 100644 tools/lkl/cptofs.c

diff --git a/tools/lkl/.gitignore b/tools/lkl/.gitignore
index a345a79..1048323 100644
--- a/tools/lkl/.gitignore
+++ b/tools/lkl/.gitignore
@@ -1,2 +1,4 @@
 test/boot
 fs2tar
+cptofs
+cpfromfs
diff --git a/tools/lkl/Makefile b/tools/lkl/Makefile
index 9aeab49..4084609 100644
--- a/tools/lkl/Makefile
+++ b/tools/lkl/Makefile
@@ -12,11 +12,13 @@ ifneq (,$(filter $(shell $(LD) -r -print-output-format),elf64-x86-64 elf32-i386)
 source += $(wildcard *.c)
 lib_source += lib/posix-host.c
 LDFLAGS += -lpthread -lrt
+source += $(wildcard *.c)
+execs =  cpfromfs
 endif
 
 lib_objs = $(patsubst %.c,%.o, $(lib_source)) lib/lkl.o
 objs = $(patsubst %.c,%.o, $(source))
-execs = $(patsubst %.c,%, $(source))
+execs += $(patsubst %.c,%, $(source))
 
 all: lib/liblkl.a $(execs)
 
@@ -38,3 +40,5 @@ clean:
 	-rm -rf include/lkl/ lib/liblkl.a $(lib_objs) $(objs) $(execs)
 
 fs2tar: LDFLAGS += -larchive
+cpfromfs: cptofs
+	if ! [ -e $@ ]; then ln -s $< $@; fi
diff --git a/tools/lkl/cptofs.c b/tools/lkl/cptofs.c
new file mode 100644
index 0000000..0017395
--- /dev/null
+++ b/tools/lkl/cptofs.c
@@ -0,0 +1,467 @@
+#include <stdio.h>
+#include <time.h>
+#include <argp.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <libgen.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <fnmatch.h>
+#undef st_atime
+#undef st_mtime
+#undef st_ctime
+#include <dirent.h>
+#include <lkl.h>
+#include <lkl_host.h>
+
+static const char doc_cptofs[] = "Copy files to a filesystem image";
+static const char doc_cpfromfs[] = "Copy files from a filesystem image";
+static const char args_doc_cptofs[] = "-t fstype -i fsimage path fs_path";
+static const char args_doc_cpfromfs[] = "-t fstype -i fsimage fs_path path";
+
+static struct argp_option options[] = {
+	{"enable-printk", 'p', 0, 0, "show Linux printks"},
+	{"filesystem-type", 't', "string", 0,
+	 "select filesystem type - mandatory"},
+	{"filesystem-image", 'i', "string", 0,
+	 "path to the filesystem image - mandatory"},
+	{"selinux", 's', "string", 0, "selinux attributes for destination"},
+	{0},
+};
+
+static struct cl_args {
+	int printk;
+	const char *fsimg_type;
+	const char *fsimg_path;
+	const char *src_path;
+	const char *dst_path;
+	const char *selinux;
+} cla;
+
+static int cptofs;
+
+static error_t parse_opt(int key, char *arg, struct argp_state *state)
+{
+	struct cl_args *cla = state->input;
+
+	switch (key) {
+	case 'p':
+		cla->printk = 1;
+		break;
+	case 't':
+		cla->fsimg_type = arg;
+		break;
+	case 'i':
+		cla->fsimg_path = arg;
+		break;
+	case 's':
+		cla->selinux = arg;
+		break;
+	case ARGP_KEY_ARG:
+		if (!cla->src_path) {
+			cla->src_path = arg;
+		} else if (!cla->dst_path) {
+			cla->dst_path = arg;
+		} else {
+			argp_usage(state);
+			return -1;
+		}
+		break;
+	case ARGP_KEY_END:
+		if (state->arg_num < 2 || !cla->fsimg_type || !cla->fsimg_path)
+			argp_usage(state);
+	default:
+		return ARGP_ERR_UNKNOWN;
+	}
+
+	return 0;
+}
+
+static struct argp argp_cptofs = {
+	.options = options,
+	.parser = parse_opt,
+	.args_doc = args_doc_cptofs,
+	.doc = doc_cptofs,
+};
+
+static struct argp argp_cpfromfs = {
+	.options = options,
+	.parser = parse_opt,
+	.args_doc = args_doc_cpfromfs,
+	.doc = doc_cpfromfs,
+};
+
+static int searchdir(const char *fs_path, const char *path, const char *match);
+
+static int open_src(const char *path)
+{
+	int fd;
+
+	if (cptofs)
+		fd = open(path, O_RDONLY, 0);
+	else
+		fd = lkl_sys_open(path, LKL_O_RDONLY, 0);
+
+	if (fd < 0)
+		fprintf(stderr, "unable to open file %s for reading: %s\n",
+			path, cptofs ? strerror(errno) : lkl_strerror(fd));
+
+	return fd;
+}
+
+static int open_dst(const char *path, int mode)
+{
+	int fd;
+
+	if (cptofs)
+		fd = lkl_sys_open(path, LKL_O_RDWR | LKL_O_TRUNC | LKL_O_CREAT,
+				  mode);
+	else
+		fd = open(path, O_RDWR | O_TRUNC | O_CREAT, mode);
+
+	if (fd < 0)
+		fprintf(stderr, "unable to open file %s for writing: %s\n",
+			path, cptofs ? lkl_strerror(fd) : strerror(errno));
+
+	if (cla.selinux && cptofs) {
+		int ret = lkl_sys_fsetxattr(fd, "security.selinux", cla.selinux,
+					    strlen(cla.selinux), 0);
+		if (ret)
+			fprintf(stderr, "unable to set selinux attribute on %s: %s\n",
+				path, lkl_strerror(ret));
+	}
+
+	return fd;
+}
+
+static int read_src(int fd, char *buf, int len)
+{
+	int ret;
+
+	if (cptofs)
+		ret = read(fd, buf, len);
+	else
+		ret = lkl_sys_read(fd, buf, len);
+
+	if (ret < 0)
+		fprintf(stderr, "error reading file: %s\n",
+			cptofs ? strerror(errno) : lkl_strerror(ret));
+
+	return ret;
+}
+
+static int write_dst(int fd, char *buf, int len)
+{
+	int ret;
+
+	if (cptofs)
+		ret = lkl_sys_write(fd, buf, len);
+	else
+		ret = write(fd, buf, len);
+
+	if (ret < 0)
+		fprintf(stderr, "error writing file: %s\n",
+			cptofs ? lkl_strerror(ret) : strerror(errno));
+
+	return ret;
+}
+
+static void close_src(int fd)
+{
+	if (cptofs)
+		close(fd);
+	else
+		lkl_sys_close(fd);
+}
+
+static void close_dst(int fd)
+{
+	if (cptofs)
+		lkl_sys_close(fd);
+	else
+		close(fd);
+}
+
+static int copy_file(const char *src, const char *dst, int mode)
+{
+	long len, to_write, wrote;
+	char buf[4096], *ptr;
+	int ret = 0;
+	int fd_src, fd_dst;
+
+	fd_src = open_src(src);
+	if (fd_src < 0)
+		return fd_src;
+
+	fd_dst = open_dst(dst, mode);
+	if (fd_dst < 0)
+		return fd_dst;
+
+	do {
+		len = read_src(fd_src, buf, sizeof(buf));
+
+		if (len > 0) {
+			ptr = buf;
+			to_write = len;
+			do {
+				wrote = write_dst(fd_dst, ptr, to_write);
+
+				if (wrote < 0) {
+					ret = wrote;
+					goto out;
+				}
+
+				to_write -= wrote;
+				ptr += len;
+
+			} while (to_write > 0);
+		}
+
+		if (len < 0)
+			ret = len;
+
+	} while (len > 0);
+
+out:
+	close_src(fd_src);
+	close_dst(fd_dst);
+
+	return ret;
+}
+
+static int stat_src(const char *path, int *type, int *mode)
+{
+	struct stat stat;
+	struct lkl_stat64 lkl_stat;
+	int ret;
+
+	if (cptofs) {
+		ret = lstat(path, &stat);
+		*type = stat.st_mode & S_IFMT;
+		*mode = stat.st_mode & ~S_IFMT;
+	} else {
+		ret = lkl_sys_lstat64(path, &lkl_stat);
+		*type = lkl_stat.st_mode & S_IFMT;
+		*mode = lkl_stat.st_mode & ~S_IFMT;
+	}
+
+	if (ret)
+		fprintf(stderr, "fsimg fstat64(%s) error: %s\n",
+			path, cptofs ? strerror(errno) : lkl_strerror(ret));
+
+	return ret;
+}
+
+static int mkdir_dst(const char *path, int mode)
+{
+	int ret;
+
+	if (cptofs) {
+		ret = lkl_sys_mkdir(path, mode);
+		if (ret == -LKL_EEXIST)
+			ret = 0;
+	} else {
+		ret = mkdir(path, mode);
+		if (ret < 0 && errno == EEXIST)
+			ret = 0;
+	}
+
+	if (ret)
+		fprintf(stderr, "unable to create directory %s: %s\n",
+			path, cptofs ? strerror(errno) : lkl_strerror(ret));
+
+	return ret;
+}
+
+static int do_entry(const char *_src, const char *_dst, const char *name)
+{
+	char src[PATH_MAX], dst[PATH_MAX];
+	int type, mode;
+	int ret;
+
+	snprintf(src, sizeof(src), "%s/%s", _src, name);
+	snprintf(dst, sizeof(dst), "%s/%s", _dst, name);
+
+	ret = stat_src(src, &type, &mode);
+
+	switch (type) {
+	case S_IFREG:
+	{
+		ret = copy_file(src, dst, mode);
+		break;
+	}
+	case S_IFDIR:
+		ret = mkdir_dst(dst, mode);
+		if (ret)
+			break;
+		ret = searchdir(src, dst, NULL);
+		break;
+	case S_IFLNK:
+	case S_IFSOCK:
+	case S_IFBLK:
+	case S_IFCHR:
+	case S_IFIFO:
+	default:
+		printf("skipping %s: unsupported entry type %d\n", src, type);
+	}
+
+	if (ret)
+		printf("error processing entry %s, aborting\n", src);
+
+	return ret;
+}
+
+static DIR *open_dir(const char *path)
+{
+	DIR *dir;
+	int err;
+
+	if (cptofs)
+		dir = opendir(path);
+	else
+		dir = (DIR *)lkl_opendir(path, &err);
+
+	if (!dir)
+		fprintf(stderr, "unable to open directory %s: %s\n",
+			path, cptofs ? strerror(errno) : lkl_strerror(err));
+	return dir;
+}
+
+static const char *read_dir(DIR *dir, const char *path)
+{
+	struct lkl_dir *lkl_dir = (struct lkl_dir *)dir;
+	const char *name = NULL;
+	const char *err = NULL;
+
+	if (cptofs) {
+		struct dirent *de = readdir(dir);
+
+		if (de)
+			name = de->d_name;
+	} else {
+		struct lkl_dirent64 *de = lkl_readdir(lkl_dir);
+
+		if (de)
+			name = de->d_name;
+	}
+
+	if (!name) {
+		if (cptofs) {
+			if (errno)
+				err = strerror(errno);
+		} else {
+			if (lkl_errdir(lkl_dir))
+				err = lkl_strerror(lkl_errdir(lkl_dir));
+		}
+	}
+
+	if (err)
+		fprintf(stderr, "error while reading directory %s: %s\n",
+			path, err);
+	return name;
+}
+
+static void close_dir(DIR *dir)
+{
+	if (cptofs)
+		closedir(dir);
+	else
+		lkl_closedir((struct lkl_dir *)dir);
+}
+
+static int searchdir(const char *src, const char *dst, const char *match)
+{
+	DIR *dir;
+	const char *name;
+	int ret = 0;
+
+	dir = open_dir(src);
+	if (!dir)
+		return -1;
+
+	while ((name = read_dir(dir, src))) {
+		if (!strcmp(name, ".") || !strcmp(name, "..") ||
+		    (match && fnmatch(match, name, 0) != 0))
+			continue;
+
+		ret = do_entry(src, dst, name);
+		if (ret)
+			goto out;
+	}
+
+out:
+	close_dir(dir);
+
+	return ret;
+}
+
+int main(int argc, char **argv)
+{
+	union lkl_disk_backstore bs;
+	long ret;
+	char mpoint[32], src_path[PATH_MAX], dst_path[PATH_MAX];
+	char *src_path_dir, *src_path_base;
+	unsigned int disk_id;
+
+	if (strstr(argv[0], "cptofs")) {
+		cptofs = 1;
+		ret = argp_parse(&argp_cptofs, argc, argv, 0, 0, &cla);
+	} else {
+		ret = argp_parse(&argp_cpfromfs, argc, argv, 0, 0, &cla);
+	}
+
+	if (ret < 0)
+		return -1;
+
+	if (!cla.printk)
+		lkl_host_ops.print = NULL;
+
+	bs.fd = open(cla.fsimg_path, cptofs ? O_RDWR : O_RDONLY);
+	if (bs.fd < 0) {
+		fprintf(stderr, "can't open fsimg %s: %s\n", cla.fsimg_path,
+			strerror(errno));
+		ret = 1;
+		goto out;
+	}
+
+	disk_id = lkl_disk_add(bs);
+	if (disk_id < 0) {
+		fprintf(stderr, "can't add disk: %s\n", lkl_strerror(ret));
+		goto out_close;
+	}
+
+	lkl_start_kernel(&lkl_host_ops, 100 * 1024 * 1024, "");
+
+	ret = lkl_mount_dev(disk_id, cla.fsimg_type, cptofs ? 0 : LKL_MS_RDONLY,
+			    NULL, mpoint, sizeof(mpoint));
+	if (ret) {
+		fprintf(stderr, "can't mount disk: %s\n", lkl_strerror(ret));
+		goto out_close;
+	}
+
+	if (cptofs) {
+		snprintf(src_path, sizeof(src_path),  "%s", cla.src_path);
+		snprintf(dst_path, sizeof(dst_path),  "%s/%s", mpoint,
+			 cla.dst_path);
+	} else {
+		snprintf(src_path, sizeof(src_path),  "%s/%s", mpoint,
+			 cla.src_path);
+		snprintf(dst_path, sizeof(dst_path),  "%s", cla.dst_path);
+	}
+
+	src_path_dir = dirname(strdup(src_path));
+	src_path_base = basename(strdup(src_path));
+
+	ret = searchdir(src_path_dir, dst_path, src_path_base);
+
+	ret = lkl_umount_dev(disk_id, 0, 1000);
+
+out_close:
+	close(bs.fd);
+
+out:
+	lkl_sys_halt();
+
+	return ret;
+}
-- 
2.1.0


  parent reply	other threads:[~2015-11-03 20:25 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-11-03 20:20 [RFC PATCH 00/28] Linux Kernel Library Octavian Purdila
2015-11-03 20:20 ` [RFC PATCH 01/28] asm-generic: atomic64: allow using generic atomic64 on 64bit platforms Octavian Purdila
2015-11-03 20:20 ` [RFC PATCH 02/28] kbuild: allow architectures to automatically define kconfig symbols Octavian Purdila
2015-11-03 20:20 ` [RFC PATCH 03/28] lkl: architecture skeleton for Linux kernel library Octavian Purdila
2015-11-03 20:20 ` [RFC PATCH 04/28] lkl: host interface Octavian Purdila
2015-11-03 23:30   ` Hajime Tazaki
2015-11-03 20:20 ` [RFC PATCH 05/28] lkl: memory handling Octavian Purdila
2015-11-03 20:20 ` [RFC PATCH 06/28] lkl: kernel threads support Octavian Purdila
2015-11-03 20:20 ` [RFC PATCH 07/28] lkl: interrupt support Octavian Purdila
2015-11-03 20:20 ` [RFC PATCH 08/28] lkl: system call interface and application API Octavian Purdila
2015-11-07 23:24   ` Arnd Bergmann
2015-11-08  3:49     ` Octavian Purdila
2015-11-08 10:26       ` Arnd Bergmann
2015-11-03 20:20 ` [RFC PATCH 09/28] lkl: timers, time and delay support Octavian Purdila
2015-11-03 20:20 ` [RFC PATCH 10/28] lkl: memory mapped I/O support Octavian Purdila
2015-11-03 20:20 ` [RFC PATCH 11/28] lkl: basic kernel console support Octavian Purdila
2015-11-03 20:20 ` [RFC PATCH 12/28] init: allow architecture code to overide run_init_process Octavian Purdila
2015-11-03 20:20 ` [RFC PATCH 13/28] lkl: initialization and cleanup Octavian Purdila
2015-11-03 20:20 ` [RFC PATCH 14/28] lkl: plug in the build system Octavian Purdila
2015-11-03 20:20 ` [RFC PATCH 15/28] lkl tools: skeleton for host side library, tests and tools Octavian Purdila
2015-11-03 20:20 ` [RFC PATCH 16/28] lkl tools: host lib: add lkl_strerror and lkl_printf Octavian Purdila
2015-11-03 20:20 ` [RFC PATCH 17/28] lkl tools: host lib: memory mapped I/O helpers Octavian Purdila
2015-11-03 20:20 ` [RFC PATCH 18/28] lkl tools: host lib: virtio devices Octavian Purdila
2015-11-03 20:20 ` [RFC PATCH 19/28] lkl tools: host lib: virtio block device Octavian Purdila
2015-11-07 12:24   ` Richard Weinberger
2015-11-08  4:15     ` Octavian Purdila
2015-11-08 13:30       ` Richard Weinberger
2015-11-03 20:20 ` [RFC PATCH 20/28] lkl tools: host lib: filesystem helpers Octavian Purdila
2015-11-03 20:20 ` [RFC PATCH 21/28] lkl tools: host lib: posix host operations Octavian Purdila
2015-11-07 23:16   ` Arnd Bergmann
2015-11-08  4:01     ` Octavian Purdila
2015-11-08 10:35       ` Arnd Bergmann
2015-11-03 20:20 ` [RFC PATCH 22/28] lkl tools: "boot" test Octavian Purdila
2015-11-03 20:20 ` [RFC PATCH 23/28] lkl tools: tool that converts a filesystem image to tar Octavian Purdila
2015-11-03 20:20 ` Octavian Purdila [this message]
2015-11-03 20:20 ` [RFC PATCH 25/28] signal: use CONFIG_X86_32 instead of __i386__ Octavian Purdila
2015-11-03 20:20 ` [RFC PATCH 26/28] asm-generic: vmlinux.lds.h: allow customized rodata section name Octavian Purdila
2015-11-03 20:20 ` [RFC PATCH 27/28] lkl: add support for Windows hosts Octavian Purdila
2015-11-03 20:20 ` [RFC PATCH 28/28] lkl tools: add support for Windows host Octavian Purdila
2015-11-03 21:40 ` [RFC PATCH 00/28] Linux Kernel Library Richard Weinberger
2015-11-03 22:45   ` Richard W.M. Jones
2015-11-03 23:23     ` Hajime Tazaki
2015-11-03 23:24     ` Octavian Purdila
2015-11-04 13:22       ` Austin S Hemmelgarn
2015-11-04 13:50       ` Richard W.M. Jones
2015-11-04 14:15         ` Octavian Purdila
2015-11-07  0:35           ` Richard Weinberger
2015-11-07  7:19             ` Richard W.M. Jones
2015-11-07 10:48             ` Richard W.M. Jones
2015-11-09 16:35               ` Octavian Purdila
2015-11-08  4:16             ` Octavian Purdila
2015-11-08  4:36             ` Octavian Purdila
2015-11-03 23:06   ` Octavian Purdila
     [not found]     ` <1670BE0E-C0E0-4D45-BF16-1FF60C298149@gmail.com>
2015-11-09 15:11       ` Octavian Purdila
2015-11-08 13:45 ` Hajime Tazaki

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1446582059-17355-25-git-send-email-octavian.purdila@intel.com \
    --to=octavian.purdila@intel.com \
    --cc=linux-arch@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=thehajime@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.