From 3c30271f3c5578428f8aee2bc71b9cd81fb7f2e1 Mon Sep 17 00:00:00 2001 From: Rolf Neugebauer Date: Fri, 2 Sep 2016 16:57:52 +0100 Subject: [PATCH] transfused: Use Linux coding style (mostly) Signed-off-by: Rolf Neugebauer --- alpine/packages/transfused/transfused.c | 1830 +++++++++-------- alpine/packages/transfused/transfused.h | 66 +- alpine/packages/transfused/transfused_log.c | 375 ++-- alpine/packages/transfused/transfused_log.h | 35 +- alpine/packages/transfused/transfused_vsock.c | 137 +- alpine/packages/transfused/transfused_vsock.h | 9 +- 6 files changed, 1294 insertions(+), 1158 deletions(-) diff --git a/alpine/packages/transfused/transfused.c b/alpine/packages/transfused/transfused.c index a6c8982dc..bc722101b 100644 --- a/alpine/packages/transfused/transfused.c +++ b/alpine/packages/transfused/transfused.c @@ -25,1050 +25,1162 @@ #include "transfused_log.h" #include "transfused_vsock.h" -char * default_fusermount = DEFAULT_FUSERMOUNT; -char * default_socket = DEFAULT_SOCKET; -char * default_server = DEFAULT_SERVER; -char * usage = - "usage: transfused [-p pidfile] [-d server] [-s socket] [-f fusermount]\n" - " [-l logfile]\n" - " -p pidfile\tthe path at which to write the pid of the process\n" - " -d " DEFAULT_SERVER "\tthe server address to use ('v:addr:port')\n" - " -s " DEFAULT_SOCKET "\tthe socket address to use ('v:addr:port')\n" - " -f " DEFAULT_FUSERMOUNT "\tthe fusermount executable to use\n" - " -l logfile\tthe log file to use before uplink\n" - ; +char *default_fusermount = DEFAULT_FUSERMOUNT; +char *default_socket = DEFAULT_SOCKET; +char *default_server = DEFAULT_SERVER; +char *usage = +"usage: transfused [-p pidfile] [-d server] [-s socket] [-f fusermount]\n" +" [-l logfile]\n" +" -p pidfile\tthe path at which to write the pid of the process\n" +" -d " DEFAULT_SERVER "\tthe server address to use ('v:addr:port')\n" +" -s " DEFAULT_SOCKET "\tthe socket address to use ('v:addr:port')\n" +" -f " DEFAULT_FUSERMOUNT "\tthe fusermount executable to use\n" +" -l logfile\tthe log file to use before uplink\n"; -int debug = 0; +int debug; pthread_attr_t detached; typedef struct { - connection_t * connection; - int from; - int to; + connection_t *connection; + int from; + int to; } copy_thread_state; #include -pid_t gettid() { - return syscall(SYS_gettid); -} - -void * must_malloc(char *const descr, size_t size) { - void * ptr; - - ptr = malloc(size); - if (size != 0 && ptr == NULL) die(1, NULL, descr, ""); - - return ptr; -} - -void cond_init(char *const descr, pthread_cond_t * cond, - const pthread_condattr_t *restrict attr) { - if ((errno = pthread_cond_init(cond, attr))) - die(1, NULL, "", "cond init %s: ", descr); -} - -void lock_init(char *const descr, pthread_mutex_t * mutex, - const pthread_mutexattr_t *restrict attr) { - if ((errno = pthread_mutex_init(mutex, attr))) - die(1, NULL, "", "lock init %s: ", descr); -} - -void lock(char *const descr, pthread_mutex_t * mutex) { - if ((errno = pthread_mutex_lock(mutex))) - die(1, NULL, "", "lock %s: ", descr); -} - -void unlock(char *const descr, pthread_mutex_t * mutex) { - if ((errno = pthread_mutex_unlock(mutex))) - die(1, NULL, "", "unlock %s: ", descr); -} - -int bind_socket(const char * socket) { - int sock; - - if (socket[0] == 0) - die(2, NULL, NULL, "Socket family required"); - - if (socket[1] != ':') - die(2, NULL, NULL, "Socket address required"); - - switch (socket[0]) { - case 'v': - sock = bind_vsock(socket + 2); - break; - default: - die(2, NULL, NULL, "Unknown socket family '%c'", socket[0]); - } - - return sock; -} - -int connect_socket(const char * socket) { - int sock; - - if (socket[0] == 0) - die(2, NULL, NULL, "Socket family required"); - if (socket[1] != ':') - die(2, NULL, NULL, "Scoket address required"); - - switch (socket[0]) { - case 'v': - sock = connect_vsock(socket + 2); - break; - default: - die(2, NULL, NULL, "Unknown socket family '%c'", socket[0]); - } - - return sock; -} - -char ** read_opts(connection_t * conn, char * buf) { - int read_count; - int optc = 1; - char ** optv; - size_t mount_len; - - // TODO: deal with socket read conditions e.g. EAGAIN - read_count = read(conn->sock, buf, EVENT_BUFSZ - 1); - if (read_count < 0) die(1, conn->params, "read_opts error reading", ""); - - // TODO: protocol should deal with short read - buf[read_count] = 0x0; - - for (int i = 0; i < read_count; i++) { - if (buf[i] == 0x0) optc++; - } - - optv = (char **) must_malloc("read_opts optv", (optc + 1) * sizeof(void *)); - optv[0] = buf; - optv[optc] = 0x0; - - int j = 1; - for (int i = 0; i < read_count && j < optc; i++) { - if (buf[i] == 0x0) { - optv[j] = buf + i + 1; - j++; - } - } - - mount_len = strnlen(optv[optc - 1], 4096) + 1; - conn->mount_point = must_malloc("mount point string", mount_len); - strncpy(conn->mount_point, optv[optc - 1], mount_len - 1); - conn->mount_point[mount_len - 1] = '\0'; - - return optv; -} - -uint64_t message_id(uint64_t * message) { - return message[1]; -} - -int read_message -(char * descr, parameters * params, int fd, char * buf, size_t max_read) +pid_t gettid(void) { - int read_count; - size_t nbyte; - uint32_t len; - - // TODO: socket read conditions e.g. EAGAIN - read_count = read(fd, buf, 4); - if (read_count != 4) { - if (read_count < 0) - die(1, params, "", "read %s: error reading: ", descr); - if (read_count == 0) - die(1, params, NULL, "read %s: EOF reading length", descr); - die(1, params, NULL, "read %s: short read length %d", descr, read_count); - } - len = *((uint32_t *) buf); - if (len > max_read) - die(1, params, NULL, "read %s: message size %d exceeds buffer capacity %d", - len, max_read); - - nbyte = (size_t) (len - 4); - buf += 4; - - do { - // TODO: socket read conditions e.g. EAGAIN - read_count = read(fd, buf, nbyte); - if (read_count < 0) die(1, params, "", "read %s: error reading: ", descr); - if (read_count == 0) die(1, params, NULL, "read %s: EOF reading", descr); - nbyte -= read_count; - buf += read_count; - } while (nbyte != 0); - - return (int) len; + return syscall(SYS_gettid); } -void copy_into_fuse(copy_thread_state * copy_state) { - int from = copy_state->from; - int to = copy_state->to; - char * descr = copy_state->connection->mount_point; - int read_count, write_count; - void * buf; - parameters * params = copy_state->connection->params; +void *must_malloc(char *const descr, size_t size) +{ + void *ptr; - buf = must_malloc(descr, IN_BUFSZ); + ptr = malloc(size); + if (size != 0 && ptr == NULL) + die(1, NULL, descr, ""); - while(1) { - read_count = read_message(descr, params, from, (char *) buf, IN_BUFSZ); - - write_count = write(to, buf, read_count); - if (write_count < 0) die(1, params, "", "copy %s: error writing: ", descr); - - // /dev/fuse accepts only complete writes - if (write_count != read_count) - die(1, params, NULL, "copy %s: read %d but only wrote %d", - descr, read_count, write_count); - } - - free(buf); + return ptr; } -void copy_notify_fuse(copy_thread_state * copy_state) { - int from = copy_state->from; - int to = copy_state->to; - char * descr = copy_state->connection->mount_point; - int read_count, write_count; - uint32_t zero = 0, err; - void * buf; - parameters * params = copy_state->connection->params; - - buf = must_malloc(descr, IN_BUFSZ); - - while (1) { - read_count = read_message(descr, params, from, (char *) buf, IN_BUFSZ); - write_count = write(to, buf, read_count); - if (write_count < 0) { - err = errno; - write_count = write(from, &err, 4); - if (write_count < 0) { - log_time(params, "copy notify %s write error: %s", strerror(err)); - die(1, params, "", "copy notify %s reply write error: ", - descr); - } - continue; - } else { - if (write(from, &zero, 4) < 0) - die(1, params, "", "copy notify %s reply write error: ", - descr); - } - - if (write_count != read_count) - die(1, params, NULL, "copy notify %s: read %d but only wrote %d", - descr, read_count, write_count); - } - - free(buf); +void cond_init(char *const descr, pthread_cond_t *cond, + const pthread_condattr_t *restrict attr) +{ + errno = pthread_cond_init(cond, attr); + if (errno) + die(1, NULL, "", "cond init %s: ", descr); } -void write_exactly(char * descr, int fd, void * p, size_t nbyte) { - int write_count; - char * buf = p; - - do { - // TODO: socket write conditions e.g. EAGAIN - write_count = write(fd, buf, nbyte); - if (write_count < 0) die(1, NULL, "", "%s: error writing: ", descr); - if (write_count == 0) die(1, NULL, "", "%s: 0 write: ", descr); - - nbyte -= write_count; - buf += write_count; - } while (nbyte != 0); +void lock_init(char *const descr, pthread_mutex_t *mutex, + const pthread_mutexattr_t *restrict attr) +{ + errno = pthread_mutex_init(mutex, attr); + if (errno) + die(1, NULL, "", "lock init %s: ", descr); } -void copy_outof_fuse(copy_thread_state * copy_state) { - int from = copy_state->from; - int to = copy_state->to; - char * descr = copy_state->connection->mount_point; - int read_count; - void * buf; - parameters * params = copy_state->connection->params; - - buf = must_malloc(descr, OUT_BUFSZ); - - while(1) { - // /dev/fuse only returns complete reads - read_count = read(from, buf, OUT_BUFSZ); - if (read_count < 0) die(1, params, "", "copy %s: error reading: ", descr); - - write_exactly(descr, to, (char *) buf, read_count); - } - - free(buf); +void lock(char *const descr, pthread_mutex_t *mutex) +{ + errno = pthread_mutex_lock(mutex); + if (errno) + die(1, NULL, "", "lock %s: ", descr); } -void * copy_clean_into_fuse(copy_thread_state * copy_state) { - copy_into_fuse(copy_state); - - close(copy_state->from); - - free(copy_state); - - return NULL; +void unlock(char *const descr, pthread_mutex_t *mutex) +{ + errno = pthread_mutex_unlock(mutex); + if (errno) + die(1, NULL, "", "unlock %s: ", descr); } -void * copy_clean_into_fuse_thread(void * copy_state) { - return (copy_clean_into_fuse((copy_thread_state *) copy_state)); +int bind_socket(const char *socket) +{ + int sock; + + if (socket[0] == 0) + die(2, NULL, NULL, "Socket family required"); + + if (socket[1] != ':') + die(2, NULL, NULL, "Socket address required"); + + switch (socket[0]) { + case 'v': + sock = bind_vsock(socket + 2); + break; + default: + die(2, NULL, NULL, "Unknown socket family '%c'", socket[0]); + } + + return sock; } -void * copy_clean_notify_fuse(copy_thread_state * copy_state) { - copy_notify_fuse(copy_state); +int connect_socket(const char *socket) +{ + int sock; - close(copy_state->from); + if (socket[0] == 0) + die(2, NULL, NULL, "Socket family required"); + if (socket[1] != ':') + die(2, NULL, NULL, "Scoket address required"); - free(copy_state); + switch (socket[0]) { + case 'v': + sock = connect_vsock(socket + 2); + break; + default: + die(2, NULL, NULL, "Unknown socket family '%c'", socket[0]); + } - return NULL; + return sock; } -void * copy_clean_notify_fuse_thread(void * copy_state) { - return (copy_clean_notify_fuse((copy_thread_state *) copy_state)); +char **read_opts(connection_t *conn, char *buf) +{ + int read_count; + int optc = 1; + char **optv; + size_t mount_len; + int j; + + /* TODO: deal with socket read conditions e.g.EAGAIN */ + read_count = read(conn->sock, buf, EVENT_BUFSZ - 1); + if (read_count < 0) + die(1, conn->params, "read_opts error reading", ""); + + /* TODO: protocol should deal with short read */ + buf[read_count] = 0x0; + + for (int i = 0; i < read_count; i++) { + if (buf[i] == 0x0) + optc++; + } + + optv = (char **)must_malloc("read_opts optv", (optc + 1) * sizeof(void *)); + optv[0] = buf; + optv[optc] = 0x0; + + j = 1; + for (int i = 0; i < read_count && j < optc; i++) { + if (buf[i] == 0x0) { + optv[j] = buf + i + 1; + j++; + } + } + + mount_len = strnlen(optv[optc - 1], 4096) + 1; + conn->mount_point = must_malloc("mount point string", mount_len); + strncpy(conn->mount_point, optv[optc - 1], mount_len - 1); + conn->mount_point[mount_len - 1] = '\0'; + + return optv; } -void * copy_clean_outof_fuse(copy_thread_state * copy_state) { - copy_outof_fuse(copy_state); - - close(copy_state->to); - - free(copy_state); - - return NULL; +uint64_t message_id(uint64_t *message) +{ + return message[1]; } -void * copy_clean_outof_fuse_thread(void * copy_state) { - return (copy_clean_outof_fuse((copy_thread_state *) copy_state)); +int read_message(char *descr, parameters *params, int fd, + char *buf, size_t max_read){ + int read_count; + size_t nbyte; + uint32_t len; + + /* TODO: socket read conditions e.g.EAGAIN */ + read_count = read(fd, buf, 4); + if (read_count != 4) { + if (read_count < 0) + die(1, params, "", "read %s: error reading: ", descr); + if (read_count == 0) + die(1, params, NULL, + "read %s: EOF reading length", descr); + die(1, params, NULL, + "read %s: short read length %d", descr, read_count); + } + len = *((uint32_t *) buf); + if (len > max_read) + die(1, params, NULL, + "read %s: message size %d exceeds buffer capacity %d", + len, max_read); + + nbyte = (size_t)(len - 4); + buf += 4; + + do { + /* TODO: socket read conditions e.g.EAGAIN */ + read_count = read(fd, buf, nbyte); + if (read_count < 0) + die(1, params, "", "read %s: error reading: ", descr); + if (read_count == 0) + die(1, params, NULL, "read %s: EOF reading", descr); + nbyte -= read_count; + buf += read_count; + } while (nbyte != 0); + + return (int)len; } -int recv_fd(parameters * params, int sock) { - int ret; - int fd = -1; - char iochar; - char buf[CMSG_SPACE(sizeof(fd))]; +void copy_into_fuse(copy_thread_state *copy_state) +{ + int from = copy_state->from; + int to = copy_state->to; + char *descr = copy_state->connection->mount_point; + int read_count, write_count; + void *buf; + parameters *params = copy_state->connection->params; - struct msghdr msg; - struct iovec vec; - struct cmsghdr *cmsg; + buf = must_malloc(descr, IN_BUFSZ); - msg.msg_name = NULL; - msg.msg_namelen = 0; - vec.iov_base = &iochar; - vec.iov_len = 1; - msg.msg_iov = &vec; + while (1) { + read_count = read_message(descr, params, + from, (char *)buf, IN_BUFSZ); - msg.msg_iovlen = 1; + write_count = write(to, buf, read_count); + if (write_count < 0) + die(1, params, "", "copy %s: error writing: ", descr); - msg.msg_control = buf; - msg.msg_controllen = sizeof(buf); + /* /dev/fuse accepts only complete writes */ + if (write_count != read_count) + die(1, params, NULL, + "copy %s: read %d but only wrote %d", + descr, read_count, write_count); + } - ret = recvmsg(sock, &msg, 0); - - if (ret == -1) die(1, params, "recvmsg", ""); - - if (ret > 0 && msg.msg_controllen > 0) { - cmsg = CMSG_FIRSTHDR(&msg); - if (cmsg->cmsg_level == SOL_SOCKET && (cmsg->cmsg_type == SCM_RIGHTS)) { - fd = *(int*)CMSG_DATA(cmsg); - } - } - - return fd; + free(buf); } -// optv must be null-terminated -int get_fuse_sock(connection_t * conn, int optc, char *const optv[]) { - char ** argv; - char * envp[2]; - char * mount_notice, * arg_acc; - pid_t fusermount_pid; - int fuse_socks[2]; - int status; - int fd; +void copy_notify_fuse(copy_thread_state *copy_state) +{ + int from = copy_state->from; + int to = copy_state->to; + char *descr = copy_state->connection->mount_point; + int read_count, write_count; + uint32_t zero = 0, err; + void *buf; + parameters *params = copy_state->connection->params; - // prepare argv from optv - argv = (char **) must_malloc("fusermount argv", (optc + 2) * sizeof(char *)); + buf = must_malloc(descr, IN_BUFSZ); - argv[0] = conn->params->fusermount; - memcpy(&argv[1], optv, (optc + 1) * sizeof(char *)); + while (1) { + read_count = read_message(descr, params, + from, (char *)buf, IN_BUFSZ); + write_count = write(to, buf, read_count); + if (write_count < 0) { + err = errno; + write_count = write(from, &err, 4); + if (write_count < 0) { + log_time(params, + "copy notify %s write error: %s", strerror(err)); + die(1, params, "", + "copy notify %s reply write error: ", descr); + } + continue; + } else { + if (write(from, &zero, 4) < 0) + die(1, params, "", + "copy notify %s reply write error: ", descr); + } - // report the mount command issued - if (asprintf(&arg_acc, "mount") == -1) - die(1, conn->params, "Couldn't allocate mount notice base string", ""); + if (write_count != read_count) + die(1, params, NULL, + "copy notify %s: read %d but only wrote %d", + descr, read_count, write_count); + } - for (int i = 0; argv[i]; i++) { - if (asprintf(&mount_notice, "%s %s", arg_acc, argv[i]) == -1) - die(1, conn->params, "", "Couldn't allocate mount notice arg %d: ", i); - free(arg_acc); - arg_acc = mount_notice; - } - - if (asprintf(&mount_notice, "%s\n", arg_acc) == -1) - die(1, conn->params, "Couldn't allocate mount notice", ""); - - log_notice_time(conn->params, mount_notice); - - free(mount_notice); - free(arg_acc); - - // make the socket over which we'll be sent the FUSE socket fd - if (socketpair(PF_UNIX, SOCK_STREAM, 0, fuse_socks)) - die(1, conn->params, "Couldn't create FUSE socketpair", ""); - - // prepare to exec the suid binary fusermount - if (asprintf(&envp[0], "_FUSE_COMMFD=%d", fuse_socks[0]) == -1) - die(1, conn->params, "Couldn't allocate fusermount envp", ""); - - envp[1] = 0x0; - - // fork and exec fusermount - fusermount_pid = fork(); - if (!fusermount_pid) // child - if (execve(argv[0], argv, envp)) - die(1, conn->params, "Failed to execute fusermount", ""); - - // parent - free(argv); - free(envp[0]); - - // close the end of the socket that we gave away - close(fuse_socks[0]); - - // wait for fusermount to return - waitpid(fusermount_pid, &status, 0); - if (!WIFEXITED(status)) - die(1, conn->params, NULL, "fusermount terminated abnormally"); - - if (WEXITSTATUS(status)) - die(1, conn->params, NULL, - "fusermount exited with code %d", WEXITSTATUS(status)); - - if (debug) log_time(conn->params, "about to recv_fd from fusermount\n"); - - fd = recv_fd(conn->params, fuse_socks[1]); - if (fd == -1) - die(1, conn->params, NULL, "Couldn't receive fd over FUSE socket"); - - // close the read end of the socket - close(fuse_socks[1]); - - return fd; + free(buf); } -void start_reader(connection_t * connection, int fuse) { - pthread_t child; - copy_thread_state * copy_state; +void write_exactly(char *descr, int fd, void *p, size_t nbyte) +{ + int write_count; + char *buf = p; - copy_state = (copy_thread_state *) must_malloc("start_reader copy_state", - sizeof(copy_thread_state)); - copy_state->connection = connection; - copy_state->from = connection->sock; - copy_state->to = fuse; - if ((errno = pthread_create(&child, &detached, - copy_clean_into_fuse_thread, copy_state))) - die(1, connection->params, "", - "Couldn't create read copy thread for mount %s: ", - connection->mount_point); + do { + /* TODO: socket write conditions e.g.EAGAIN */ + write_count = write(fd, buf, nbyte); + if (write_count < 0) + die(1, NULL, "", "%s: error writing: ", descr); + if (write_count == 0) + die(1, NULL, "", "%s: 0 write: ", descr); + + nbyte -= write_count; + buf += write_count; + } while (nbyte != 0); } -void start_writer(connection_t * connection, int fuse) { - pthread_t child; - copy_thread_state * copy_state; +void copy_outof_fuse(copy_thread_state *copy_state) +{ + int from = copy_state->from; + int to = copy_state->to; + char *descr = copy_state->connection->mount_point; + int read_count; + void *buf; + parameters *params = copy_state->connection->params; - copy_state = (copy_thread_state *) must_malloc("start_writer copy_state", - sizeof(copy_thread_state)); - copy_state->connection = connection; - copy_state->from = fuse; - copy_state->to = connection->sock; - if ((errno = pthread_create(&child, &detached, - copy_clean_outof_fuse_thread, copy_state))) - die(1, connection->params, "", - "Couldn't create write copy thread for mount %s: ", - connection->mount_point); + buf = must_malloc(descr, OUT_BUFSZ); + + while (1) { + /* /dev/fuse only returns complete reads */ + read_count = read(from, buf, OUT_BUFSZ); + if (read_count < 0) + die(1, params, "", "copy %s: error reading: ", descr); + + write_exactly(descr, to, (char *)buf, read_count); + } + + free(buf); } -void negotiate_notify_channel(char * mount_point, int notify_sock) { - int len = strlen(mount_point); - char hdr[6]; +void *copy_clean_into_fuse(copy_thread_state *copy_state) +{ + copy_into_fuse(copy_state); - *((uint32_t *) hdr) = 6 + len; - *((uint16_t *) (hdr + 4)) = TRANSFUSE_NOTIFY_CHANNEL; + close(copy_state->from); - write_exactly("negotiate_notify_channel hdr", notify_sock, hdr, 6); - write_exactly("negotiate_notify_channel mnt", notify_sock, mount_point, len); + free(copy_state); + + return NULL; } -void start_notify(connection_t * connection, int fuse) { - pthread_t child; - copy_thread_state * copy_state; +void *copy_clean_into_fuse_thread(void *copy_state) +{ + return copy_clean_into_fuse((copy_thread_state *)copy_state); +} - copy_state = (copy_thread_state *) must_malloc("start_notify copy_state", - sizeof(copy_thread_state)); - copy_state->connection = connection; - copy_state->from = connect_socket(connection->params->server); - copy_state->to = fuse; +void *copy_clean_notify_fuse(copy_thread_state *copy_state) +{ + copy_notify_fuse(copy_state); - negotiate_notify_channel(connection->mount_point, copy_state->from); + close(copy_state->from); - if ((errno = pthread_create(&child, &detached, - copy_clean_notify_fuse_thread, copy_state))) - die(1, connection->params, "", - "Couldn't create notify copy thread for mount %s: ", - connection->mount_point); + free(copy_state); + + return NULL; +} + +void *copy_clean_notify_fuse_thread(void *copy_state) +{ + return copy_clean_notify_fuse((copy_thread_state *) copy_state); +} + +void *copy_clean_outof_fuse(copy_thread_state *copy_state) +{ + copy_outof_fuse(copy_state); + + close(copy_state->to); + + free(copy_state); + + return NULL; +} + +void *copy_clean_outof_fuse_thread(void *copy_state) +{ + return copy_clean_outof_fuse((copy_thread_state *) copy_state); +} + +int recv_fd(parameters *params, int sock) +{ + int ret; + int fd = -1; + char iochar; + char buf[CMSG_SPACE(sizeof(fd))]; + + struct msghdr msg; + struct iovec vec; + struct cmsghdr *cmsg; + + msg.msg_name = NULL; + msg.msg_namelen = 0; + vec.iov_base = &iochar; + vec.iov_len = 1; + msg.msg_iov = &vec; + + msg.msg_iovlen = 1; + + msg.msg_control = buf; + msg.msg_controllen = sizeof(buf); + + ret = recvmsg(sock, &msg, 0); + + if (ret == -1) + die(1, params, "recvmsg", ""); + + if (ret > 0 && msg.msg_controllen > 0) { + cmsg = CMSG_FIRSTHDR(&msg); + if (cmsg->cmsg_level == SOL_SOCKET && (cmsg->cmsg_type == SCM_RIGHTS)) + fd = *(int *)CMSG_DATA(cmsg); + } + return fd; +} + +/* optv must be null-terminated */ +int get_fuse_sock(connection_t *conn, int optc, char *const optv[]) +{ + char **argv; + char *envp[2]; + char *mount_notice, *arg_acc; + pid_t fusermount_pid; + int fuse_socks[2]; + int status; + int fd; + + /* prepare argv from optv */ + argv = (char **)must_malloc("fusermount argv", + (optc + 2) * sizeof(char *)); + + argv[0] = conn->params->fusermount; + memcpy(&argv[1], optv, (optc + 1) * sizeof(char *)); + + /* report the mount command issued */ + if (asprintf(&arg_acc, "mount") == -1) + die(1, conn->params, + "Couldn't allocate mount notice base string", ""); + + for (int i = 0; argv[i]; i++) { + if (asprintf(&mount_notice, "%s %s", arg_acc, argv[i]) == -1) + die(1, conn->params, "", + "Couldn't allocate mount notice arg %d: ", i); + free(arg_acc); + arg_acc = mount_notice; + } + + if (asprintf(&mount_notice, "%s\n", arg_acc) == -1) + die(1, conn->params, "Couldn't allocate mount notice", ""); + + log_notice_time(conn->params, mount_notice); + + free(mount_notice); + free(arg_acc); + + /* make the socket over which we'll be sent the FUSE socket fd */ + if (socketpair(PF_UNIX, SOCK_STREAM, 0, fuse_socks)) + die(1, conn->params, "Couldn't create FUSE socketpair", ""); + + /* prepare to exec the suid binary fusermount */ + if (asprintf(&envp[0], "_FUSE_COMMFD=%d", fuse_socks[0]) == -1) + die(1, conn->params, "Couldn't allocate fusermount envp", ""); + + envp[1] = 0x0; + + /* fork and exec fusermount */ + fusermount_pid = fork(); + if (!fusermount_pid) + /* child */ + if (execve(argv[0], argv, envp)) + die(1, conn->params, + "Failed to execute fusermount", ""); + + /* parent */ + free(argv); + free(envp[0]); + + /* close the end of the socket that we gave away */ + close(fuse_socks[0]); + + /* wait for fusermount to return */ + waitpid(fusermount_pid, &status, 0); + if (!WIFEXITED(status)) + die(1, conn->params, NULL, "fusermount terminated abnormally"); + + if (WEXITSTATUS(status)) + die(1, conn->params, NULL, + "fusermount exited with code %d", WEXITSTATUS(status)); + + if (debug) + log_time(conn->params, "about to recv_fd from fusermount\n"); + + fd = recv_fd(conn->params, fuse_socks[1]); + if (fd == -1) + die(1, conn->params, NULL, "Couldn't receive fd over FUSE socket"); + + /* close the read end of the socket */ + close(fuse_socks[1]); + + return fd; +} + +void start_reader(connection_t *connection, int fuse) +{ + pthread_t child; + copy_thread_state *copy_state; + + copy_state = (copy_thread_state *) + must_malloc("start_reader copy_state", + sizeof(copy_thread_state)); + copy_state->connection = connection; + copy_state->from = connection->sock; + copy_state->to = fuse; + errno = pthread_create(&child, &detached, + copy_clean_into_fuse_thread, copy_state); + if (errno) + die(1, connection->params, "", + "Couldn't create read copy thread for mount %s: ", + connection->mount_point); +} + +void start_writer(connection_t *connection, int fuse) +{ + pthread_t child; + copy_thread_state *copy_state; + + copy_state = (copy_thread_state *) + must_malloc("start_writer copy_state", + sizeof(copy_thread_state)); + copy_state->connection = connection; + copy_state->from = fuse; + copy_state->to = connection->sock; + errno = pthread_create(&child, &detached, + copy_clean_outof_fuse_thread, copy_state); + if (errno) + die(1, connection->params, "", + "Couldn't create write copy thread for mount %s: ", + connection->mount_point); +} + +void negotiate_notify_channel(char *mount_point, int notify_sock) +{ + int len = strlen(mount_point); + char hdr[6]; + + *((uint32_t *)hdr) = 6 + len; + *((uint16_t *)(hdr + 4)) = TRANSFUSE_NOTIFY_CHANNEL; + + write_exactly("negotiate_notify_channel hdr", notify_sock, hdr, 6); + write_exactly("negotiate_notify_channel mnt", + notify_sock, mount_point, len); +} + +void start_notify(connection_t *connection, int fuse) +{ + pthread_t child; + copy_thread_state *copy_state; + + copy_state = (copy_thread_state *) + must_malloc("start_notify copy_state", + sizeof(copy_thread_state)); + copy_state->connection = connection; + copy_state->from = connect_socket(connection->params->server); + copy_state->to = fuse; + + negotiate_notify_channel(connection->mount_point, copy_state->from); + + errno = pthread_create(&child, &detached, + copy_clean_notify_fuse_thread, copy_state); + if (errno) + die(1, connection->params, "", + "Couldn't create notify copy thread for mount %s: ", + connection->mount_point); } -char * alloc_dirname(connection_t * conn, char * path) { - size_t len = strlen(path) + 1; - char * input = must_malloc("alloc_dirname input", len); - char * output = must_malloc("alloc_dirname output", len); - char * dir; - strlcpy(input, path, len); +char *alloc_dirname(connection_t *conn, char *path) +{ + size_t len = strlen(path) + 1; + char *input = must_malloc("alloc_dirname input", len); + char *output = must_malloc("alloc_dirname output", len); + char *dir; - dir = dirname(input); - if (dir == NULL) - die(1, conn->params, "", "Couldn't get dirname of %s: ", path); - strcpy(output, dir); + strlcpy(input, path, len); - free(input); - return output; + dir = dirname(input); + if (dir == NULL) + die(1, conn->params, "", "Couldn't get dirname of %s: ", path); + strcpy(output, dir); + + free(input); + return output; } -void mkdir_p(connection_t * conn, char * path) { - char * parent; +void mkdir_p(connection_t *conn, char *path) +{ + char *parent; - if (mkdir(path, 0700)) switch (errno) { - case EEXIST: return; - case ENOENT: - parent = alloc_dirname(conn, path); - mkdir_p(conn, parent); - free(parent); - if (mkdir(path, 0700)) - die(1, conn->params, "", "Couldn't create directory %s: ", path); - break; - default: - die(1, conn->params, "", "Couldn't create directory %s: ", path); - } + if (mkdir(path, 0700)) + switch (errno) { + case EEXIST: + return; + case ENOENT: + parent = alloc_dirname(conn, path); + mkdir_p(conn, parent); + free(parent); + if (mkdir(path, 0700)) + die(1, conn->params, "", + "Couldn't create directory %s: ", path); + break; + default: + die(1, conn->params, "", + "Couldn't create directory %s: ", path); + } } -int is_next_child_ok(parameters * params, char * path, DIR * dir) { - struct dirent * child; +int is_next_child_ok(parameters *params, char *path, DIR *dir) +{ + struct dirent *child; - errno = 0; - child = readdir(dir); - if (child == NULL) { - if (errno != 0) - die(1, params, "", "Couldn't read directory %s: ", path); - else return 0; - } - return 1; + errno = 0; + child = readdir(dir); + if (child == NULL) { + if (errno != 0) + die(1, params, "", + "Couldn't read directory %s: ", path); + else + return 0; + } + return 1; } -int is_path_mountable -(parameters * params, int allow_empty, char * path) { - DIR * dir; +int is_path_mountable(parameters *params, int allow_empty, char *path) +{ + DIR *dir; - dir = opendir(path); - if (dir != NULL) { - // allow for . and .. - if (is_next_child_ok(params, path, dir)) - if (is_next_child_ok(params, path, dir)) { - if (is_next_child_ok(params, path, dir)) goto no; - else if (allow_empty) goto yes; - else goto no; - } - goto yes; - } else { - switch (errno) { - case ENOENT: goto yes; - case ENOTDIR: goto no; - default: goto no; - } - } - goto no; + dir = opendir(path); + if (dir != NULL) { + /* allow for . and .. */ + if (is_next_child_ok(params, path, dir)) + if (is_next_child_ok(params, path, dir)) { + if (is_next_child_ok(params, path, dir)) + goto no; + else if (allow_empty) + goto yes; + else + goto no; + } + goto yes; + } else { + switch (errno) { + case ENOENT: + goto yes; + case ENOTDIR: + goto no; + default: + goto no; + } + } + goto no; - no: if (dir) closedir(dir); return 0; - yes: if (dir) closedir(dir); return 1; +no: + if (dir) + closedir(dir); + return 0; + +yes: + if (dir) + closedir(dir); + return 1; } -// The leaf may exist but must be empty. Any proper path prefix may exist. -void prepare_mount_point(connection_t * conn) { - char * mount_point = conn->mount_point; +/* The leaf may exist but must be empty. Any proper path prefix may exist. */ +void prepare_mount_point(connection_t *conn) +{ + char *mount_point = conn->mount_point; - if (is_path_mountable(conn->params, 1, mount_point)) - mkdir_p(conn, mount_point); - else die(1, conn->params, NULL, - "Couldn't mount on %s: not missing or empty", mount_point); + if (is_path_mountable(conn->params, 1, mount_point)) + mkdir_p(conn, mount_point); + else + die(1, conn->params, NULL, + "Couldn't mount on %s: not missing or empty", mount_point); } -void * mount_connection(connection_t * conn) { - int optc; - char ** optv; - int fuse; - char * buf; - pthread_mutex_t copy_lock; - pthread_cond_t copy_halt; - int should_halt = 0; - - buf = (char *) must_malloc("read_opts packet malloc", EVENT_BUFSZ); +void *mount_connection(connection_t *conn) +{ + int optc; + char **optv; + int fuse; + char *buf; + pthread_mutex_t copy_lock; + pthread_cond_t copy_halt; + int should_halt = 0; - optv = read_opts(conn, buf); + buf = (char *)must_malloc("read_opts packet malloc", EVENT_BUFSZ); - prepare_mount_point(conn); + optv = read_opts(conn, buf); - for (optc = 0; optv[optc] != NULL; optc++) {} + prepare_mount_point(conn); - fuse = get_fuse_sock(conn, optc, optv); - free(buf); - free(optv); + for (optc = 0; optv[optc] != NULL; optc++) { + } - lock_init("copy_lock", ©_lock, NULL); - cond_init("copy_halt", ©_halt, NULL); + fuse = get_fuse_sock(conn, optc, optv); + free(buf); + free(optv); - start_reader(conn, fuse); - start_writer(conn, fuse); - start_notify(conn, fuse); + lock_init("copy_lock", ©_lock, NULL); + cond_init("copy_halt", ©_halt, NULL); - lock("copy lock", ©_lock); - while (!should_halt) - if ((errno = pthread_cond_wait(©_halt, ©_lock))) - die(1, conn->params, "", - "Couldn't wait for copy halt for mount %s: ", - conn->mount_point); - unlock("copy lock", ©_lock); + start_reader(conn, fuse); + start_writer(conn, fuse); + start_notify(conn, fuse); - free(conn); + lock("copy lock", ©_lock); + while (!should_halt) + errno = pthread_cond_wait(©_halt, ©_lock); + if (errno) + die(1, conn->params, "", + "Couldn't wait for copy halt for mount %s: ", + conn->mount_point); + unlock("copy lock", ©_lock); - return NULL; + free(conn); + + return NULL; } -void * mount_thread(void * connection) { - return mount_connection((connection_t *) connection); +void *mount_thread(void *connection) +{ + return mount_connection((connection_t *) connection); } -void write_pid(connection_t * connection) { - pid_t pid = gettid(); - char * pid_s; - int pid_s_len, write_count; +void write_pid(connection_t *connection) +{ + pid_t pid = gettid(); + char *pid_s; + int pid_s_len, write_count; - if (asprintf(&pid_s, "%lld", (long long) pid) == -1) - die(1, connection->params, "Couldn't allocate pid string", ""); + if (asprintf(&pid_s, "%lld", (long long)pid) == -1) + die(1, connection->params, "Couldn't allocate pid string", ""); - pid_s_len = strlen(pid_s); + pid_s_len = strlen(pid_s); - // TODO: check for socket write conditions e.g. EAGAIN - write_count = write(connection->sock, pid_s, pid_s_len); - if (write_count < 0) - die(1, connection->params, "Error writing pid", ""); + /* TODO: check for socket write conditions e.g.EAGAIN */ + write_count = write(connection->sock, pid_s, pid_s_len); + if (write_count < 0) + die(1, connection->params, "Error writing pid", ""); - // TODO: handle short writes - if (write_count != pid_s_len) - die(1, connection->params, NULL, - "Error writing pid %s to socket: only wrote %d bytes", - pid_s, write_count); + /* TODO: handle short writes */ + if (write_count != pid_s_len) + die(1, connection->params, NULL, + "Error writing pid %s to socket: only wrote %d bytes", + pid_s, write_count); - free(pid_s); + free(pid_s); } -void pong(parameters * params) { - char pong_msg[6] = { '\6', '\0', '\0', '\0', PONG_REPLY, '\0' }; +void pong(parameters *params) +{ + char pong_msg[6] = {'\6', '\0', '\0', '\0', PONG_REPLY, '\0'}; - write_exactly("pong reply", params->ctl_sock, pong_msg, 6); + write_exactly("pong reply", params->ctl_sock, pong_msg, 6); } -void perform_syscall(connection_t * conn, uint8_t syscall, char path[]) { - char * name; - int r = 0; +void perform_syscall(connection_t *conn, uint8_t syscall, char path[]) +{ + char *name; + int r = 0; - switch (syscall) { + switch (syscall) { - case PING: - pong(conn->params); - r = 0; - break; + case PING: + pong(conn->params); + r = 0; + break; - case RMDIR_SYSCALL: - name = "rmdir"; - r = rmdir(path); - break; + case RMDIR_SYSCALL: + name = "rmdir"; + r = rmdir(path); + break; - case UNLINK_SYSCALL: - name = "unlink"; - r = unlink(path); - break; + case UNLINK_SYSCALL: + name = "unlink"; + r = unlink(path); + break; - case MKDIR_SYSCALL: - name = "mkdir"; - r = mkdir(path, 00000); - break; + case MKDIR_SYSCALL: + name = "mkdir"; + r = mkdir(path, 00000); + break; - case SYMLINK_SYSCALL: - name = "symlink"; - r = symlink(".",path); - break; + case SYMLINK_SYSCALL: + name = "symlink"; + r = symlink(".", path); + break; - case MKNOD_REG_SYSCALL: - name = "mknod"; - r = mknod(path, 0600, 0); - break; + case MKNOD_REG_SYSCALL: + name = "mknod"; + r = mknod(path, 0600, 0); + break; - case TRUNCATE_SYSCALL: - name = "truncate"; - r = truncate(path, 0); - break; + case TRUNCATE_SYSCALL: + name = "truncate"; + r = truncate(path, 0); + break; - case CHMOD_SYSCALL: - name = "chmod"; - r = chmod(path, 0700); - break; + case CHMOD_SYSCALL: + name = "chmod"; + r = chmod(path, 0700); + break; - default: - die(1, conn->params, NULL, "Unknown event syscall %" PRIu8, syscall); - } + default: + die(1, conn->params, NULL, + "Unknown event syscall %" PRIu8, syscall); + } - if (r != 0) - thread_log_time(conn, "Event %s %s error: %s\n", - name, path, strerror(errno)); + if (r != 0) + thread_log_time(conn, "Event %s %s error: %s\n", + name, path, strerror(errno)); } -void * event_thread(void * connection_ptr) { - int read_count, path_len; - void * buf; - connection_t * connection = connection_ptr; +void * event_thread(void *connection_ptr) +{ + int read_count, path_len; + void *buf; + connection_t *connection = connection_ptr; - char * path; - uint8_t syscall; + char *path; + uint8_t syscall; - // This thread registers with the file system server as being an - // fsnotify event actuator. Other mounted file system interactions - // (such as self-logging) SHOULD NOT occur on this thread. + /* This thread registers with the file system server as being an + * fsnotify event actuator. Other mounted file system interactions + * (such as self-logging) SHOULD NOT occur on this thread. */ + write_pid(connection); - write_pid(connection); + buf = must_malloc("incoming event buffer", EVENT_BUFSZ); - buf = must_malloc("incoming event buffer", EVENT_BUFSZ); + while (1) { + read_count = read_message("events", connection->params, + connection->sock, buf, EVENT_BUFSZ); - while(1) { - read_count = read_message("events", connection->params, - connection->sock, buf, EVENT_BUFSZ); + if (debug) + thread_log_time(connection, + "read %d bytes from event connection\n", + read_count); - if (debug) - thread_log_time(connection, "read %d bytes from event connection\n", - read_count); + path_len = (int)ntohs(*(((uint32_t *) buf) + 1)); + /* TODO: could check the path length isn't a lie here */ + path = (char *)(((uint8_t *)buf) + 6); + /* TODO: could check the path is NULL terminated here */ + syscall = *(((uint8_t *)buf) + 6 + path_len); - path_len = (int) ntohs(*(((uint32_t *) buf) + 1)); - // TODO: could check the path length isn't a lie here - path = (char *) (((uint8_t *) buf) + 6); - // TODO: could check the path is NUL terminated here - syscall = *(((uint8_t *) buf) + 6 + path_len); + /* TODO: should this be in another thread ? */ + perform_syscall(connection, syscall, path); + } - // TODO: should this be in another thread? - perform_syscall(connection, syscall, path); - } - - free(buf); - // TODO: close connection - return NULL; + free(buf); + /* TODO: close connection */ + return NULL; } -void write_pidfile(parameters * params) { - int fd; - pid_t pid = getpid(); - char * pid_s; - int pid_s_len, write_count; +void write_pidfile(parameters *params) +{ + int fd; + pid_t pid = getpid(); + char *pid_s; + int pid_s_len, write_count; - if (asprintf(&pid_s, "%lld", (long long) pid) == -1) - die(1, params, "Couldn't allocate pidfile string", ""); + if (asprintf(&pid_s, "%lld", (long long)pid) == -1) + die(1, params, "Couldn't allocate pidfile string", ""); - pid_s_len = strlen(pid_s); + pid_s_len = strlen(pid_s); - fd = open(params->pidfile, O_WRONLY | O_CREAT | O_TRUNC, 0644); - if (fd == -1) - die(1, params, "", "Couldn't open pidfile path %s: ", params->pidfile); + fd = open(params->pidfile, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd == -1) + die(1, params, "", + "Couldn't open pidfile path %s: ", params->pidfile); - write_count = write(fd, pid_s, pid_s_len); - if (write_count == -1) - die(1, params, "", "Error writing pidfile %s: ", params->pidfile); + write_count = write(fd, pid_s, pid_s_len); + if (write_count == -1) + die(1, params, "", + "Error writing pidfile %s: ", params->pidfile); - if (write_count != pid_s_len) - die(1, params, NULL, - "Error writing %s to pidfile %s: only wrote %d bytes", - pid_s, params->pidfile, write_count); + if (write_count != pid_s_len) + die(1, params, NULL, + "Error writing %s to pidfile %s: only wrote %d bytes", + pid_s, params->pidfile, write_count); - close(fd); - free(pid_s); + close(fd); + free(pid_s); } -// TODO: the message parsing here is rickety, do it properly -void * determine_mount_suitability(parameters * params, - int allow_empty, char * req, int len) { - void * buf = (void *) req; - uint16_t id = *((uint16_t *) buf); - uint16_t slen; - char * reply; - int roff; +/* TODO: the message parsing here is rickety, do it properly */ +void *determine_mount_suitability(parameters *params, int allow_empty, + char *req, int len) +{ + void *buf = (void *)req; + uint16_t id = *((uint16_t *) buf); + uint16_t slen; + char *reply; + int roff; - reply = (char *) must_malloc("determine_mount_suitability", len + 6); - *((uint16_t *)(reply + 4)) = MOUNT_SUITABILITY_REPLY; - *((uint16_t *)(reply + 6)) = id; - roff = 8; + reply = (char *)must_malloc("determine_mount_suitability", len + 6); + *((uint16_t *) (reply + 4)) = MOUNT_SUITABILITY_REPLY; + *((uint16_t *) (reply + 6)) = id; + roff = 8; - buf = (void *) ((char *) buf + 2); - len -= 2; - while (len) { - slen = *((uint16_t *) buf) + 1; - if (is_path_mountable(params, allow_empty, ((char *) buf) + 2)) { - slen = strlcpy(reply + roff + 2, ((char *) buf) + 2, slen) + 1; - *((uint16_t *) ((void *) (reply + roff))) = slen - 1; - roff += 2 + slen; - } - buf = (void *) ((char *) buf + 2 + slen); - len -= 2 + slen; - } + buf = (void *)((char *)buf + 2); + len -= 2; + while (len) { + slen = *((uint16_t *) buf) + 1; + if (is_path_mountable(params, allow_empty, ((char *)buf) + 2)) { + slen = strlcpy(reply + roff + 2, + ((char *)buf) + 2, slen) + 1; + *((uint16_t *)((void *)(reply + roff))) = slen - 1; + roff += 2 + slen; + } + buf = (void *)((char *)buf + 2 + slen); + len -= 2 + slen; + } - *((uint32_t *) ((void *) reply)) = roff; - return (void *) reply; + *((uint32_t *) ((void *)reply)) = roff; + return (void *)reply; } -void * init_thread(void * params_ptr) { - parameters * params = params_ptr; - int write_count, read_count, len; - char init_msg[6] = { '\6', '\0', '\0', '\0', '\0', '\0' }; - void * buf, * response; - uint16_t msg_type; +void *init_thread(void *params_ptr) +{ + parameters *params = params_ptr; + int write_count, read_count, len; + char init_msg[6] = {'\6', '\0', '\0', '\0', '\0', '\0'}; + void *buf, *response; + uint16_t msg_type; - params->ctl_sock = connect_socket(params->server); + params->ctl_sock = connect_socket(params->server); - // TODO: handle short write/socket conditions - write_count = write(params->ctl_sock, init_msg, sizeof(init_msg)); - if (write_count < 0) die(1, NULL, "init thread: couldn't write init", ""); - if (write_count != sizeof(init_msg)) - die(1, NULL, "init thread: incomplete write", ""); + /* TODO: handle short write/socket conditions */ + write_count = write(params->ctl_sock, init_msg, sizeof(init_msg)); + if (write_count < 0) + die(1, NULL, "init thread: couldn't write init", ""); + if (write_count != sizeof(init_msg)) + die(1, NULL, "init thread: incomplete write", ""); - buf = must_malloc("incoming control message buffer", CTL_BUFSZ); + buf = must_malloc("incoming control message buffer", CTL_BUFSZ); - // TODO: handle short read/socket conditions - read_count = read(params->ctl_sock, buf, 6); - if (read_count < 0) die(1, params, "init thread: error reading", ""); - // TODO: handle other messages - if (read_count != 6) die(1, params, NULL, "init thread: response not 6"); - for (int i = 0; i < sizeof(init_msg); i++) - if (((char *)buf)[i] != init_msg[i]) - die(1, params, NULL, "init thread: unexpected message"); + /* TODO: handle short read / socket conditions */ + read_count = read(params->ctl_sock, buf, 6); + if (read_count < 0) + die(1, params, "init thread: error reading", ""); + /* TODO: handle other messages */ + if (read_count != 6) + die(1, params, NULL, "init thread: response not 6"); + for (int i = 0; i < sizeof(init_msg); i++) + if (((char *)buf)[i] != init_msg[i]) + die(1, params, NULL, "init thread: unexpected message"); - // we've gotten Continue so write the pidfile - if (params->pidfile != NULL) - write_pidfile(params); + /* we've gotten Continue so write the pidfile */ + if (params->pidfile != NULL) + write_pidfile(params); - while (1) { - read_count = read_message("control", params, params->ctl_sock, - buf, CTL_BUFSZ); - msg_type = *((uint16_t *) buf + 2); - switch (msg_type) { - case MOUNT_SUITABILITY_REQUEST: - response = - determine_mount_suitability(params, 0, - (char *) buf + 6, read_count - 6); - len = *((size_t *) response); - write_exactly("init thread: mount suitability response", - params->ctl_sock, response, len); - free(response); - break; - case EXPORT_SUITABILITY_REQUEST: - response = - determine_mount_suitability(params, 1, - (char *) buf + 6, read_count - 6); - len = *((size_t *) response); - write_exactly("init thread: export suitability response", - params->ctl_sock, response, len); - free(response); - break; - default: - die(1, params, NULL, "init thread: unknown message %d", msg_type); - } - } + while (1) { + read_count = read_message("control", params, params->ctl_sock, + buf, CTL_BUFSZ); + msg_type = *((uint16_t *)buf + 2); + switch (msg_type) { + case MOUNT_SUITABILITY_REQUEST: + response = determine_mount_suitability(params, 0, + (char *)buf + 6, + read_count - 6); + len = *((size_t *) response); + write_exactly("init thread: mount suitability response", + params->ctl_sock, response, len); + free(response); + break; - free(buf); - return NULL; + case EXPORT_SUITABILITY_REQUEST: + response = determine_mount_suitability(params, 1, + (char *)buf + 6, + read_count - 6); + len = *((size_t *) response); + write_exactly("init thread: export suitability response", + params->ctl_sock, response, len); + free(response); + break; + + default: + die(1, params, NULL, + "init thread: unknown message %d", msg_type); + } + } + + free(buf); + return NULL; } -void toggle_debug(int sig) { - debug = !debug; +void toggle_debug(int sig) +{ + debug = !debug; } -void setup_debug() { - if (SIG_ERR == signal(SIGHUP, toggle_debug)) - die(1, NULL, "Couldn't set SIGHUP behavior", ""); +void setup_debug(void) +{ + if (signal(SIGHUP, toggle_debug) == SIG_ERR) + die(1, NULL, "Couldn't set SIGHUP behavior", ""); - if (siginterrupt(SIGHUP, 1)) - die(1, NULL, "Couldn't set siginterrupt for SIGHUP", ""); + if (siginterrupt(SIGHUP, 1)) + die(1, NULL, "Couldn't set siginterrupt for SIGHUP", ""); } -void parse_parameters(int argc, char * argv[], parameters * params) { - int c; - int errflg = 0; +void parse_parameters(int argc, char *argv[], parameters *params) +{ + int c; + int errflg = 0; - params->pidfile = NULL; - params->socket = NULL; - params->fusermount = NULL; - params->logfile = NULL; - params->logfile_fd = 0; - params->data_sock = 0; - params->ctl_sock = 0; - lock_init("ctl_lock", ¶ms->ctl_lock, NULL); + params->pidfile = NULL; + params->socket = NULL; + params->fusermount = NULL; + params->logfile = NULL; + params->logfile_fd = 0; + params->data_sock = 0; + params->ctl_sock = 0; + lock_init("ctl_lock", ¶ms->ctl_lock, NULL); - while ((c = getopt(argc, argv, ":p:d:s:f:l:")) != -1) { - switch(c) { + while ((c = getopt(argc, argv, ":p:d:s:f:l:")) != -1) { + switch (c) { - case 'p': - params->pidfile = optarg; - break; + case 'p': + params->pidfile = optarg; + break; - case 'd': - params->server = optarg; - break; + case 'd': + params->server = optarg; + break; - case 's': - params->socket = optarg; - break; + case 's': + params->socket = optarg; + break; - case 'f': - params->fusermount = optarg; - break; + case 'f': + params->fusermount = optarg; + break; - case 'l': - params->logfile = optarg; - break; + case 'l': + params->logfile = optarg; + break; - case ':': - fprintf(stderr, "Option -%c requires a path argument\n", optopt); - errflg++; - break; + case ':': + fprintf(stderr, "Option -%c requires a path argument\n", optopt); + errflg++; + break; - case '?': - fprintf(stderr, "Unrecognized option: '-%c'\n", optopt); - errflg++; - break; + case '?': + fprintf(stderr, "Unrecognized option: '-%c'\n", optopt); + errflg++; + break; - default: - fprintf(stderr, "Internal error parsing -%c\n", c); - errflg++; - } - } + default: + fprintf(stderr, "Internal error parsing -%c\n", c); + errflg++; + } + } - if (errflg) { - fprintf(stderr, "%s", usage); - exit(2); - } + if (errflg) { + fprintf(stderr, "%s", usage); + exit(2); + } + if (params->pidfile != NULL && access(params->pidfile, W_OK)) + if (errno != ENOENT) { + fprintf(stderr, "-p %s path to pidfile must be writable: ", + params->pidfile); + perror(""); + exit(2); + } + if (params->fusermount == NULL) + params->fusermount = default_fusermount; + if (access(params->fusermount, X_OK)) { + fprintf(stderr, "-f %s path to fusermount must be executable: ", + params->fusermount); + perror(""); + exit(2); + } + if (params->socket == NULL) + params->socket = default_socket; - if (params->pidfile != NULL && access(params->pidfile, W_OK)) - if (errno != ENOENT) { - fprintf(stderr, "-p %s path to pidfile must be writable: ", - params->pidfile); - perror(""); - exit(2); - } + if (params->server == NULL) + params->server = default_server; - if (params->fusermount == NULL) - params->fusermount = default_fusermount; - if (access(params->fusermount, X_OK)) { - fprintf(stderr, "-f %s path to fusermount must be executable: ", - params->fusermount); - perror(""); - exit(2); - } - - if (params->socket == NULL) - params->socket = default_socket; - - if (params->server == NULL) - params->server = default_server; - - if (params->logfile != NULL && access(params->logfile, W_OK)) - if (errno != ENOENT) { - fprintf(stderr, "-l %s path to logfile must be writable: ", - params->logfile); - perror(""); - exit(2); - } + if (params->logfile != NULL && access(params->logfile, W_OK)) + if (errno != ENOENT) { + fprintf(stderr, "-l %s path to logfile must be writable: ", + params->logfile); + perror(""); + exit(2); + } } -void serve(parameters * params) { - ssize_t read_count; - char subproto_selector; - pthread_t child; - connection_t * conn; - void * (*connection_handler_thread)(void *); +void serve(parameters *params) +{ + ssize_t read_count; + char subproto_selector; + pthread_t child; + connection_t *conn; + void *(*connection_handler_thread)(void *); - if (listen(params->data_sock, 16)) - die(1, NULL, "listen", ""); + if (listen(params->data_sock, 16)) + die(1, NULL, "listen", ""); - if ((errno = pthread_create(&child, &detached, init_thread, params))) - die(1, NULL, "", "Couldn't create initialization thread: "); + errno = pthread_create(&child, &detached, init_thread, params); + if (errno) + die(1, NULL, "", "Couldn't create initialization thread: "); - while (1) { - conn = (connection_t *) must_malloc("connection state", - sizeof(connection_t)); - conn->params = params; - conn->mount_point = ""; + while (1) { + conn = (connection_t *)must_malloc("connection state", + sizeof(connection_t)); + conn->params = params; + conn->mount_point = ""; - conn->sock = accept(params->data_sock, - &conn->sa_client, &conn->socklen_client); - if (conn->sock < 0) - die(1, params, "accept", ""); + conn->sock = accept(params->data_sock, + &conn->sa_client, &conn->socklen_client); + if (conn->sock < 0) + die(1, params, "accept", ""); - // TODO: check for socket read conditions e.g. EAGAIN - read_count = read(conn->sock, &subproto_selector, 1); - if (read_count <= 0) - die(1, params, "read subprotocol selector", ""); + /* TODO: check for socket read conditions e.g.EAGAIN */ + read_count = read(conn->sock, &subproto_selector, 1); + if (read_count <= 0) + die(1, params, "read subprotocol selector", ""); - switch (subproto_selector) { - case 'm': - conn->type_descr = "mount"; - connection_handler_thread = mount_thread; - break; - case 'e': - conn->type_descr = "event"; - connection_handler_thread = event_thread; - break; - default: - die(1, params, NULL, "Unknown subprotocol type '%c'", subproto_selector); - } + switch (subproto_selector) { + case 'm': + conn->type_descr = "mount"; + connection_handler_thread = mount_thread; + break; + case 'e': + conn->type_descr = "event"; + connection_handler_thread = event_thread; + break; + default: + die(1, params, NULL, + "Unknown subprotocol type '%c'", subproto_selector); + } - if ((errno = pthread_create(&child, &detached, - connection_handler_thread, conn))) - die(1, params, "", "Couldn't create thread for %s connection: ", - conn->type_descr); + errno = pthread_create(&child, &detached, + connection_handler_thread, conn); + if (errno) + die(1, params, "", + "Couldn't create thread for %s connection: ", + conn->type_descr); - if (debug) log_time(conn->params, "thread spawned\n"); - } + if (debug) + log_time(conn->params, "thread spawned\n"); + } } -int main(int argc, char * argv[]) { - parameters params; - struct rlimit core_limit; +int main(int argc, char *argv[]) +{ + parameters params; + struct rlimit core_limit; - core_limit.rlim_cur = RLIM_INFINITY; - core_limit.rlim_max = RLIM_INFINITY; - if (setrlimit(RLIMIT_CORE, &core_limit)) - die(1, NULL, "", "Couldn't set RLIMIT_CORE to RLIM_INFINITY"); + core_limit.rlim_cur = RLIM_INFINITY; + core_limit.rlim_max = RLIM_INFINITY; + if (setrlimit(RLIMIT_CORE, &core_limit)) + die(1, NULL, "", "Couldn't set RLIMIT_CORE to RLIM_INFINITY"); - openlog(argv[0], LOG_CONS | LOG_PERROR | LOG_NDELAY, LOG_DAEMON); + openlog(argv[0], LOG_CONS | LOG_PERROR | LOG_NDELAY, LOG_DAEMON); - parse_parameters(argc, argv, ¶ms); - setup_debug(); + parse_parameters(argc, argv, ¶ms); + setup_debug(); - if ((errno = pthread_attr_setdetachstate(&detached, - PTHREAD_CREATE_DETACHED))) - die(1, NULL, "Couldn't set pthread detach state", ""); + errno = pthread_attr_setdetachstate(&detached, PTHREAD_CREATE_DETACHED); + if (errno) + die(1, NULL, "Couldn't set pthread detach state", ""); - if (params.logfile != NULL) { - params.logfile_fd = open(params.logfile, O_WRONLY | O_APPEND | O_CREAT); - if (params.logfile_fd == -1) - die(1, NULL, "", "Couldn't open log file %s: ", params.logfile); - } + if (params.logfile != NULL) { + params.logfile_fd = open(params.logfile, + O_WRONLY | O_APPEND | O_CREAT); + if (params.logfile_fd == -1) + die(1, NULL, "", + "Couldn't open log file %s: ", params.logfile); + } + params.data_sock = bind_socket(params.socket); + serve(¶ms); - params.data_sock = bind_socket(params.socket); - serve(¶ms); - - return 0; + return 0; } diff --git a/alpine/packages/transfused/transfused.h b/alpine/packages/transfused/transfused.h index 8bce1d9df..ba979bf68 100644 --- a/alpine/packages/transfused/transfused.h +++ b/alpine/packages/transfused/transfused.h @@ -1,37 +1,9 @@ +#ifndef _TRANSFUSED_H_ +#define _TRANSFUSED_H_ + #include #include -typedef struct { - char * server; - char * socket; - char * fusermount; - char * pidfile; - char * logfile; - int logfile_fd; - int ctl_sock; - int data_sock; - pthread_mutex_t ctl_lock; -} parameters; - -typedef struct { - parameters * params; - char * type_descr; - char * mount_point; - struct sockaddr sa_client; - socklen_t socklen_client; - int sock; -} connection_t; - -pthread_attr_t detached; - -void * must_malloc(char *const descr, size_t size); - -void lock(char *const descr, pthread_mutex_t * mutex); - -void unlock(char *const descr, pthread_mutex_t * mutex); - -void write_exactly(char * descr, int fd, void * buf, size_t nbyte); - #define IN_BUFSZ ((1 << 20) + 16) #define OUT_BUFSZ ((1 << 20) + 64) #define EVENT_BUFSZ 4096 @@ -49,7 +21,7 @@ void write_exactly(char * descr, int fd, void * buf, size_t nbyte); #define TRUNCATE_SYSCALL 4 #define CHMOD_SYSCALL 5 #define MKNOD_REG_SYSCALL 6 -// these could be turned into an enum probably but... C standard nausea +/* these could be turned into an enum probably but...C standard nausea */ #define MOUNT_SUITABILITY_REQUEST 1 #define EXPORT_SUITABILITY_REQUEST 2 @@ -59,3 +31,33 @@ void write_exactly(char * descr, int fd, void * buf, size_t nbyte); #define PONG_REPLY 3 #define MOUNT_SUITABILITY_REPLY 4 #define TRANSFUSE_NOTIFY_CHANNEL 5 + +typedef struct { + char *server; + char *socket; + char *fusermount; + char *pidfile; + char *logfile; + int logfile_fd; + int ctl_sock; + int data_sock; + pthread_mutex_t ctl_lock; +} parameters; + +typedef struct { + parameters *params; + char *type_descr; + char *mount_point; + struct sockaddr sa_client; + socklen_t socklen_client; + int sock; +} connection_t; + +pthread_attr_t detached; + +void *must_malloc(char *const descr, size_t size); +void lock(char *const descr, pthread_mutex_t *mutex); +void unlock(char *const descr, pthread_mutex_t *mutex); +void write_exactly(char *descr, int fd, void *buf, size_t nbyte); + +#endif /* _TRANSFUSED_H_ */ diff --git a/alpine/packages/transfused/transfused_log.c b/alpine/packages/transfused/transfused_log.c index 9b104031f..287cfbaf9 100644 --- a/alpine/packages/transfused/transfused_log.c +++ b/alpine/packages/transfused/transfused_log.c @@ -15,232 +15,243 @@ #include #include "transfused.h" +#include "transfused_log.h" -void log_timestamp(int fd) { - char timestamp[26]; - int msec; - struct tm* tm_info; - struct timeval tv; - - gettimeofday(&tv, NULL); - - msec = lrint(tv.tv_usec/1000.0); - if (msec >= 1000) { - msec -= 1000; - tv.tv_sec++; - } - - tm_info = localtime(&tv.tv_sec); - - strftime(timestamp, 26, "%Y-%m-%d %H:%M:%S", tm_info); - dprintf(fd, "%s.%03d ", timestamp, msec); -} - -void die -(int exit_code, parameters * params, const char * parg, const char * fmt, ...); - -void vlog_sock_locked -(int fd, uint16_t msg_type, const char * fmt, va_list args) { - int rc, len; - va_list targs; - char * fill; - - va_copy(targs, args); - len = vsnprintf(NULL, 0, fmt, targs); - if (len < 0) die(1, NULL, NULL, "Couldn't log due to vsnprintf failure"); - va_end(targs); - - rc = len + 4 + 2; // 4 for length itself and 2 for message type - write_exactly("vlog_sock_locked", fd, (uint32_t *) &rc, sizeof(uint32_t)); - write_exactly("vlog_sock_locked", fd, &msg_type, sizeof(uint16_t)); - - va_copy(targs, args); - rc = vdprintf(fd, fmt, targs); - if (rc < 0) die(1, NULL, "Couldn't send log message with vdprintf", ""); - va_end(targs); - - if (rc < len) { // we didn't write the whole message :-( - rc = len - rc; - fill = (char *) calloc(rc, 1); - if (fill == NULL) die(1, NULL, "vlog_sock_locked fill", ""); - write_exactly("vlog_sock_locked fill", fd, fill, rc); - } -} - -void log_sock_locked(int fd, uint16_t msg_type, const char * fmt, ...) { - va_list args; - - va_start(args, fmt); - - vlog_sock_locked(fd, msg_type, fmt, args); - - va_end(args); -} - -void die -(int exit_code, parameters * params, const char * parg, const char * fmt, ...) +void log_timestamp(int fd) { - va_list argp, targs; - int in_errno = errno; - int fd = 0; + char timestamp[26]; + int msec; + struct tm *tm_info; + struct timeval tv; - if (params != NULL) { - fd = params->ctl_sock; - lock("die ctl_lock", ¶ms->ctl_lock); - } + gettimeofday(&tv, NULL); - va_start(argp, fmt); - va_copy(targs, argp); - vsyslog(LOG_CRIT, fmt, targs); - va_end(targs); + msec = lrint(tv.tv_usec / 1000.0); + if (msec >= 1000) { + msec -= 1000; + tv.tv_sec++; + } + tm_info = localtime(&tv.tv_sec); - if (fd != 0) vlog_sock_locked(fd, TRANSFUSE_LOG_ERROR, fmt, argp); - va_end(argp); - - if (parg != NULL) { - if (*parg != 0) { - syslog(LOG_CRIT, "%s: %s", parg, strerror(in_errno)); - if (fd != 0) - log_sock_locked(fd, TRANSFUSE_LOG_ERROR, - "%s: %s", parg, strerror(in_errno)); - } else { - syslog(LOG_CRIT, "%s", strerror(in_errno)); - if (fd != 0) - log_sock_locked(fd, TRANSFUSE_LOG_ERROR, "%s", strerror(in_errno)); - } - } - - if (fd != 0) close(fd); // flush - exit(exit_code); - // Nobody else should die before we terminate everything - unlock("die ctl_lock", ¶ms->ctl_lock); + strftime(timestamp, 26, "%Y-%m-%d %H:%M:%S", tm_info); + dprintf(fd, "%s.%03d ", timestamp, msec); } -void vlog_locked -(parameters * params, uint16_t msg_type, const char * fmt, va_list args) { - int rc; - int fd = params->ctl_sock; - va_list targs; +void vlog_sock_locked(int fd, uint16_t msg_type, const char *fmt, va_list args) +{ + int rc, len; + va_list targs; + char *fill; - if (fd != 0) vlog_sock_locked(fd, msg_type, fmt, args); - else { - va_copy(targs, args); - // TODO: translate msg_type to syslog message type - vsyslog(LOG_INFO, fmt, targs); - va_end(targs); + va_copy(targs, args); + len = vsnprintf(NULL, 0, fmt, targs); + if (len < 0) + die(1, NULL, NULL, "Couldn't log due to vsnprintf failure"); + va_end(targs); - fd = params->logfile_fd; - if (fd != 0) { - va_copy(targs, args); - // TODO: include message type? - rc = vdprintf(fd, fmt, targs); - if (rc < 0) die(1, NULL, "Couldn't write log message with vdprintf", ""); - va_end(targs); - } - } + /* 4 for length itself and 2 for message type */ + rc = len + 4 + 2; + write_exactly("vlog_sock_locked", fd, + (uint32_t *)&rc, sizeof(uint32_t)); + write_exactly("vlog_sock_locked", fd, &msg_type, sizeof(uint16_t)); + + va_copy(targs, args); + rc = vdprintf(fd, fmt, targs); + if (rc < 0) + die(1, NULL, "Couldn't send log message with vdprintf", ""); + va_end(targs); + + if (rc < len) { + /* we didn't write the whole message :-( */ + rc = len - rc; + fill = (char *)calloc(rc, 1); + if (fill == NULL) + die(1, NULL, "vlog_sock_locked fill", ""); + write_exactly("vlog_sock_locked fill", fd, fill, rc); + } } -void vlog_time_locked -(parameters * params, uint16_t msg_type, const char * fmt, va_list args) { - int fd = params->logfile_fd; +void log_sock_locked(int fd, uint16_t msg_type, const char *fmt, ...) +{ + va_list args; - if (fd != 0 && params->ctl_sock == 0) log_timestamp(fd); - vlog_locked(params, msg_type, fmt, args); + va_start(args, fmt); + vlog_sock_locked(fd, msg_type, fmt, args); + va_end(args); } -void log_time_locked -(parameters * params, uint16_t msg_type, const char * fmt, ...) { - va_list args; +void die(int exit_code, parameters *params, const char *parg, + const char *fmt, ...) +{ + va_list argp, targs; + int in_errno = errno; + int fd = 0; - va_start(args, fmt); + if (params != NULL) { + fd = params->ctl_sock; + lock("die ctl_lock", ¶ms->ctl_lock); + } - vlog_time_locked(params, msg_type, fmt, args); + va_start(argp, fmt); + va_copy(targs, argp); + vsyslog(LOG_CRIT, fmt, targs); + va_end(targs); - va_end(args); + if (fd != 0) + vlog_sock_locked(fd, TRANSFUSE_LOG_ERROR, fmt, argp); + va_end(argp); + + if (parg != NULL) { + if (*parg != 0) { + syslog(LOG_CRIT, "%s: %s", parg, strerror(in_errno)); + if (fd != 0) + log_sock_locked(fd, TRANSFUSE_LOG_ERROR, + "%s: %s", parg, strerror(in_errno)); + } else { + syslog(LOG_CRIT, "%s", strerror(in_errno)); + if (fd != 0) + log_sock_locked(fd, TRANSFUSE_LOG_ERROR, + "%s", strerror(in_errno)); + } + } + if (fd != 0) + close(fd); /* flush */ + exit(exit_code); + /* Nobody else should die before we terminate everything */ + unlock("die ctl_lock", ¶ms->ctl_lock); } -void log_time(parameters * params, const char * fmt, ...) { - va_list args; +void vlog_locked(parameters *params, uint16_t msg_type, + const char *fmt, va_list args) +{ + int rc; + int fd = params->ctl_sock; + va_list targs; - va_start(args, fmt); + if (fd != 0) { + vlog_sock_locked(fd, msg_type, fmt, args); + } else { + va_copy(targs, args); + /* TODO: translate msg_type to syslog message type */ + vsyslog(LOG_INFO, fmt, targs); + va_end(targs); - lock("log_time ctl_lock", ¶ms->ctl_lock); - vlog_time_locked(params, TRANSFUSE_LOG_ERROR, fmt, args); - unlock("log_time ctl_lock", ¶ms->ctl_lock); - - va_end(args); + fd = params->logfile_fd; + if (fd != 0) { + va_copy(targs, args); + /* TODO: include message type? */ + rc = vdprintf(fd, fmt, targs); + if (rc < 0) + die(1, NULL, + "Couldn't write log message with vdprintf", ""); + va_end(targs); + } + } } -void log_notice_time(parameters * params, const char * fmt, ...) { - va_list args; +void vlog_time_locked(parameters *params, uint16_t msg_type, + const char *fmt, va_list args) +{ + int fd = params->logfile_fd; - va_start(args, fmt); + if (fd != 0 && params->ctl_sock == 0) + log_timestamp(fd); + vlog_locked(params, msg_type, fmt, args); +} - lock("log_time ctl_lock", ¶ms->ctl_lock); - vlog_time_locked(params, TRANSFUSE_LOG_NOTICE, fmt, args); - unlock("log_time ctl_lock", ¶ms->ctl_lock); +void log_time_locked(parameters *params, uint16_t msg_type, + const char *fmt, ...) +{ + va_list args; - va_end(args); + va_start(args, fmt); + vlog_time_locked(params, msg_type, fmt, args); + va_end(args); +} + +void log_time(parameters *params, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + lock("log_time ctl_lock", ¶ms->ctl_lock); + vlog_time_locked(params, TRANSFUSE_LOG_ERROR, fmt, args); + unlock("log_time ctl_lock", ¶ms->ctl_lock); + va_end(args); +} + +void log_notice_time(parameters *params, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + lock("log_time ctl_lock", ¶ms->ctl_lock); + vlog_time_locked(params, TRANSFUSE_LOG_NOTICE, fmt, args); + unlock("log_time ctl_lock", ¶ms->ctl_lock); + + va_end(args); } typedef struct { - parameters * params; - char * msg; + parameters *params; + char *msg; } log_thread_state; -void * log_time_thread(void * log_state_ptr) { - log_thread_state * log_state = log_state_ptr; +void *log_time_thread(void *log_state_ptr) +{ + log_thread_state *log_state = log_state_ptr; - log_time(log_state->params, log_state->msg); + log_time(log_state->params, log_state->msg); - free(log_state->msg); - free(log_state); - - return NULL; + free(log_state->msg); + free(log_state); + return NULL; } -void thread_log_time(connection_t * conn, const char * fmt, ...) { - pthread_t logger; - va_list args; - log_thread_state * log_state; +void thread_log_time(connection_t *conn, const char *fmt, ...) +{ + log_thread_state *log_state; + pthread_t logger; + va_list args; - log_state = must_malloc("thread_log_time log_state", - sizeof(log_thread_state)); - log_state->params = conn->params; + log_state = must_malloc("thread_log_time log_state", + sizeof(log_thread_state)); + log_state->params = conn->params; - va_start(args, fmt); - if (vasprintf(&log_state->msg, fmt, args) == -1) - die(1, conn->params, "Couldn't allocate thread_log_time message", ""); - va_end(args); + va_start(args, fmt); + if (vasprintf(&log_state->msg, fmt, args) == -1) + die(1, conn->params, + "Couldn't allocate thread_log_time message", ""); + va_end(args); - // TODO: We currently spawn a new thread for every message. This is - // far from ideal but fine for now as we anticipate thread-sensitive - // log demand to be low. - - if ((errno = pthread_create(&logger, &detached, log_time_thread, log_state))) - die(1, conn->params, "", - "Couldn't create log thread for %s connection %s: ", - conn->type_descr, conn->mount_point); + /* TODO: We currently spawn a new thread for every + * message. This is far from ideal but fine for now as we + * anticipate thread-sensitive log demand to be low. */ + errno = pthread_create(&logger, &detached, log_time_thread, log_state); + if (errno) + die(1, conn->params, "", + "Couldn't create log thread for %s connection %s: ", + conn->type_descr, conn->mount_point); } -void log_continue_locked(parameters * params, const char * fmt, ...) { - va_list args; +void log_continue_locked(parameters *params, const char *fmt, ...) +{ + va_list args; - va_start(args, fmt); - - vlog_locked(params, TRANSFUSE_LOG_ERROR, fmt, args); - - va_end(args); + va_start(args, fmt); + vlog_locked(params, TRANSFUSE_LOG_ERROR, fmt, args); + va_end(args); } -void log_continue(parameters * params, const char * fmt, ...) { - va_list args; +void log_continue(parameters *params, const char *fmt, ...) +{ + va_list args; - va_start(args, fmt); + va_start(args, fmt); - lock("log_continue ctl_lock", ¶ms->ctl_lock); - vlog_locked(params, TRANSFUSE_LOG_ERROR, fmt, args); - unlock("log_continue ctl_lock", ¶ms->ctl_lock); + lock("log_continue ctl_lock", ¶ms->ctl_lock); + vlog_locked(params, TRANSFUSE_LOG_ERROR, fmt, args); + unlock("log_continue ctl_lock", ¶ms->ctl_lock); - va_end(args); + va_end(args); } diff --git a/alpine/packages/transfused/transfused_log.h b/alpine/packages/transfused/transfused_log.h index ab146d30e..e2176a1e4 100644 --- a/alpine/packages/transfused/transfused_log.h +++ b/alpine/packages/transfused/transfused_log.h @@ -1,27 +1,26 @@ +#ifndef _TRANSFUSED_LOG_H_ +#define _TRANSFUSED_LOG_H_ + #include #include #include "transfused.h" -void die -(int exit_code, parameters * params, const char * perror_arg, - const char * fmt, ...); +void die(int exit_code, parameters *params, const char *perror_arg, + const char *fmt, ...); -void vlog_locked -(parameters * params, uint16_t msg_type, const char * fmt, va_list args); +void vlog_locked(parameters *params, uint16_t msg_type, + const char *fmt, va_list args); +void vlog_time_locked(parameters *params, uint16_t msg_type, + const char *fmt, va_list args); -void vlog_time_locked -(parameters * params, uint16_t msg_type, const char * fmt, va_list args); +void log_time_locked(parameters *params, uint16_t msg_type, + const char *fmt, ...); -void log_time_locked -(parameters * params, uint16_t msg_type, const char * fmt, ...); +void log_time(parameters *params, const char *fmt, ...); +void log_notice_time(parameters *params, const char *fmt, ...); +void thread_log_time(connection_t *conn, const char *fmt, ...); +void log_continue_locked(parameters *params, const char *fmt, ...); +void log_continue(parameters *params, const char *fmt, ...); -void log_time(parameters * params, const char * fmt, ...); - -void log_notice_time(parameters * params, const char * fmt, ...); - -void thread_log_time(connection_t * conn, const char * fmt, ...); - -void log_continue_locked(parameters * params, const char * fmt, ...); - -void log_continue(parameters * params, const char * fmt, ...); +#endif /* _TRANSFUSED_LOG_H_ */ diff --git a/alpine/packages/transfused/transfused_vsock.c b/alpine/packages/transfused/transfused_vsock.c index 08408dd0e..04cdce6da 100644 --- a/alpine/packages/transfused/transfused_vsock.c +++ b/alpine/packages/transfused/transfused_vsock.c @@ -7,93 +7,100 @@ #include "transfused_log.h" -long parse_cid(const char * address) { - char * end = NULL; - long cid = strtol(address, &end, 10); - if (address == end || *end != ':') { - *end = 0; - die(2, NULL, NULL, "Invalid vsock cid: %s", address); - } - return cid; +long parse_cid(const char *address) +{ + char *end = NULL; + long cid = strtol(address, &end, 10); + + if (address == end || *end != ':') { + *end = 0; + die(2, NULL, NULL, "Invalid vsock cid: %s", address); + } + return cid; } -long parse_port(const char * port_str) { - char * end = NULL; - long port = strtol(port_str, &end, 10); - if (port_str == end || *end != '\0') { - *end = 0; - die(2, NULL, NULL, "Invalid vsock port: %s", port_str); - } - return port; +long parse_port(const char *port_str) +{ + char *end = NULL; + long port = strtol(port_str, &end, 10); + + if (port_str == end || *end != '\0') { + *end = 0; + die(2, NULL, NULL, "Invalid vsock port: %s", port_str); + } + return port; } -int find_colon(const char * address) { - int colon = 0; +int find_colon(const char *address) +{ + int colon = 0; - while (address[colon] != '\0') - if (address[colon] == ':') break; - else colon++; + while (address[colon] != '\0') + if (address[colon] == ':') + break; + else + colon++; - if (address[colon] == '\0') - die(2, NULL, NULL, "Missing port in vsock address %s", address); + if (address[colon] == '\0') + die(2, NULL, NULL, "Missing port in vsock address %s", address); - return colon; + return colon; } -int bind_vsock(const char * address) { - long cid, port; - int colon; +int bind_vsock(const char *address) +{ + long cid, port; + int colon; + struct sockaddr_vm sa_listen = { + .svm_family = AF_VSOCK, + }; + int sock_fd; - struct sockaddr_vm sa_listen = { - .svm_family = AF_VSOCK, - }; + colon = find_colon(address); - int sock_fd; + if (address[0] == '_' && colon == 1) + cid = VMADDR_CID_ANY; + else + cid = parse_cid(address); - colon = find_colon(address); + port = parse_port(address + colon + 1); - if (address[0] == '_' && colon == 1) cid = VMADDR_CID_ANY; - else cid = parse_cid(address); + sa_listen.svm_cid = cid; + sa_listen.svm_port = port; - port = parse_port(address + colon + 1); + sock_fd = socket(AF_VSOCK, SOCK_STREAM, 0); + if (sock_fd < 0) + die(1, NULL, "socket(AF_VSOCK)", ""); - sa_listen.svm_cid = cid; - sa_listen.svm_port = port; + if (bind(sock_fd, (struct sockaddr *)&sa_listen, sizeof(sa_listen))) + die(1, NULL, "bind(AF_VSOCK)", ""); - sock_fd = socket(AF_VSOCK, SOCK_STREAM, 0); - if (sock_fd < 0) - die(1, NULL, "socket(AF_VSOCK)", ""); - - if (bind(sock_fd, (struct sockaddr *) &sa_listen, sizeof(sa_listen))) - die(1, NULL, "bind(AF_VSOCK)", ""); - - return sock_fd; + return sock_fd; } -int connect_vsock(const char * address) { - long cid, port; - int colon; +int connect_vsock(const char *address) +{ + long cid, port; + int colon; + struct sockaddr_vm sa_connect = { + .svm_family = AF_VSOCK, + }; + int sock_fd; - struct sockaddr_vm sa_connect = { - .svm_family = AF_VSOCK, - }; + colon = find_colon(address); - int sock_fd; + cid = parse_cid(address); + port = parse_port(address + colon + 1); - colon = find_colon(address); + sa_connect.svm_cid = cid; + sa_connect.svm_port = port; - cid = parse_cid(address); - port = parse_port(address + colon + 1); + sock_fd = socket(AF_VSOCK, SOCK_STREAM, 0); + if (sock_fd < 0) + die(1, NULL, "socket(AF_VSOCK)", ""); - sa_connect.svm_cid = cid; - sa_connect.svm_port = port; + if (connect(sock_fd, (struct sockaddr *)&sa_connect, sizeof(sa_connect))) + die(1, NULL, "connect(AF_VSOCK)", ""); - sock_fd = socket(AF_VSOCK, SOCK_STREAM, 0); - if (sock_fd < 0) - die(1, NULL, "socket(AF_VSOCK)", ""); - - if (connect(sock_fd, (struct sockaddr *) &sa_connect, sizeof(sa_connect))) - die(1, NULL, "connect(AF_VSOCK)", ""); - - return sock_fd; + return sock_fd; } diff --git a/alpine/packages/transfused/transfused_vsock.h b/alpine/packages/transfused/transfused_vsock.h index a6bef6f08..6be8979e4 100644 --- a/alpine/packages/transfused/transfused_vsock.h +++ b/alpine/packages/transfused/transfused_vsock.h @@ -1,2 +1,7 @@ -int bind_vsock(const char * address); -int connect_vsock(const char * address); +#ifndef _TRANSFUSED_VSOCK_H_ +#define _TRANSFUSED_VSOCK_H_ + +int bind_vsock(const char *address); +int connect_vsock(const char *address); + +#endif /* _TRANSFUSED_VSOCK_H_ */