diff options
author | Alexander Larsson <alexl@redhat.com> | 2016-02-16 15:55:08 +0100 |
---|---|---|
committer | Alexander Larsson <alexl@redhat.com> | 2016-02-16 15:55:08 +0100 |
commit | f5b006ff0ca206b3f760253baf73bd0a00ff71cd (patch) | |
tree | 984d8efd67e84d4910889046cad2fb5d74d31aa9 | |
parent | 0bf9bc3d0b9833f3441f5e53ed35b2589f90c487 (diff) | |
download | bubblewrap-f5b006ff0ca206b3f760253baf73bd0a00ff71cd.tar.gz |
Support --make-file
-rw-r--r-- | build-root.c | 39 | ||||
-rw-r--r-- | utils.c | 65 | ||||
-rw-r--r-- | utils.h | 5 |
3 files changed, 109 insertions, 0 deletions
diff --git a/build-root.c b/build-root.c index ac7ff31..dcea2d6 100644 --- a/build-root.c +++ b/build-root.c @@ -63,6 +63,7 @@ usage () " --mount-proc DEST Mount procfs on DEST in the sandbox\n" " --mount-dev DEST Mount new dev on DEST in the sandbox\n" " --make-dir DEST Create dir at DEST in the sandbox\n" + " --make-file FD DEST Copy from FD to dest DEST in the sandbox\n" " --make-symlink SRC DEST Create symlink at DEST in the sandbox with target SRC\n" " --make-passwd DEST Create trivial /etc/passwd file at DEST in the sandbox\n" " --make-group DEST Create trivial /etc/group file at DEST in the sandbox\n" @@ -296,6 +297,7 @@ typedef enum { SETUP_MOUNT_PROC, SETUP_MOUNT_DEV, SETUP_MAKE_DIR, + SETUP_MAKE_FILE, SETUP_MAKE_SYMLINK, SETUP_MAKE_PASSWD, SETUP_MAKE_GROUP, @@ -307,6 +309,7 @@ struct _SetupOp { SetupOpType type; const char *source; const char *dest; + int fd; SetupOp *next; }; @@ -319,6 +322,7 @@ setup_op_new (SetupOpType type) SetupOp *op = xcalloc (sizeof (SetupOp)); op->type = type; + op->fd = -1; if (last_op != NULL) last_op->next = op; else @@ -518,6 +522,26 @@ main (int argc, argv += 1; argc -= 1; } + else if (strcmp (arg, "--make-file") == 0) + { + SetupOp *op; + int file_fd; + char *endptr; + + if (argc < 3) + die ("--make-file takes two arguments"); + + file_fd = strtol (argv[1], &endptr, 10); + if (argv[1][0] == 0 || endptr[0] != 0 || file_fd < 0) + die ("Invalid fd: %s", argv[1]); + + op = setup_op_new (SETUP_MAKE_FILE); + op->fd = file_fd; + op->dest = argv[2]; + + argv += 2; + argc -= 2; + } else if (strcmp (arg, "--make-symlink") == 0) { SetupOp *op; @@ -840,6 +864,21 @@ main (int argc, break; + case SETUP_MAKE_FILE: + { + cleanup_fd int dest_fd = -1; + + dest_fd = creat (dest, 0666); + if (dest_fd == -1) + die_with_error ("Can't create file %s", op->dest); + + if (copy_file_data (op->fd, dest_fd) != 0) + die_with_error ("Can't write data to file %s", op->dest); + + close (op->fd); + } + break; + case SETUP_MAKE_SYMLINK: if (symlink (op->source, dest) != 0) die_with_error ("Can't make symlink at %s", op->dest); @@ -330,6 +330,71 @@ create_file (const char *path, return res; } +#define BUFSIZE 8192 +/* Sets errno on error (!= 0), ENOSPC on short write */ +int +copy_file_data (int sfd, + int dfd) +{ + char buffer[BUFSIZE]; + ssize_t bytes_read; + + while (TRUE) + { + bytes_read = read (sfd, buffer, BUFSIZE); + if (bytes_read == -1) + { + if (errno == EINTR) + continue; + + return -1; + } + + if (bytes_read == 0) + break; + + if (write_to_fd (dfd, buffer, bytes_read) != 0) + return -1; + } + + return 0; +} + +/* Sets errno on error (!= 0), ENOSPC on short write */ +int +copy_file (const char *src_path, + const char *dst_path, + mode_t mode) +{ + int sfd; + int dfd; + int res; + int errsv; + + sfd = open (src_path, O_CLOEXEC | O_RDONLY); + if (sfd == -1) + return -1; + + dfd = creat (dst_path, mode); + if (dfd == -1) + { + errsv = errno; + close (sfd); + errno = errsv; + return -1; + } + + res = copy_file_data (sfd, dfd); + + errsv = errno; + close (sfd); + close (dfd); + errno = errsv; + + return res; +} + + /* Sets errno on error (== NULL) */ char * load_file_at (int dirfd, @@ -81,6 +81,11 @@ int write_file_at (int dirfd, int write_to_fd (int fd, const char *content, ssize_t len); +int copy_file_data (int sfd, + int dfd); +int copy_file (const char *src_path, + const char *dst_path, + mode_t mode); int create_file (const char *path, mode_t mode, const char *content); |