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 #if (NXT_HAVE_LINUX_MOUNT)
14
15 nxt_int_t
nxt_fs_mount(nxt_task_t * task,nxt_fs_mount_t * mnt)16 nxt_fs_mount(nxt_task_t *task, nxt_fs_mount_t *mnt)
17 {
18 int rc;
19 const char *fsname;
20 unsigned long flags;
21
22 flags = 0;
23
24 switch (mnt->type) {
25 case NXT_FS_BIND:
26 if (nxt_slow_path(mnt->flags != 0)) {
27 nxt_log(task, NXT_LOG_WARN,
28 "bind mount ignores additional flags");
29 }
30
31 fsname = "bind";
32 flags = MS_BIND | MS_REC;
33 break;
34
35 case NXT_FS_PROC:
36 fsname = "proc";
37 goto getflags;
38
39 case NXT_FS_TMP:
40 fsname = "tmpfs";
41 goto getflags;
42
43 default:
44 fsname = (const char *) mnt->name;
45
46 getflags:
47
48 if (mnt->flags & NXT_FS_FLAGS_NODEV) {
49 flags |= MS_NODEV;
50 }
51
52 if (mnt->flags & NXT_FS_FLAGS_NOEXEC) {
53 flags |= MS_NOEXEC;
54 }
55
56 if (mnt->flags & NXT_FS_FLAGS_NOSUID) {
57 flags |= MS_NOSUID;
58 }
59
60 if (!(mnt->flags & NXT_FS_FLAGS_NOTIME)) {
61 flags |= MS_RELATIME;
62 }
63 }
64
65 rc = mount((const char *) mnt->src, (const char *) mnt->dst, fsname, flags,
66 mnt->data);
67
68 if (nxt_slow_path(rc < 0)) {
69 nxt_alert(task, "mount(\"%s\", \"%s\", \"%s\", %ul, \"%s\") %E",
70 mnt->src, mnt->dst, fsname, flags, mnt->data, nxt_errno);
71
72 return NXT_ERROR;
73 }
74
75 return NXT_OK;
76 }
77
78 #elif (NXT_HAVE_FREEBSD_NMOUNT)
79
80 nxt_int_t
nxt_fs_mount(nxt_task_t * task,nxt_fs_mount_t * mnt)81 nxt_fs_mount(nxt_task_t *task, nxt_fs_mount_t *mnt)
82 {
83 int flags;
84 u_char *data, *p, *end;
85 size_t iovlen;
86 nxt_int_t ret;
87 const char *fsname;
88 struct iovec iov[128];
89 char errmsg[256];
90
91 if (nxt_slow_path((mnt->flags & NXT_FS_FLAGS_NODEV) && !mnt->builtin)) {
92 nxt_alert(task, "nmount(2) doesn't support \"nodev\" option");
93
94 return NXT_ERROR;
95 }
96
97 flags = 0;
98
99 switch (mnt->type) {
100 case NXT_FS_BIND:
101 fsname = "nullfs";
102 break;
103
104 case NXT_FS_PROC:
105 fsname = "procfs";
106 goto getflags;
107
108 case NXT_FS_TMP:
109 fsname = "tmpfs";
110 goto getflags;
111
112 default:
113 fsname = (const char *) mnt->name;
114
115 getflags:
116
117 if (mnt->flags & NXT_FS_FLAGS_NOEXEC) {
118 flags |= MNT_NOEXEC;
119 }
120
121 if (mnt->flags & NXT_FS_FLAGS_NOSUID) {
122 flags |= MNT_NOSUID;
123 }
124
125 if (mnt->flags & NXT_FS_FLAGS_NOTIME) {
126 flags |= MNT_NOATIME;
127 }
128
129 if (mnt->flags & NXT_FS_FLAGS_RDONLY) {
130 flags |= MNT_RDONLY;
131 }
132 }
133
134 iov[0].iov_base = (void *) "fstype";
135 iov[0].iov_len = 7;
136 iov[1].iov_base = (void *) fsname;
137 iov[1].iov_len = nxt_strlen(fsname) + 1;
138 iov[2].iov_base = (void *) "fspath";
139 iov[2].iov_len = 7;
140 iov[3].iov_base = (void *) mnt->dst;
141 iov[3].iov_len = nxt_strlen(mnt->dst) + 1;
142 iov[4].iov_base = (void *) "target";
143 iov[4].iov_len = 7;
144 iov[5].iov_base = (void *) mnt->src;
145 iov[5].iov_len = nxt_strlen(mnt->src) + 1;
146 iov[6].iov_base = (void *) "errmsg";
147 iov[6].iov_len = 7;
148 iov[7].iov_base = (void *) errmsg;
149 iov[7].iov_len = sizeof(errmsg);
150
151 iovlen = 8;
152
153 data = NULL;
154
155 if (mnt->data != NULL) {
156 data = (u_char *) nxt_strdup(mnt->data);
157 if (nxt_slow_path(data == NULL)) {
158 return NXT_ERROR;
159 }
160
161 end = data - 1;
162
163 do {
164 p = end + 1;
165 end = nxt_strchr(p, '=');
166 if (end == NULL) {
167 break;
168 }
169
170 *end = '\0';
171
172 iov[iovlen].iov_base = (void *) p;
173 iov[iovlen].iov_len = (end - p) + 1;
174
175 iovlen++;
176
177 p = end + 1;
178
179 end = nxt_strchr(p, ',');
180 if (end != NULL) {
181 *end = '\0';
182 }
183
184 iov[iovlen].iov_base = (void *) p;
185 iov[iovlen].iov_len = nxt_strlen(p) + 1;
186
187 iovlen++;
188
189 } while (end != NULL && nxt_nitems(iov) > (iovlen + 2));
190 }
191
192 ret = NXT_OK;
193
194 if (nxt_slow_path(nmount(iov, iovlen, flags) < 0)) {
195 nxt_alert(task, "nmount(%p, %d, 0) %s", iov, iovlen, errmsg);
196 ret = NXT_ERROR;
197 }
198
199 if (data != NULL) {
200 free(data);
201 }
202
203 return ret;
204 }
205
206 #endif
207
208
209 #if (NXT_HAVE_LINUX_UMOUNT2)
210
211 void
nxt_fs_unmount(const u_char * path)212 nxt_fs_unmount(const u_char *path)
213 {
214 if (nxt_slow_path(umount2((const char *) path, MNT_DETACH) < 0)) {
215 nxt_thread_log_error(NXT_LOG_WARN, "umount2(%s, MNT_DETACH) %E",
216 path, nxt_errno);
217 }
218 }
219
220 #elif (NXT_HAVE_UNMOUNT)
221
222 void
nxt_fs_unmount(const u_char * path)223 nxt_fs_unmount(const u_char *path)
224 {
225 if (nxt_slow_path(unmount((const char *) path, MNT_FORCE) < 0)) {
226 nxt_thread_log_error(NXT_LOG_WARN, "unmount(%s) %E", path, nxt_errno);
227 }
228 }
229
230 #endif
231