From 232afc9538af2437888054a2eb3f8d4fcd983521 Mon Sep 17 00:00:00 2001 From: YaoZengzeng Date: Fri, 30 Sep 2016 15:17:15 +0800 Subject: [PATCH] read and write file in parent process whose fd sent by its child process Signed-off-by: Yao Zengzeng --- src/init.c | 260 +++++++++++++++++++---------------------------------- 1 file changed, 92 insertions(+), 168 deletions(-) diff --git a/src/init.c b/src/init.c index 67fe147..2145e71 100644 --- a/src/init.c +++ b/src/init.c @@ -656,184 +656,77 @@ out: return ret; } -static int hyper_cmd_write_file(char *json, int length) -{ - struct file_command cmd; - struct hyper_container *c; - struct hyper_pod *pod = &global_pod; - int pipe[2] = {-1, -1}; - int pid, mntns = -1, fd; - int datalen, len = 0, size, ret = -1; - char *data = NULL; - - fprintf(stdout, "%s\n", __func__); - - // TODO: send the data via hyperstream rather than append it at the end of the command - data = strchr(json, '}'); - if (data == NULL) { - goto out; - } - data++; - datalen = length - (data - json); - length = data - json; - if (hyper_parse_file_command(&cmd, json, length) < 0) { - goto out; - } - - c = hyper_find_container(pod, cmd.id); - if (c == NULL) { - fprintf(stderr, "can not find container whose id is %s\n", cmd.id); - goto out; - } - - if (pipe2(pipe, O_CLOEXEC) < 0) { - perror("create writter pipe failed"); - goto out; - } - - mntns = c->ns; - if (mntns < 0) { - perror("fail to open mnt ns"); - goto out; - } - - pid = fork(); - if (pid < 0) { - perror("fail to fork writter process"); - goto out; - } else if (pid > 0) { - uint32_t type; - - if (hyper_get_type(pipe[0], &type) < 0 || type != READY) { - fprintf(stderr, "get incorrect message type %d, expect READY\n", type); - goto out; - } - - ret = 0; - goto out; - } - - /* TODO: wait for container finishing setup root */ - if (setns(mntns, CLONE_NEWNS) < 0) { - perror("fail to enter container ns"); - goto exit; - } - - fprintf(stdout, "write file %s, data len %d\n", cmd.file, datalen); - - fd = open(cmd.file, O_CREAT| O_TRUNC| O_WRONLY, 0644); - if (fd < 0) { - perror("fail to open target file"); - goto exit; - } - - while(len < datalen) { - size = write(fd, data + len, datalen - len); - - if (size < 0) { - if (errno == EINTR) - continue; - - perror("fail to write data to file"); - goto exit; - } - - len += size; - } - ret = 0; -exit: - hyper_send_type(pipe[1], ret ? ERROR : READY); - _exit(0); -out: - close(pipe[0]); - close(pipe[1]); - free(cmd.id); - free(cmd.file); - - return 0; -} - struct hyper_file_arg { - int mntns; - int pipe[2]; - char *file; - char root[128]; - uint32_t *datalen; - uint8_t **data; + int rw; + int mntns; + int pipe[2]; + char *file; }; -static int hyper_do_cmd_read_file(void *data) +static int hyper_open_container_file(void *data) { - struct stat st; - int len = 0, size, fd, ret = -1; struct hyper_file_arg *arg = data; + int fd = -1, ret = -1, size; - /* TODO: wait for container finishing setup root */ if (setns(arg->mntns, CLONE_NEWNS) < 0) { perror("fail to enter container ns"); - goto err; + goto exit; } - fprintf(stdout, "read file %s\n", arg->file); - - if (stat(arg->file, &st) < 0) { - perror("fail to state file"); - goto err; + if (arg->rw == WRITEFILE) { + fd = open(arg->file, O_CREAT| O_TRUNC| O_WRONLY, 0644); + } else { + fd = open(arg->file, O_RDONLY); } - - *arg->datalen = st.st_size; - *arg->data = malloc(*arg->datalen); - if (*arg->data == NULL) { - fprintf(stderr, "allocate memory for reading file failed\n"); - goto err; - } - - fd = open(arg->file, O_RDONLY); if (fd < 0) { perror("fail to open target file"); - goto err; + goto exit; } - - fprintf(stdout, "file length %d\n", *arg->datalen); - while(len < *arg->datalen) { - size = read(fd, *arg->data + len, *arg->datalen - len); - - if (size < 0) { - if (errno == EINTR) - continue; - - perror("fail to read data from file"); - goto err; - } - - len += size; - } - - fprintf(stdout, "read data %s\n", *arg->data); ret = 0; -err: - hyper_send_type(arg->pipe[1], ret ? ERROR : READY); - _exit(ret); + +exit: + size = write(arg->pipe[1], &fd, sizeof(fd)); + if (size != sizeof(fd) && ret == 0) { + ret = -1; + } + exit(ret); } -static int hyper_cmd_read_file(char *json, int length, uint32_t *datalen, uint8_t **data) +static int hyper_cmd_rw_file(char *json, int length, uint32_t *rdatalen, uint8_t **rdata, int rw) { - struct file_command cmd; - struct hyper_container *c; - struct hyper_pod *pod = &global_pod; + struct file_command cmd = { + .id = NULL, + .file = NULL, + }; struct hyper_file_arg arg = { .pipe = {-1, -1}, + .rw = rw, }; - int stacksize = getpagesize() * 4; + struct hyper_container *c; + struct hyper_pod *pod = &global_pod; + char *data = NULL; void *stack = NULL; - int pid, ret = -1, status; - uint32_t type; + int stacksize = getpagesize() * 4; + int fd = -1, len = 0, ret = -1, datalen = 0; + int pid, size; - fprintf(stdout, "%s\n", __func__); + fprintf(stdout, "%s: %s\n", __func__, rw == WRITEFILE ? "write" : "read"); + + if (rw == WRITEFILE) { + // TODO: send the data via hyperstream rather than append it at the end of the command + data = strchr(json, '}'); + if (data == NULL) { + goto out; + } + data++; + datalen = length - (data - json); + length = data - json; + } if (hyper_parse_file_command(&cmd, json, length) < 0) { goto out; } + arg.file = cmd.file; c = hyper_find_container(pod, cmd.id); if (c == NULL) { @@ -841,20 +734,16 @@ static int hyper_cmd_read_file(char *json, int length, uint32_t *datalen, uint8_ goto out; } - if (pipe2(arg.pipe, O_CLOEXEC) < 0) { - perror("create reader pipe failed"); - goto out; - } - arg.mntns = c->ns; if (arg.mntns < 0) { perror("fail to open mnt ns"); goto out; } - arg.file = cmd.file; - arg.datalen = datalen; - arg.data = data; + if (pipe2(arg.pipe, O_CLOEXEC) < 0) { + perror("create pipe failed"); + goto out; + } stack = malloc(stacksize); if (stack == NULL) { @@ -862,24 +751,59 @@ static int hyper_cmd_read_file(char *json, int length, uint32_t *datalen, uint8_ goto out; } - pid = clone(hyper_do_cmd_read_file, stack + stacksize, CLONE_VM| SIGQUIT, &arg); + pid = clone(hyper_open_container_file, stack + stacksize, CLONE_FILES | SIGCHLD, &arg); if (pid < 0) { - perror("fail to fork reader process"); + perror("fail to fork child process"); goto out; } - if (waitpid(pid, &status, __WCLONE) <= 0) { - perror("waiting hyper_do_cmd_read_file finish failed"); + size = read(arg.pipe[0], &fd, sizeof(fd)); + if (size != sizeof(fd)) { + perror("fail to read fd from pipe"); + goto out; + } + if (fd < 0) { + perror("child open target file failed"); goto out; } - if (hyper_get_type(arg.pipe[0], &type) < 0 || type != READY) { - fprintf(stderr, "%s to incorrect type %" PRIu32 "\n", __func__, type); - goto out; + if (rw == READFILE) { + struct stat st; + if(fstat(fd, &st) < 0) { + perror("fail to state file"); + goto out; + } + *rdatalen = datalen = st.st_size; + data = malloc(datalen); + *rdata = (uint8_t *) data; + if (*rdata == NULL) { + fprintf(stderr, "allocate memory for reading file failed\n"); + goto out; + } + fprintf(stdout, "file length %d\n", *rdatalen); } + while(len < datalen) { + if (rw == WRITEFILE) { + size = write(fd, data + len, datalen - len); + } else { + size = read(fd, data + len, datalen - len); + } + + if (size < 0) { + if (errno == EINTR) + continue; + + perror("fail to operate data to file"); + goto out; + } + + len += size; + } ret = 0; + out: + close(fd); close(arg.pipe[0]); close(arg.pipe[1]); free(cmd.id); @@ -1123,10 +1047,10 @@ static int hyper_channel_handle(struct hyper_event *de, uint32_t len) ret = hyper_exec_cmd((char *)buf->data + 8, len - 8); break; case WRITEFILE: - ret = hyper_cmd_write_file((char *)buf->data + 8, len - 8); + ret = hyper_cmd_rw_file((char *)buf->data + 8, len - 8, NULL, NULL, WRITEFILE); break; case READFILE: - ret = hyper_cmd_read_file((char *)buf->data + 8, len - 8, &datalen, &data); + ret = hyper_cmd_rw_file((char *)buf->data + 8, len - 8, &datalen, &data, READFILE); break; case PING: case GETPOD: