summaryrefslogtreecommitdiffhomepage
path: root/src/nxt_fs_mount.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/nxt_fs_mount.c230
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