xref: /unit/src/nxt_fs.c (revision 1674:3828127016b3)
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