1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved. 24 */ 25 #include <os/freebsd/zfs/sys/zfs_ioctl_compat.h> 26 #include <libzfs_impl.h> 27 #include <libzfs.h> 28 #include <libzutil.h> 29 #include <sys/sysctl.h> 30 #include <libintl.h> 31 #include <sys/linker.h> 32 #include <sys/module.h> 33 #include <sys/stat.h> 34 #include <sys/param.h> 35 36 #ifdef IN_BASE 37 #define ZFS_KMOD "zfs" 38 #else 39 #define ZFS_KMOD "openzfs" 40 #endif 41 42 void 43 libzfs_set_pipe_max(int infd) 44 { 45 /* FreeBSD automatically resizes */ 46 } 47 48 static int 49 execvPe(const char *name, const char *path, char * const *argv, 50 char * const *envp) 51 { 52 const char **memp; 53 size_t cnt, lp, ln; 54 int eacces, save_errno; 55 char *cur, buf[MAXPATHLEN]; 56 const char *p, *bp; 57 struct stat sb; 58 59 eacces = 0; 60 61 /* If it's an absolute or relative path name, it's easy. */ 62 if (strchr(name, '/')) { 63 bp = name; 64 cur = NULL; 65 goto retry; 66 } 67 bp = buf; 68 69 /* If it's an empty path name, fail in the usual POSIX way. */ 70 if (*name == '\0') { 71 errno = ENOENT; 72 return (-1); 73 } 74 75 cur = alloca(strlen(path) + 1); 76 if (cur == NULL) { 77 errno = ENOMEM; 78 return (-1); 79 } 80 strcpy(cur, path); 81 while ((p = strsep(&cur, ":")) != NULL) { 82 /* 83 * It's a SHELL path -- double, leading and trailing colons 84 * mean the current directory. 85 */ 86 if (*p == '\0') { 87 p = "."; 88 lp = 1; 89 } else 90 lp = strlen(p); 91 ln = strlen(name); 92 93 /* 94 * If the path is too long complain. This is a possible 95 * security issue; given a way to make the path too long 96 * the user may execute the wrong program. 97 */ 98 if (lp + ln + 2 > sizeof (buf)) { 99 (void) write(STDERR_FILENO, "execvP: ", 8); 100 (void) write(STDERR_FILENO, p, lp); 101 (void) write(STDERR_FILENO, ": path too long\n", 102 16); 103 continue; 104 } 105 bcopy(p, buf, lp); 106 buf[lp] = '/'; 107 bcopy(name, buf + lp + 1, ln); 108 buf[lp + ln + 1] = '\0'; 109 110 retry: (void) execve(bp, argv, envp); 111 switch (errno) { 112 case E2BIG: 113 goto done; 114 case ELOOP: 115 case ENAMETOOLONG: 116 case ENOENT: 117 break; 118 case ENOEXEC: 119 for (cnt = 0; argv[cnt]; ++cnt) 120 ; 121 memp = alloca((cnt + 2) * sizeof (char *)); 122 if (memp == NULL) { 123 /* errno = ENOMEM; XXX override ENOEXEC? */ 124 goto done; 125 } 126 memp[0] = "sh"; 127 memp[1] = bp; 128 bcopy(argv + 1, memp + 2, cnt * sizeof (char *)); 129 execve(_PATH_BSHELL, __DECONST(char **, memp), envp); 130 goto done; 131 case ENOMEM: 132 goto done; 133 case ENOTDIR: 134 break; 135 case ETXTBSY: 136 /* 137 * We used to retry here, but sh(1) doesn't. 138 */ 139 goto done; 140 default: 141 /* 142 * EACCES may be for an inaccessible directory or 143 * a non-executable file. Call stat() to decide 144 * which. This also handles ambiguities for EFAULT 145 * and EIO, and undocumented errors like ESTALE. 146 * We hope that the race for a stat() is unimportant. 147 */ 148 save_errno = errno; 149 if (stat(bp, &sb) != 0) 150 break; 151 if (save_errno == EACCES) { 152 eacces = 1; 153 continue; 154 } 155 errno = save_errno; 156 goto done; 157 } 158 } 159 if (eacces) 160 errno = EACCES; 161 else 162 errno = ENOENT; 163 done: 164 return (-1); 165 } 166 167 int 168 execvpe(const char *name, char * const argv[], char * const envp[]) 169 { 170 const char *path; 171 172 /* Get the path we're searching. */ 173 if ((path = getenv("PATH")) == NULL) 174 path = _PATH_DEFPATH; 175 176 return (execvPe(name, path, argv, envp)); 177 } 178 179 const char * 180 libzfs_error_init(int error) 181 { 182 183 return (strerror(error)); 184 } 185 186 int 187 zfs_ioctl(libzfs_handle_t *hdl, int request, zfs_cmd_t *zc) 188 { 189 return (zfs_ioctl_fd(hdl->libzfs_fd, request, zc)); 190 } 191 192 /* 193 * Verify the required ZFS_DEV device is available and optionally attempt 194 * to load the ZFS modules. Under normal circumstances the modules 195 * should already have been loaded by some external mechanism. 196 * 197 * Environment variables: 198 * - ZFS_MODULE_LOADING="YES|yes|ON|on" - Attempt to load modules. 199 * - ZFS_MODULE_TIMEOUT="<seconds>" - Seconds to wait for ZFS_DEV 200 */ 201 int 202 libzfs_load_module(void) 203 { 204 /* 205 * XXX: kldfind(ZFS_KMOD) would be nice here, but we retain 206 * modfind("zfs") so out-of-base openzfs userland works with the 207 * in-base module. 208 */ 209 if (modfind("zfs") < 0) { 210 /* Not present in kernel, try loading it. */ 211 if (kldload(ZFS_KMOD) < 0 && errno != EEXIST) { 212 return (errno); 213 } 214 } 215 return (0); 216 } 217 218 int 219 zpool_relabel_disk(libzfs_handle_t *hdl, const char *path, const char *msg) 220 { 221 return (0); 222 } 223 224 int 225 zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, const char *name) 226 { 227 return (0); 228 } 229 230 int 231 find_shares_object(differ_info_t *di) 232 { 233 return (0); 234 } 235 236 /* 237 * Attach/detach the given filesystem to/from the given jail. 238 */ 239 int 240 zfs_jail(zfs_handle_t *zhp, int jailid, int attach) 241 { 242 libzfs_handle_t *hdl = zhp->zfs_hdl; 243 zfs_cmd_t zc = {"\0"}; 244 char errbuf[1024]; 245 unsigned long cmd; 246 int ret; 247 248 if (attach) { 249 (void) snprintf(errbuf, sizeof (errbuf), 250 dgettext(TEXT_DOMAIN, "cannot jail '%s'"), zhp->zfs_name); 251 } else { 252 (void) snprintf(errbuf, sizeof (errbuf), 253 dgettext(TEXT_DOMAIN, "cannot unjail '%s'"), zhp->zfs_name); 254 } 255 256 switch (zhp->zfs_type) { 257 case ZFS_TYPE_VOLUME: 258 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 259 "volumes can not be jailed")); 260 return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); 261 case ZFS_TYPE_SNAPSHOT: 262 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 263 "snapshots can not be jailed")); 264 return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); 265 case ZFS_TYPE_BOOKMARK: 266 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 267 "bookmarks can not be jailed")); 268 return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); 269 case ZFS_TYPE_POOL: 270 case ZFS_TYPE_FILESYSTEM: 271 /* OK */ 272 ; 273 } 274 assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM); 275 276 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 277 zc.zc_objset_type = DMU_OST_ZFS; 278 zc.zc_zoneid = jailid; 279 280 cmd = attach ? ZFS_IOC_JAIL : ZFS_IOC_UNJAIL; 281 if ((ret = zfs_ioctl(hdl, cmd, &zc)) != 0) 282 zfs_standard_error(hdl, errno, errbuf); 283 284 return (ret); 285 } 286 287 /* 288 * Set loader options for next boot. 289 */ 290 int 291 zpool_nextboot(libzfs_handle_t *hdl, uint64_t pool_guid, uint64_t dev_guid, 292 const char *command) 293 { 294 zfs_cmd_t zc = {"\0"}; 295 nvlist_t *args; 296 int error; 297 298 args = fnvlist_alloc(); 299 fnvlist_add_uint64(args, ZPOOL_CONFIG_POOL_GUID, pool_guid); 300 fnvlist_add_uint64(args, ZPOOL_CONFIG_GUID, dev_guid); 301 fnvlist_add_string(args, "command", command); 302 error = zcmd_write_src_nvlist(hdl, &zc, args); 303 if (error == 0) 304 error = zfs_ioctl(hdl, ZFS_IOC_NEXTBOOT, &zc); 305 zcmd_free_nvlists(&zc); 306 nvlist_free(args); 307 return (error); 308 } 309 310 /* 311 * Fill given version buffer with zfs kernel version. 312 * Returns 0 on success, and -1 on error (with errno set) 313 */ 314 int 315 zfs_version_kernel(char *version, int len) 316 { 317 size_t l = len; 318 319 return (sysctlbyname("vfs.zfs.version.module", 320 version, &l, NULL, 0)); 321 } 322