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 const char *fstype; 44 uint8_t is_bind, is_proc; 45 struct iovec iov[8]; 46 char errmsg[256]; 47 48 is_bind = nxt_strncmp(mnt->fstype, "bind", 4) == 0; 49 is_proc = nxt_strncmp(mnt->fstype, "proc", 4) == 0; 50 51 if (nxt_slow_path(!is_bind && !is_proc)) { 52 nxt_alert(task, "mount type \"%s\" not implemented.", mnt->fstype); 53 return NXT_ERROR; 54 } 55 56 if (is_bind) { 57 fstype = "nullfs"; 58 59 } else { 60 fstype = "procfs"; 61 } 62 63 iov[0].iov_base = (void *) "fstype"; 64 iov[0].iov_len = 7; 65 iov[1].iov_base = (void *) fstype; 66 iov[1].iov_len = strlen(fstype) + 1; 67 iov[2].iov_base = (void *) "fspath"; 68 iov[2].iov_len = 7; 69 iov[3].iov_base = (void *) mnt->dst; 70 iov[3].iov_len = nxt_strlen(mnt->dst) + 1; 71 iov[4].iov_base = (void *) "target"; 72 iov[4].iov_len = 7; 73 iov[5].iov_base = (void *) mnt->src; 74 iov[5].iov_len = nxt_strlen(mnt->src) + 1; 75 iov[6].iov_base = (void *) "errmsg"; 76 iov[6].iov_len = 7; 77 iov[7].iov_base = (void *) errmsg; 78 iov[7].iov_len = sizeof(errmsg); 79 80 if (nxt_slow_path(nmount(iov, 8, 0) < 0)) { 81 nxt_alert(task, "nmount(%p, 8, 0) %s", errmsg); 82 return NXT_ERROR; 83 } 84 85 return NXT_OK; 86 } 87 88 #endif 89 90 91 #if (NXT_HAVE_LINUX_UMOUNT2) 92 93 void 94 nxt_fs_unmount(const u_char *path) 95 { 96 if (nxt_slow_path(umount2((const char *) path, MNT_DETACH) < 0)) { 97 nxt_thread_log_error(NXT_LOG_WARN, "umount2(%s, MNT_DETACH) %E", 98 path, nxt_errno); 99 } 100 } 101 102 #elif (NXT_HAVE_UNMOUNT) 103 104 void 105 nxt_fs_unmount(const u_char *path) 106 { 107 if (nxt_slow_path(unmount((const char *) path, MNT_FORCE) < 0)) { 108 nxt_thread_log_error(NXT_LOG_WARN, "unmount(%s) %E", path, nxt_errno); 109 } 110 } 111 112 #endif 113 114 115 nxt_int_t 116 nxt_fs_mkdir_all(const u_char *dir, mode_t mode) 117 { 118 char *start, *end, *dst; 119 size_t dirlen; 120 char path[PATH_MAX]; 121 122 dirlen = nxt_strlen(dir); 123 124 nxt_assert(dirlen < PATH_MAX && dirlen > 1 && dir[0] == '/'); 125 126 dst = path; 127 start = end = (char *) dir; 128 129 while (*start != '\0') { 130 if (*start == '/') { 131 *dst++ = *start++; 132 } 133 134 end = strchr(start, '/'); 135 if (end == NULL) { 136 end = ((char *)dir + dirlen); 137 } 138 139 dst = nxt_cpymem(dst, start, end - start); 140 *dst = '\0'; 141 142 if (nxt_slow_path(nxt_fs_mkdir((u_char *) path, mode) != NXT_OK 143 && nxt_errno != EEXIST)) 144 { 145 return NXT_ERROR; 146 } 147 148 start = end; 149 } 150 151 return NXT_OK; 152 } 153 154 155 static nxt_int_t 156 nxt_fs_mkdir(const u_char *dir, mode_t mode) 157 { 158 if (nxt_fast_path(mkdir((const char *) dir, mode) == 0)) { 159 return NXT_OK; 160 } 161 162 return NXT_ERROR; 163 } 164