diff options
Diffstat (limited to 'src/nxt_fs_mount.c')
-rw-r--r-- | src/nxt_fs_mount.c | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/src/nxt_fs_mount.c b/src/nxt_fs_mount.c new file mode 100644 index 00000000..d9b384e4 --- /dev/null +++ b/src/nxt_fs_mount.c @@ -0,0 +1,230 @@ +/* + * Copyright (C) NGINX, Inc. + */ + +#include <nxt_main.h> + +#if (NXT_HAVE_FREEBSD_NMOUNT) +#include <sys/param.h> +#include <sys/uio.h> +#endif + + +#if (NXT_HAVE_LINUX_MOUNT) + +nxt_int_t +nxt_fs_mount(nxt_task_t *task, nxt_fs_mount_t *mnt) +{ + int rc; + const char *fsname; + unsigned long flags; + + flags = 0; + + switch (mnt->type) { + case NXT_FS_BIND: + if (nxt_slow_path(mnt->flags != 0)) { + nxt_log(task, NXT_LOG_WARN, + "bind mount ignores additional flags"); + } + + fsname = "bind"; + flags = MS_BIND | MS_REC; + break; + + case NXT_FS_PROC: + fsname = "proc"; + goto getflags; + + case NXT_FS_TMP: + fsname = "tmpfs"; + goto getflags; + + default: + fsname = (const char *) mnt->name; + + getflags: + + if (mnt->flags & NXT_FS_FLAGS_NODEV) { + flags |= MS_NODEV; + } + + if (mnt->flags & NXT_FS_FLAGS_NOEXEC) { + flags |= MS_NOEXEC; + } + + if (mnt->flags & NXT_FS_FLAGS_NOSUID) { + flags |= MS_NOSUID; + } + + if (!(mnt->flags & NXT_FS_FLAGS_NOTIME)) { + flags |= MS_RELATIME; + } + } + + rc = mount((const char *) mnt->src, (const char *) mnt->dst, fsname, flags, + mnt->data); + + if (nxt_slow_path(rc < 0)) { + nxt_alert(task, "mount(\"%s\", \"%s\", \"%s\", %ul, \"%s\") %E", + mnt->src, mnt->dst, fsname, flags, mnt->data, nxt_errno); + + return NXT_ERROR; + } + + return NXT_OK; +} + +#elif (NXT_HAVE_FREEBSD_NMOUNT) + +nxt_int_t +nxt_fs_mount(nxt_task_t *task, nxt_fs_mount_t *mnt) +{ + int flags; + u_char *data, *p, *end; + size_t iovlen; + nxt_int_t ret; + const char *fsname; + struct iovec iov[128]; + char errmsg[256]; + + if (nxt_slow_path((mnt->flags & NXT_FS_FLAGS_NODEV) && !mnt->builtin)) { + nxt_alert(task, "nmount(2) doesn't support \"nodev\" option"); + + return NXT_ERROR; + } + + flags = 0; + + switch (mnt->type) { + case NXT_FS_BIND: + fsname = "nullfs"; + break; + + case NXT_FS_PROC: + fsname = "procfs"; + goto getflags; + + case NXT_FS_TMP: + fsname = "tmpfs"; + goto getflags; + + default: + fsname = (const char *) mnt->name; + + getflags: + + if (mnt->flags & NXT_FS_FLAGS_NOEXEC) { + flags |= MNT_NOEXEC; + } + + if (mnt->flags & NXT_FS_FLAGS_NOSUID) { + flags |= MNT_NOSUID; + } + + if (mnt->flags & NXT_FS_FLAGS_NOTIME) { + flags |= MNT_NOATIME; + } + + if (mnt->flags & NXT_FS_FLAGS_RDONLY) { + flags |= MNT_RDONLY; + } + } + + iov[0].iov_base = (void *) "fstype"; + iov[0].iov_len = 7; + iov[1].iov_base = (void *) fsname; + iov[1].iov_len = nxt_strlen(fsname) + 1; + iov[2].iov_base = (void *) "fspath"; + iov[2].iov_len = 7; + iov[3].iov_base = (void *) mnt->dst; + iov[3].iov_len = nxt_strlen(mnt->dst) + 1; + iov[4].iov_base = (void *) "target"; + iov[4].iov_len = 7; + iov[5].iov_base = (void *) mnt->src; + iov[5].iov_len = nxt_strlen(mnt->src) + 1; + iov[6].iov_base = (void *) "errmsg"; + iov[6].iov_len = 7; + iov[7].iov_base = (void *) errmsg; + iov[7].iov_len = sizeof(errmsg); + + iovlen = 8; + + data = NULL; + + if (mnt->data != NULL) { + data = (u_char *) nxt_strdup(mnt->data); + if (nxt_slow_path(data == NULL)) { + return NXT_ERROR; + } + + end = data - 1; + + do { + p = end + 1; + end = nxt_strchr(p, '='); + if (end == NULL) { + break; + } + + *end = '\0'; + + iov[iovlen].iov_base = (void *) p; + iov[iovlen].iov_len = (end - p) + 1; + + iovlen++; + + p = end + 1; + + end = nxt_strchr(p, ','); + if (end != NULL) { + *end = '\0'; + } + + iov[iovlen].iov_base = (void *) p; + iov[iovlen].iov_len = nxt_strlen(p) + 1; + + iovlen++; + + } while (end != NULL && nxt_nitems(iov) > (iovlen + 2)); + } + + ret = NXT_OK; + + if (nxt_slow_path(nmount(iov, iovlen, flags) < 0)) { + nxt_alert(task, "nmount(%p, %d, 0) %s", iov, iovlen, errmsg); + ret = NXT_ERROR; + } + + if (data != NULL) { + free(data); + } + + return ret; +} + +#endif + + +#if (NXT_HAVE_LINUX_UMOUNT2) + +void +nxt_fs_unmount(const u_char *path) +{ + if (nxt_slow_path(umount2((const char *) path, MNT_DETACH) < 0)) { + nxt_thread_log_error(NXT_LOG_WARN, "umount2(%s, MNT_DETACH) %E", + path, nxt_errno); + } +} + +#elif (NXT_HAVE_UNMOUNT) + +void +nxt_fs_unmount(const u_char *path) +{ + if (nxt_slow_path(unmount((const char *) path, MNT_FORCE) < 0)) { + nxt_thread_log_error(NXT_LOG_WARN, "unmount(%s) %E", path, nxt_errno); + } +} + +#endif |