xref: /unit/src/nxt_fs.c (revision 1674:3828127016b3)
1 /*
2  * Copyright (C) NGINX, Inc.
3  */
4 
5 #include <nxt_main.h>
6 
7 #if (NXT_HAVE_FREEBSD_NMOUNT)
8 #include <sys/param.h>
9 #include <sys/uio.h>
10 #endif
11 
12 
13 static nxt_int_t nxt_fs_mkdir(const u_char *dir, mode_t mode);
14 
15 
16 #if (NXT_HAVE_LINUX_MOUNT)
17 
18 nxt_int_t
nxt_fs_mount(nxt_task_t * task,nxt_fs_mount_t * mnt)19 nxt_fs_mount(nxt_task_t *task, nxt_fs_mount_t *mnt)
20 {
21     int            rc;
22     const char     *fsname;
23     unsigned long  flags;
24 
25     flags = 0;
26 
27     switch (mnt->type) {
28     case NXT_FS_BIND:
29         if (nxt_slow_path(mnt->flags != 0)) {
30             nxt_log(task, NXT_LOG_WARN,
31                     "bind mount ignores additional flags");
32         }
33 
34         fsname = "bind";
35         flags = MS_BIND | MS_REC;
36         break;
37 
38     case NXT_FS_PROC:
39         fsname = "proc";
40         goto getflags;
41 
42     case NXT_FS_TMP:
43         fsname = "tmpfs";
44         goto getflags;
45 
46     default:
47         fsname = (const char *) mnt->name;
48 
49     getflags:
50 
51         if (mnt->flags & NXT_FS_FLAGS_NODEV) {
52             flags |= MS_NODEV;
53         }
54 
55         if (mnt->flags & NXT_FS_FLAGS_NOEXEC) {
56             flags |= MS_NOEXEC;
57         }
58 
59         if (mnt->flags & NXT_FS_FLAGS_NOSUID) {
60             flags |= MS_NOSUID;
61         }
62 
63         if (!(mnt->flags & NXT_FS_FLAGS_NOTIME)) {
64             flags |= MS_RELATIME;
65         }
66     }
67 
68     rc = mount((const char *) mnt->src, (const char *) mnt->dst, fsname, flags,
69                mnt->data);
70 
71     if (nxt_slow_path(rc < 0)) {
72         nxt_alert(task, "mount(\"%s\", \"%s\", \"%s\", %ul, \"%s\") %E",
73                   mnt->src, mnt->dst, fsname, flags, mnt->data, nxt_errno);
74 
75         return NXT_ERROR;
76     }
77 
78     return NXT_OK;
79 }
80 
81 #elif (NXT_HAVE_FREEBSD_NMOUNT)
82 
83 nxt_int_t
nxt_fs_mount(nxt_task_t * task,nxt_fs_mount_t * mnt)84 nxt_fs_mount(nxt_task_t *task, nxt_fs_mount_t *mnt)
85 {
86     int           flags;
87     u_char        *data, *p, *end;
88     size_t        iovlen;
89     nxt_int_t     ret;
90     const char    *fsname;
91     struct iovec  iov[128];
92     char          errmsg[256];
93 
94     if (nxt_slow_path((mnt->flags & NXT_FS_FLAGS_NODEV) && !mnt->builtin)) {
95         nxt_alert(task, "nmount(2) doesn't support \"nodev\" option");
96 
97         return NXT_ERROR;
98     }
99 
100     flags = 0;
101 
102     switch (mnt->type) {
103     case NXT_FS_BIND:
104         fsname = "nullfs";
105         break;
106 
107     case NXT_FS_PROC:
108         fsname = "procfs";
109         goto getflags;
110 
111     case NXT_FS_TMP:
112         fsname = "tmpfs";
113         goto getflags;
114 
115     default:
116         fsname = (const char *) mnt->name;
117 
118     getflags:
119 
120         if (mnt->flags & NXT_FS_FLAGS_NOEXEC) {
121             flags |= MNT_NOEXEC;
122         }
123 
124         if (mnt->flags & NXT_FS_FLAGS_NOSUID) {
125             flags |= MNT_NOSUID;
126         }
127 
128         if (mnt->flags & NXT_FS_FLAGS_NOTIME) {
129             flags |= MNT_NOATIME;
130         }
131 
132         if (mnt->flags & NXT_FS_FLAGS_RDONLY) {
133             flags |= MNT_RDONLY;
134         }
135     }
136 
137     iov[0].iov_base = (void *) "fstype";
138     iov[0].iov_len = 7;
139     iov[1].iov_base = (void *) fsname;
140     iov[1].iov_len = nxt_strlen(fsname) + 1;
141     iov[2].iov_base = (void *) "fspath";
142     iov[2].iov_len = 7;
143     iov[3].iov_base = (void *) mnt->dst;
144     iov[3].iov_len = nxt_strlen(mnt->dst) + 1;
145     iov[4].iov_base = (void *) "target";
146     iov[4].iov_len = 7;
147     iov[5].iov_base = (void *) mnt->src;
148     iov[5].iov_len = nxt_strlen(mnt->src) + 1;
149     iov[6].iov_base = (void *) "errmsg";
150     iov[6].iov_len = 7;
151     iov[7].iov_base = (void *) errmsg;
152     iov[7].iov_len = sizeof(errmsg);
153 
154     iovlen = 8;
155 
156     data = NULL;
157 
158     if (mnt->data != NULL) {
159         data = (u_char *) nxt_strdup(mnt->data);
160         if (nxt_slow_path(data == NULL)) {
161             return NXT_ERROR;
162         }
163 
164         end = data - 1;
165 
166         do {
167             p = end + 1;
168             end = nxt_strchr(p, '=');
169             if (end == NULL) {
170                 break;
171             }
172 
173             *end = '\0';
174 
175             iov[iovlen].iov_base = (void *) p;
176             iov[iovlen].iov_len = (end - p) + 1;
177 
178             iovlen++;
179 
180             p = end + 1;
181 
182             end = nxt_strchr(p, ',');
183             if (end != NULL) {
184                 *end = '\0';
185             }
186 
187             iov[iovlen].iov_base = (void *) p;
188             iov[iovlen].iov_len = nxt_strlen(p) + 1;
189 
190             iovlen++;
191 
192         } while (end != NULL && nxt_nitems(iov) > (iovlen + 2));
193     }
194 
195     ret = NXT_OK;
196 
197     if (nxt_slow_path(nmount(iov, iovlen, flags) < 0)) {
198         nxt_alert(task, "nmount(%p, %d, 0) %s", iov, iovlen, errmsg);
199         ret = NXT_ERROR;
200     }
201 
202     if (data != NULL) {
203         free(data);
204     }
205 
206     return ret;
207 }
208 
209 #endif
210 
211 
212 #if (NXT_HAVE_LINUX_UMOUNT2)
213 
214 void
nxt_fs_unmount(const u_char * path)215 nxt_fs_unmount(const u_char *path)
216 {
217     if (nxt_slow_path(umount2((const char *) path, MNT_DETACH) < 0)) {
218         nxt_thread_log_error(NXT_LOG_WARN, "umount2(%s, MNT_DETACH) %E",
219                              path, nxt_errno);
220     }
221 }
222 
223 #elif (NXT_HAVE_UNMOUNT)
224 
225 void
nxt_fs_unmount(const u_char * path)226 nxt_fs_unmount(const u_char *path)
227 {
228     if (nxt_slow_path(unmount((const char *) path, MNT_FORCE) < 0)) {
229         nxt_thread_log_error(NXT_LOG_WARN, "unmount(%s) %E", path, nxt_errno);
230     }
231 }
232 
233 #endif
234 
235 
236 nxt_int_t
nxt_fs_mkdir_all(const u_char * dir,mode_t mode)237 nxt_fs_mkdir_all(const u_char *dir, mode_t mode)
238 {
239     char    *start, *end, *dst;
240     size_t  dirlen;
241     char    path[PATH_MAX];
242 
243     dirlen = nxt_strlen(dir);
244 
245     nxt_assert(dirlen < PATH_MAX && dirlen > 1 && dir[0] == '/');
246 
247     dst = path;
248     start = end = (char *) dir;
249 
250     while (*start != '\0') {
251         if (*start == '/') {
252             *dst++ = *start++;
253         }
254 
255         end = strchr(start, '/');
256         if (end == NULL) {
257             end = ((char *)dir + dirlen);
258         }
259 
260         dst = nxt_cpymem(dst, start, end - start);
261         *dst = '\0';
262 
263         if (nxt_slow_path(nxt_fs_mkdir((u_char *) path, mode) != NXT_OK
264                           && nxt_errno != EEXIST))
265         {
266             return NXT_ERROR;
267         }
268 
269         start = end;
270     }
271 
272     return NXT_OK;
273 }
274 
275 
276 static nxt_int_t
nxt_fs_mkdir(const u_char * dir,mode_t mode)277 nxt_fs_mkdir(const u_char *dir, mode_t mode)
278 {
279     if (nxt_fast_path(mkdir((const char *) dir, mode) == 0)) {
280         return NXT_OK;
281     }
282 
283     return NXT_ERROR;
284 }
285