11489St.nateldemoura@f5.com /*
21489St.nateldemoura@f5.com * Copyright (C) NGINX, Inc.
31489St.nateldemoura@f5.com */
41489St.nateldemoura@f5.com
51489St.nateldemoura@f5.com #include <nxt_main.h>
61489St.nateldemoura@f5.com
71489St.nateldemoura@f5.com #if (NXT_HAVE_FREEBSD_NMOUNT)
81489St.nateldemoura@f5.com #include <sys/param.h>
91489St.nateldemoura@f5.com #include <sys/uio.h>
101489St.nateldemoura@f5.com #endif
111489St.nateldemoura@f5.com
121489St.nateldemoura@f5.com
131489St.nateldemoura@f5.com static nxt_int_t nxt_fs_mkdir(const u_char *dir, mode_t mode);
141489St.nateldemoura@f5.com
151489St.nateldemoura@f5.com
161489St.nateldemoura@f5.com #if (NXT_HAVE_LINUX_MOUNT)
171489St.nateldemoura@f5.com
181489St.nateldemoura@f5.com nxt_int_t
nxt_fs_mount(nxt_task_t * task,nxt_fs_mount_t * mnt)191489St.nateldemoura@f5.com nxt_fs_mount(nxt_task_t *task, nxt_fs_mount_t *mnt)
201489St.nateldemoura@f5.com {
211673St.nateldemoura@f5.com int rc;
221673St.nateldemoura@f5.com const char *fsname;
231673St.nateldemoura@f5.com unsigned long flags;
241673St.nateldemoura@f5.com
251673St.nateldemoura@f5.com flags = 0;
261673St.nateldemoura@f5.com
271673St.nateldemoura@f5.com switch (mnt->type) {
281673St.nateldemoura@f5.com case NXT_FS_BIND:
291673St.nateldemoura@f5.com if (nxt_slow_path(mnt->flags != 0)) {
301673St.nateldemoura@f5.com nxt_log(task, NXT_LOG_WARN,
311673St.nateldemoura@f5.com "bind mount ignores additional flags");
321673St.nateldemoura@f5.com }
331673St.nateldemoura@f5.com
341673St.nateldemoura@f5.com fsname = "bind";
351673St.nateldemoura@f5.com flags = MS_BIND | MS_REC;
361673St.nateldemoura@f5.com break;
371673St.nateldemoura@f5.com
381673St.nateldemoura@f5.com case NXT_FS_PROC:
391673St.nateldemoura@f5.com fsname = "proc";
401673St.nateldemoura@f5.com goto getflags;
411673St.nateldemoura@f5.com
421673St.nateldemoura@f5.com case NXT_FS_TMP:
431673St.nateldemoura@f5.com fsname = "tmpfs";
441673St.nateldemoura@f5.com goto getflags;
451489St.nateldemoura@f5.com
461673St.nateldemoura@f5.com default:
471673St.nateldemoura@f5.com fsname = (const char *) mnt->name;
481673St.nateldemoura@f5.com
491673St.nateldemoura@f5.com getflags:
501673St.nateldemoura@f5.com
511673St.nateldemoura@f5.com if (mnt->flags & NXT_FS_FLAGS_NODEV) {
521673St.nateldemoura@f5.com flags |= MS_NODEV;
531673St.nateldemoura@f5.com }
541673St.nateldemoura@f5.com
551673St.nateldemoura@f5.com if (mnt->flags & NXT_FS_FLAGS_NOEXEC) {
561673St.nateldemoura@f5.com flags |= MS_NOEXEC;
571673St.nateldemoura@f5.com }
581673St.nateldemoura@f5.com
591673St.nateldemoura@f5.com if (mnt->flags & NXT_FS_FLAGS_NOSUID) {
601673St.nateldemoura@f5.com flags |= MS_NOSUID;
611673St.nateldemoura@f5.com }
621673St.nateldemoura@f5.com
631673St.nateldemoura@f5.com if (!(mnt->flags & NXT_FS_FLAGS_NOTIME)) {
641673St.nateldemoura@f5.com flags |= MS_RELATIME;
651673St.nateldemoura@f5.com }
661673St.nateldemoura@f5.com }
671673St.nateldemoura@f5.com
681673St.nateldemoura@f5.com rc = mount((const char *) mnt->src, (const char *) mnt->dst, fsname, flags,
691673St.nateldemoura@f5.com mnt->data);
701489St.nateldemoura@f5.com
711489St.nateldemoura@f5.com if (nxt_slow_path(rc < 0)) {
721673St.nateldemoura@f5.com nxt_alert(task, "mount(\"%s\", \"%s\", \"%s\", %ul, \"%s\") %E",
731673St.nateldemoura@f5.com mnt->src, mnt->dst, fsname, flags, mnt->data, nxt_errno);
741489St.nateldemoura@f5.com
751489St.nateldemoura@f5.com return NXT_ERROR;
761489St.nateldemoura@f5.com }
771489St.nateldemoura@f5.com
781489St.nateldemoura@f5.com return NXT_OK;
791489St.nateldemoura@f5.com }
801489St.nateldemoura@f5.com
811489St.nateldemoura@f5.com #elif (NXT_HAVE_FREEBSD_NMOUNT)
821489St.nateldemoura@f5.com
831489St.nateldemoura@f5.com nxt_int_t
nxt_fs_mount(nxt_task_t * task,nxt_fs_mount_t * mnt)841489St.nateldemoura@f5.com nxt_fs_mount(nxt_task_t *task, nxt_fs_mount_t *mnt)
851489St.nateldemoura@f5.com {
861673St.nateldemoura@f5.com int flags;
871580St.nateldemoura@f5.com u_char *data, *p, *end;
881580St.nateldemoura@f5.com size_t iovlen;
891580St.nateldemoura@f5.com nxt_int_t ret;
901673St.nateldemoura@f5.com const char *fsname;
911580St.nateldemoura@f5.com struct iovec iov[128];
921489St.nateldemoura@f5.com char errmsg[256];
931489St.nateldemoura@f5.com
941673St.nateldemoura@f5.com if (nxt_slow_path((mnt->flags & NXT_FS_FLAGS_NODEV) && !mnt->builtin)) {
951673St.nateldemoura@f5.com nxt_alert(task, "nmount(2) doesn't support \"nodev\" option");
961673St.nateldemoura@f5.com
971673St.nateldemoura@f5.com return NXT_ERROR;
981673St.nateldemoura@f5.com }
991673St.nateldemoura@f5.com
1001673St.nateldemoura@f5.com flags = 0;
1011489St.nateldemoura@f5.com
1021673St.nateldemoura@f5.com switch (mnt->type) {
1031673St.nateldemoura@f5.com case NXT_FS_BIND:
1041673St.nateldemoura@f5.com fsname = "nullfs";
1051673St.nateldemoura@f5.com break;
1061673St.nateldemoura@f5.com
1071673St.nateldemoura@f5.com case NXT_FS_PROC:
1081673St.nateldemoura@f5.com fsname = "procfs";
1091673St.nateldemoura@f5.com goto getflags;
1101673St.nateldemoura@f5.com
1111673St.nateldemoura@f5.com case NXT_FS_TMP:
1121673St.nateldemoura@f5.com fsname = "tmpfs";
1131673St.nateldemoura@f5.com goto getflags;
1141580St.nateldemoura@f5.com
1151673St.nateldemoura@f5.com default:
1161673St.nateldemoura@f5.com fsname = (const char *) mnt->name;
1171673St.nateldemoura@f5.com
1181673St.nateldemoura@f5.com getflags:
1191673St.nateldemoura@f5.com
1201673St.nateldemoura@f5.com if (mnt->flags & NXT_FS_FLAGS_NOEXEC) {
1211673St.nateldemoura@f5.com flags |= MNT_NOEXEC;
1221673St.nateldemoura@f5.com }
1231580St.nateldemoura@f5.com
1241673St.nateldemoura@f5.com if (mnt->flags & NXT_FS_FLAGS_NOSUID) {
1251673St.nateldemoura@f5.com flags |= MNT_NOSUID;
1261673St.nateldemoura@f5.com }
1271673St.nateldemoura@f5.com
1281673St.nateldemoura@f5.com if (mnt->flags & NXT_FS_FLAGS_NOTIME) {
1291673St.nateldemoura@f5.com flags |= MNT_NOATIME;
1301673St.nateldemoura@f5.com }
1311673St.nateldemoura@f5.com
1321673St.nateldemoura@f5.com if (mnt->flags & NXT_FS_FLAGS_RDONLY) {
1331673St.nateldemoura@f5.com flags |= MNT_RDONLY;
1341673St.nateldemoura@f5.com }
1351489St.nateldemoura@f5.com }
1361489St.nateldemoura@f5.com
1371489St.nateldemoura@f5.com iov[0].iov_base = (void *) "fstype";
1381489St.nateldemoura@f5.com iov[0].iov_len = 7;
1391673St.nateldemoura@f5.com iov[1].iov_base = (void *) fsname;
1401673St.nateldemoura@f5.com iov[1].iov_len = nxt_strlen(fsname) + 1;
1411489St.nateldemoura@f5.com iov[2].iov_base = (void *) "fspath";
1421489St.nateldemoura@f5.com iov[2].iov_len = 7;
1431489St.nateldemoura@f5.com iov[3].iov_base = (void *) mnt->dst;
1441489St.nateldemoura@f5.com iov[3].iov_len = nxt_strlen(mnt->dst) + 1;
1451489St.nateldemoura@f5.com iov[4].iov_base = (void *) "target";
1461489St.nateldemoura@f5.com iov[4].iov_len = 7;
1471489St.nateldemoura@f5.com iov[5].iov_base = (void *) mnt->src;
1481489St.nateldemoura@f5.com iov[5].iov_len = nxt_strlen(mnt->src) + 1;
1491489St.nateldemoura@f5.com iov[6].iov_base = (void *) "errmsg";
1501489St.nateldemoura@f5.com iov[6].iov_len = 7;
1511489St.nateldemoura@f5.com iov[7].iov_base = (void *) errmsg;
1521489St.nateldemoura@f5.com iov[7].iov_len = sizeof(errmsg);
1531489St.nateldemoura@f5.com
1541580St.nateldemoura@f5.com iovlen = 8;
1551580St.nateldemoura@f5.com
1561580St.nateldemoura@f5.com data = NULL;
1571580St.nateldemoura@f5.com
1581580St.nateldemoura@f5.com if (mnt->data != NULL) {
1591580St.nateldemoura@f5.com data = (u_char *) nxt_strdup(mnt->data);
1601580St.nateldemoura@f5.com if (nxt_slow_path(data == NULL)) {
1611580St.nateldemoura@f5.com return NXT_ERROR;
1621580St.nateldemoura@f5.com }
1631580St.nateldemoura@f5.com
1641580St.nateldemoura@f5.com end = data - 1;
1651580St.nateldemoura@f5.com
1661580St.nateldemoura@f5.com do {
1671580St.nateldemoura@f5.com p = end + 1;
1681580St.nateldemoura@f5.com end = nxt_strchr(p, '=');
1691580St.nateldemoura@f5.com if (end == NULL) {
1701580St.nateldemoura@f5.com break;
1711580St.nateldemoura@f5.com }
1721580St.nateldemoura@f5.com
1731580St.nateldemoura@f5.com *end = '\0';
1741580St.nateldemoura@f5.com
175*1674Svbart@nginx.com iov[iovlen].iov_base = (void *) p;
176*1674Svbart@nginx.com iov[iovlen].iov_len = (end - p) + 1;
177*1674Svbart@nginx.com
178*1674Svbart@nginx.com iovlen++;
1791580St.nateldemoura@f5.com
1801580St.nateldemoura@f5.com p = end + 1;
1811580St.nateldemoura@f5.com
1821580St.nateldemoura@f5.com end = nxt_strchr(p, ',');
1831580St.nateldemoura@f5.com if (end != NULL) {
1841580St.nateldemoura@f5.com *end = '\0';
1851580St.nateldemoura@f5.com }
1861580St.nateldemoura@f5.com
187*1674Svbart@nginx.com iov[iovlen].iov_base = (void *) p;
188*1674Svbart@nginx.com iov[iovlen].iov_len = nxt_strlen(p) + 1;
189*1674Svbart@nginx.com
190*1674Svbart@nginx.com iovlen++;
1911580St.nateldemoura@f5.com
1921580St.nateldemoura@f5.com } while (end != NULL && nxt_nitems(iov) > (iovlen + 2));
1931489St.nateldemoura@f5.com }
1941489St.nateldemoura@f5.com
1951580St.nateldemoura@f5.com ret = NXT_OK;
1961580St.nateldemoura@f5.com
1971673St.nateldemoura@f5.com if (nxt_slow_path(nmount(iov, iovlen, flags) < 0)) {
1981580St.nateldemoura@f5.com nxt_alert(task, "nmount(%p, %d, 0) %s", iov, iovlen, errmsg);
1991580St.nateldemoura@f5.com ret = NXT_ERROR;
2001580St.nateldemoura@f5.com }
2011580St.nateldemoura@f5.com
2021580St.nateldemoura@f5.com if (data != NULL) {
2031580St.nateldemoura@f5.com free(data);
2041580St.nateldemoura@f5.com }
2051580St.nateldemoura@f5.com
2061580St.nateldemoura@f5.com return ret;
2071489St.nateldemoura@f5.com }
2081489St.nateldemoura@f5.com
2091489St.nateldemoura@f5.com #endif
2101489St.nateldemoura@f5.com
2111489St.nateldemoura@f5.com
2121489St.nateldemoura@f5.com #if (NXT_HAVE_LINUX_UMOUNT2)
2131489St.nateldemoura@f5.com
2141489St.nateldemoura@f5.com void
nxt_fs_unmount(const u_char * path)2151489St.nateldemoura@f5.com nxt_fs_unmount(const u_char *path)
2161489St.nateldemoura@f5.com {
2171489St.nateldemoura@f5.com if (nxt_slow_path(umount2((const char *) path, MNT_DETACH) < 0)) {
2181489St.nateldemoura@f5.com nxt_thread_log_error(NXT_LOG_WARN, "umount2(%s, MNT_DETACH) %E",
2191489St.nateldemoura@f5.com path, nxt_errno);
2201489St.nateldemoura@f5.com }
2211489St.nateldemoura@f5.com }
2221489St.nateldemoura@f5.com
2231489St.nateldemoura@f5.com #elif (NXT_HAVE_UNMOUNT)
2241489St.nateldemoura@f5.com
2251489St.nateldemoura@f5.com void
nxt_fs_unmount(const u_char * path)2261489St.nateldemoura@f5.com nxt_fs_unmount(const u_char *path)
2271489St.nateldemoura@f5.com {
2281489St.nateldemoura@f5.com if (nxt_slow_path(unmount((const char *) path, MNT_FORCE) < 0)) {
2291489St.nateldemoura@f5.com nxt_thread_log_error(NXT_LOG_WARN, "unmount(%s) %E", path, nxt_errno);
2301489St.nateldemoura@f5.com }
2311489St.nateldemoura@f5.com }
2321489St.nateldemoura@f5.com
2331489St.nateldemoura@f5.com #endif
2341489St.nateldemoura@f5.com
2351489St.nateldemoura@f5.com
2361489St.nateldemoura@f5.com nxt_int_t
nxt_fs_mkdir_all(const u_char * dir,mode_t mode)2371489St.nateldemoura@f5.com nxt_fs_mkdir_all(const u_char *dir, mode_t mode)
2381489St.nateldemoura@f5.com {
2391489St.nateldemoura@f5.com char *start, *end, *dst;
2401489St.nateldemoura@f5.com size_t dirlen;
2411489St.nateldemoura@f5.com char path[PATH_MAX];
2421489St.nateldemoura@f5.com
2431489St.nateldemoura@f5.com dirlen = nxt_strlen(dir);
2441489St.nateldemoura@f5.com
2451489St.nateldemoura@f5.com nxt_assert(dirlen < PATH_MAX && dirlen > 1 && dir[0] == '/');
2461489St.nateldemoura@f5.com
2471489St.nateldemoura@f5.com dst = path;
2481489St.nateldemoura@f5.com start = end = (char *) dir;
2491489St.nateldemoura@f5.com
2501489St.nateldemoura@f5.com while (*start != '\0') {
2511489St.nateldemoura@f5.com if (*start == '/') {
2521489St.nateldemoura@f5.com *dst++ = *start++;
2531489St.nateldemoura@f5.com }
2541489St.nateldemoura@f5.com
2551489St.nateldemoura@f5.com end = strchr(start, '/');
2561489St.nateldemoura@f5.com if (end == NULL) {
2571489St.nateldemoura@f5.com end = ((char *)dir + dirlen);
2581489St.nateldemoura@f5.com }
2591489St.nateldemoura@f5.com
2601489St.nateldemoura@f5.com dst = nxt_cpymem(dst, start, end - start);
2611489St.nateldemoura@f5.com *dst = '\0';
2621489St.nateldemoura@f5.com
2631489St.nateldemoura@f5.com if (nxt_slow_path(nxt_fs_mkdir((u_char *) path, mode) != NXT_OK
2641489St.nateldemoura@f5.com && nxt_errno != EEXIST))
2651489St.nateldemoura@f5.com {
2661489St.nateldemoura@f5.com return NXT_ERROR;
2671489St.nateldemoura@f5.com }
2681489St.nateldemoura@f5.com
2691489St.nateldemoura@f5.com start = end;
2701489St.nateldemoura@f5.com }
2711489St.nateldemoura@f5.com
2721489St.nateldemoura@f5.com return NXT_OK;
2731489St.nateldemoura@f5.com }
2741489St.nateldemoura@f5.com
2751489St.nateldemoura@f5.com
2761489St.nateldemoura@f5.com static nxt_int_t
nxt_fs_mkdir(const u_char * dir,mode_t mode)2771489St.nateldemoura@f5.com nxt_fs_mkdir(const u_char *dir, mode_t mode)
2781489St.nateldemoura@f5.com {
2791489St.nateldemoura@f5.com if (nxt_fast_path(mkdir((const char *) dir, mode) == 0)) {
2801489St.nateldemoura@f5.com return NXT_OK;
2811489St.nateldemoura@f5.com }
2821489St.nateldemoura@f5.com
2831489St.nateldemoura@f5.com return NXT_ERROR;
2841489St.nateldemoura@f5.com }
285