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 #define ERRBUFLEN 256 180 181 static __thread char errbuf[ERRBUFLEN]; 182 183 const char * 184 libzfs_error_init(int error) 185 { 186 char *msg = errbuf; 187 size_t len, msglen = ERRBUFLEN; 188 189 if (modfind("zfs") < 0) { 190 len = snprintf(msg, msglen, dgettext(TEXT_DOMAIN, 191 "Failed to load %s module: "), ZFS_KMOD); 192 msg += len; 193 msglen -= len; 194 } 195 196 (void) snprintf(msg, msglen, "%s", strerror(error)); 197 198 return (errbuf); 199 } 200 201 int 202 zfs_ioctl(libzfs_handle_t *hdl, int request, zfs_cmd_t *zc) 203 { 204 return (zfs_ioctl_fd(hdl->libzfs_fd, request, zc)); 205 } 206 207 /* 208 * Verify the required ZFS_DEV device is available and optionally attempt 209 * to load the ZFS modules. Under normal circumstances the modules 210 * should already have been loaded by some external mechanism. 211 */ 212 int 213 libzfs_load_module(void) 214 { 215 /* 216 * XXX: kldfind(ZFS_KMOD) would be nice here, but we retain 217 * modfind("zfs") so out-of-base openzfs userland works with the 218 * in-base module. 219 */ 220 if (modfind("zfs") < 0) { 221 /* Not present in kernel, try loading it. */ 222 if (kldload(ZFS_KMOD) < 0 && errno != EEXIST) { 223 return (errno); 224 } 225 } 226 return (0); 227 } 228 229 int 230 zpool_relabel_disk(libzfs_handle_t *hdl, const char *path, const char *msg) 231 { 232 return (0); 233 } 234 235 int 236 zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, const char *name) 237 { 238 return (0); 239 } 240 241 int 242 find_shares_object(differ_info_t *di) 243 { 244 return (0); 245 } 246 247 /* 248 * Attach/detach the given filesystem to/from the given jail. 249 */ 250 int 251 zfs_jail(zfs_handle_t *zhp, int jailid, int attach) 252 { 253 libzfs_handle_t *hdl = zhp->zfs_hdl; 254 zfs_cmd_t zc = {"\0"}; 255 char errbuf[1024]; 256 unsigned long cmd; 257 int ret; 258 259 if (attach) { 260 (void) snprintf(errbuf, sizeof (errbuf), 261 dgettext(TEXT_DOMAIN, "cannot jail '%s'"), zhp->zfs_name); 262 } else { 263 (void) snprintf(errbuf, sizeof (errbuf), 264 dgettext(TEXT_DOMAIN, "cannot unjail '%s'"), zhp->zfs_name); 265 } 266 267 switch (zhp->zfs_type) { 268 case ZFS_TYPE_VOLUME: 269 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 270 "volumes can not be jailed")); 271 return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); 272 case ZFS_TYPE_SNAPSHOT: 273 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 274 "snapshots can not be jailed")); 275 return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); 276 case ZFS_TYPE_BOOKMARK: 277 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 278 "bookmarks can not be jailed")); 279 return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); 280 case ZFS_TYPE_POOL: 281 case ZFS_TYPE_FILESYSTEM: 282 /* OK */ 283 ; 284 } 285 assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM); 286 287 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 288 zc.zc_objset_type = DMU_OST_ZFS; 289 zc.zc_zoneid = jailid; 290 291 cmd = attach ? ZFS_IOC_JAIL : ZFS_IOC_UNJAIL; 292 if ((ret = zfs_ioctl(hdl, cmd, &zc)) != 0) 293 zfs_standard_error(hdl, errno, errbuf); 294 295 return (ret); 296 } 297 298 /* 299 * Set loader options for next boot. 300 */ 301 int 302 zpool_nextboot(libzfs_handle_t *hdl, uint64_t pool_guid, uint64_t dev_guid, 303 const char *command) 304 { 305 zfs_cmd_t zc = {"\0"}; 306 nvlist_t *args; 307 int error; 308 309 args = fnvlist_alloc(); 310 fnvlist_add_uint64(args, ZPOOL_CONFIG_POOL_GUID, pool_guid); 311 fnvlist_add_uint64(args, ZPOOL_CONFIG_GUID, dev_guid); 312 fnvlist_add_string(args, "command", command); 313 error = zcmd_write_src_nvlist(hdl, &zc, args); 314 if (error == 0) 315 error = zfs_ioctl(hdl, ZFS_IOC_NEXTBOOT, &zc); 316 zcmd_free_nvlists(&zc); 317 nvlist_free(args); 318 return (error); 319 } 320 321 /* 322 * Fill given version buffer with zfs kernel version. 323 * Returns 0 on success, and -1 on error (with errno set) 324 */ 325 int 326 zfs_version_kernel(char *version, int len) 327 { 328 size_t l = len; 329 330 return (sysctlbyname("vfs.zfs.version.module", 331 version, &l, NULL, 0)); 332 } 333