diff options
author | Lennart Poettering <lennart@poettering.net> | 2015-03-09 17:55:07 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2015-03-09 18:02:23 +0100 |
commit | 587fec427c80b6c34dcf1d7570f891fcb652a7c5 (patch) | |
tree | 0b8f6e748ac8ecc34cbe6d03327532fb52a0e85b /src/import/import-common.c | |
parent | ea79e73b8a8fa72fb959a0604f642f97e200a803 (diff) |
importd: add API for exporting container/VM images
Also, expose it in machinectl.
Diffstat (limited to 'src/import/import-common.c')
-rw-r--r-- | src/import/import-common.c | 76 |
1 files changed, 75 insertions, 1 deletions
diff --git a/src/import/import-common.c b/src/import/import-common.c index 6c3f347e75..aede2f9b36 100644 --- a/src/import/import-common.c +++ b/src/import/import-common.c @@ -69,7 +69,7 @@ int import_make_read_only(const char *path) { return import_make_read_only_fd(fd); } -int import_fork_tar(const char *path, pid_t *ret) { +int import_fork_tar_x(const char *path, pid_t *ret) { _cleanup_close_pair_ int pipefd[2] = { -1, -1 }; pid_t pid; int r; @@ -148,3 +148,77 @@ int import_fork_tar(const char *path, pid_t *ret) { return r; } + +int import_fork_tar_c(const char *path, pid_t *ret) { + _cleanup_close_pair_ int pipefd[2] = { -1, -1 }; + pid_t pid; + int r; + + assert(path); + assert(ret); + + if (pipe2(pipefd, O_CLOEXEC) < 0) + return log_error_errno(errno, "Failed to create pipe for tar: %m"); + + pid = fork(); + if (pid < 0) + return log_error_errno(errno, "Failed to fork off tar: %m"); + + if (pid == 0) { + int null_fd; + uint64_t retain = (1ULL << CAP_DAC_OVERRIDE); + + /* Child */ + + reset_all_signal_handlers(); + reset_signal_mask(); + assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); + + pipefd[0] = safe_close(pipefd[0]); + + if (dup2(pipefd[1], STDOUT_FILENO) != STDOUT_FILENO) { + log_error_errno(errno, "Failed to dup2() fd: %m"); + _exit(EXIT_FAILURE); + } + + if (pipefd[1] != STDOUT_FILENO) + pipefd[1] = safe_close(pipefd[1]); + + null_fd = open("/dev/null", O_RDONLY|O_NOCTTY); + if (null_fd < 0) { + log_error_errno(errno, "Failed to open /dev/null: %m"); + _exit(EXIT_FAILURE); + } + + if (dup2(null_fd, STDIN_FILENO) != STDIN_FILENO) { + log_error_errno(errno, "Failed to dup2() fd: %m"); + _exit(EXIT_FAILURE); + } + + if (null_fd != STDIN_FILENO) + null_fd = safe_close(null_fd); + + fd_cloexec(STDIN_FILENO, false); + fd_cloexec(STDOUT_FILENO, false); + fd_cloexec(STDERR_FILENO, false); + + if (unshare(CLONE_NEWNET) < 0) + log_error_errno(errno, "Failed to lock tar into network namespace, ignoring: %m"); + + r = capability_bounding_set_drop(~retain, true); + if (r < 0) + log_error_errno(r, "Failed to drop capabilities, ignoring: %m"); + + execlp("tar", "tar", "--sparse", "-C", path, "-c", ".", NULL); + log_error_errno(errno, "Failed to execute tar: %m"); + _exit(EXIT_FAILURE); + } + + pipefd[1] = safe_close(pipefd[1]); + r = pipefd[0]; + pipefd[0] = -1; + + *ret = pid; + + return r; +} |