xref: /unit/src/nxt_fs.c (revision 1580:f1aefdf995d4)
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
19 nxt_fs_mount(nxt_task_t *task, nxt_fs_mount_t *mnt)
20 {
21     int  rc;
22 
23     rc = mount((const char *) mnt->src, (const char *) mnt->dst,
24                (const char *) mnt->fstype, mnt->flags, mnt->data);
25 
26     if (nxt_slow_path(rc < 0)) {
27         nxt_alert(task, "mount(\"%s\", \"%s\", \"%s\", %d, \"%s\") %E",
28                   mnt->src, mnt->dst, mnt->fstype, mnt->flags, mnt->data,
29                   nxt_errno);
30 
31         return NXT_ERROR;
32     }
33 
34     return NXT_OK;
35 }
36 
37 
38 #elif (NXT_HAVE_FREEBSD_NMOUNT)
39 
40 nxt_int_t
41 nxt_fs_mount(nxt_task_t *task, nxt_fs_mount_t *mnt)
42 {
43     u_char        *data, *p, *end;
44     size_t        iovlen;
45     nxt_int_t     ret;
46     const char    *fstype;
47     struct iovec  iov[128];
48     char          errmsg[256];
49 
50     if (nxt_strncmp(mnt->fstype, "bind", 4) == 0) {
51         fstype = "nullfs";
52 
53     } else if (nxt_strncmp(mnt->fstype, "proc", 4) == 0) {
54         fstype = "procfs";
55 
56     } else if (nxt_strncmp(mnt->fstype, "tmpfs", 5) == 0) {
57         fstype = "tmpfs";
58 
59     } else {
60         nxt_alert(task, "mount type \"%s\" not implemented.", mnt->fstype);
61         return NXT_ERROR;
62     }
63 
64     iov[0].iov_base = (void *) "fstype";
65     iov[0].iov_len = 7;
66     iov[1].iov_base = (void *) fstype;
67     iov[1].iov_len = nxt_strlen(fstype) + 1;
68     iov[2].iov_base = (void *) "fspath";
69     iov[2].iov_len = 7;
70     iov[3].iov_base = (void *) mnt->dst;
71     iov[3].iov_len = nxt_strlen(mnt->dst) + 1;
72     iov[4].iov_base = (void *) "target";
73     iov[4].iov_len = 7;
74     iov[5].iov_base = (void *) mnt->src;
75     iov[5].iov_len = nxt_strlen(mnt->src) + 1;
76     iov[6].iov_base = (void *) "errmsg";
77     iov[6].iov_len = 7;
78     iov[7].iov_base = (void *) errmsg;
79     iov[7].iov_len = sizeof(errmsg);
80 
81     iovlen = 8;
82 
83     data = NULL;
84 
85     if (mnt->data != NULL) {
86         data = (u_char *) nxt_strdup(mnt->data);
87         if (nxt_slow_path(data == NULL)) {
88             return NXT_ERROR;
89         }
90 
91         end = data - 1;
92 
93         do {
94             p = end + 1;
95             end = nxt_strchr(p, '=');
96             if (end == NULL) {
97                 break;
98             }
99 
100             *end = '\0';
101 
102             iov[iovlen++].iov_base = (void *) p;
103             iov[iovlen++].iov_len = (end - p) + 1;
104 
105             p = end + 1;
106 
107             end = nxt_strchr(p, ',');
108             if (end != NULL) {
109                 *end = '\0';
110             }
111 
112             iov[iovlen++].iov_base = (void *) p;
113             iov[iovlen++].iov_len = nxt_strlen(p) + 1;
114 
115         } while (end != NULL && nxt_nitems(iov) > (iovlen + 2));
116     }
117 
118     ret = NXT_OK;
119 
120     if (nxt_slow_path(nmount(iov, iovlen, 0) < 0)) {
121         nxt_alert(task, "nmount(%p, %d, 0) %s", iov, iovlen, errmsg);
122         ret = NXT_ERROR;
123     }
124 
125     if (data != NULL) {
126         free(data);
127     }
128 
129     return ret;
130 }
131 
132 #endif
133 
134 
135 #if (NXT_HAVE_LINUX_UMOUNT2)
136 
137 void
138 nxt_fs_unmount(const u_char *path)
139 {
140     if (nxt_slow_path(umount2((const char *) path, MNT_DETACH) < 0)) {
141         nxt_thread_log_error(NXT_LOG_WARN, "umount2(%s, MNT_DETACH) %E",
142                              path, nxt_errno);
143     }
144 }
145 
146 #elif (NXT_HAVE_UNMOUNT)
147 
148 void
149 nxt_fs_unmount(const u_char *path)
150 {
151     if (nxt_slow_path(unmount((const char *) path, MNT_FORCE) < 0)) {
152         nxt_thread_log_error(NXT_LOG_WARN, "unmount(%s) %E", path, nxt_errno);
153     }
154 }
155 
156 #endif
157 
158 
159 nxt_int_t
160 nxt_fs_mkdir_all(const u_char *dir, mode_t mode)
161 {
162     char    *start, *end, *dst;
163     size_t  dirlen;
164     char    path[PATH_MAX];
165 
166     dirlen = nxt_strlen(dir);
167 
168     nxt_assert(dirlen < PATH_MAX && dirlen > 1 && dir[0] == '/');
169 
170     dst = path;
171     start = end = (char *) dir;
172 
173     while (*start != '\0') {
174         if (*start == '/') {
175             *dst++ = *start++;
176         }
177 
178         end = strchr(start, '/');
179         if (end == NULL) {
180             end = ((char *)dir + dirlen);
181         }
182 
183         dst = nxt_cpymem(dst, start, end - start);
184         *dst = '\0';
185 
186         if (nxt_slow_path(nxt_fs_mkdir((u_char *) path, mode) != NXT_OK
187                           && nxt_errno != EEXIST))
188         {
189             return NXT_ERROR;
190         }
191 
192         start = end;
193     }
194 
195     return NXT_OK;
196 }
197 
198 
199 static nxt_int_t
200 nxt_fs_mkdir(const u_char *dir, mode_t mode)
201 {
202     if (nxt_fast_path(mkdir((const char *) dir, mode) == 0)) {
203         return NXT_OK;
204     }
205 
206     return NXT_ERROR;
207 }
208