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.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or https://opensource.org/licenses/CDDL-1.0.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
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]
23 * Copyright (c) 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
25 #include "../../libzfs_impl.h"
28 #include <sys/sysctl.h>
30 #include <sys/linker.h>
31 #include <sys/module.h>
33 #include <sys/param.h>
36 #define ZFS_KMOD "zfs"
38 #define ZFS_KMOD "openzfs"
42 /* FreeBSD prior to 15 lacks execvpe */
44 execvPe(const char *name
, const char *path
, char * const *argv
,
49 int eacces
, save_errno
;
51 const char *bp
, *np
, *op
, *p
;
56 /* If it's an absolute or relative path name, it's easy. */
57 if (strchr(name
, '/')) {
64 /* If it's an empty path name, fail in the usual POSIX way. */
73 np
= strchrnul(op
, ':');
76 * It's a SHELL path -- double, leading and trailing colons
77 * mean the current directory.
80 /* Empty component. */
84 /* Non-empty component. */
89 /* Advance to the next component or terminate after this. */
96 * If the path is too long complain. This is a possible
97 * security issue; given a way to make the path too long
98 * the user may execute the wrong program.
100 if (lp
+ ln
+ 2 > sizeof (buf
)) {
101 (void) write(STDERR_FILENO
, "execvP: ", 8);
102 (void) write(STDERR_FILENO
, p
, lp
);
103 (void) write(STDERR_FILENO
, ": path too long\n",
109 memcpy(buf
+ lp
+ 1, name
, ln
);
110 buf
[lp
+ ln
+ 1] = '\0';
112 retry
: (void) execve(bp
, argv
, envp
);
121 for (cnt
= 0; argv
[cnt
]; ++cnt
)
125 * cnt may be 0 above; always allocate at least
126 * 3 entries so that we can at least fit "sh", bp, and
127 * the NULL terminator. We can rely on cnt to take into
128 * account the NULL terminator in all other scenarios,
129 * as we drop argv[0].
131 memp
= alloca(MAX(3, cnt
+ 2) * sizeof (char *));
133 /* errno = ENOMEM; XXX override ENOEXEC? */
139 memcpy(memp
+ 2, argv
+ 1,
140 cnt
* sizeof (char *));
146 (void) execve(_PATH_BSHELL
,
147 __DECONST(char **, memp
), envp
);
155 * We used to retry here, but sh(1) doesn't.
160 * EACCES may be for an inaccessible directory or
161 * a non-executable file. Call stat() to decide
162 * which. This also handles ambiguities for EFAULT
163 * and EIO, and undocumented errors like ESTALE.
164 * We hope that the race for a stat() is unimportant.
167 if (stat(bp
, &sb
) != 0)
169 if (save_errno
== EACCES
) {
186 execvpe(const char *name
, char * const argv
[], char * const envp
[])
190 /* Get the path we're searching. */
191 if ((path
= getenv("PATH")) == NULL
)
192 path
= _PATH_DEFPATH
;
194 return (execvPe(name
, path
, argv
, envp
));
196 #endif /* !HAVE_EXECVPE */
198 static __thread
char errbuf
[ERRBUFLEN
];
201 libzfs_error_init(int error
)
204 size_t msglen
= sizeof (errbuf
);
206 if (modfind("zfs") < 0) {
207 size_t len
= snprintf(msg
, msglen
, dgettext(TEXT_DOMAIN
,
208 "Failed to load %s module: "), ZFS_KMOD
);
215 (void) snprintf(msg
, msglen
, "%s", zfs_strerror(error
));
221 zfs_ioctl(libzfs_handle_t
*hdl
, int request
, zfs_cmd_t
*zc
)
223 return (lzc_ioctl_fd(hdl
->libzfs_fd
, request
, zc
));
227 * Verify the required ZFS_DEV device is available and optionally attempt
228 * to load the ZFS modules. Under normal circumstances the modules
229 * should already have been loaded by some external mechanism.
232 libzfs_load_module(void)
235 * XXX: kldfind(ZFS_KMOD) would be nice here, but we retain
236 * modfind("zfs") so out-of-base openzfs userland works with the
239 if (modfind("zfs") < 0) {
240 /* Not present in kernel, try loading it. */
241 if (kldload(ZFS_KMOD
) < 0 && errno
!= EEXIST
) {
249 zpool_relabel_disk(libzfs_handle_t
*hdl
, const char *path
, const char *msg
)
251 (void) hdl
, (void) path
, (void) msg
;
256 zpool_label_disk(libzfs_handle_t
*hdl
, zpool_handle_t
*zhp
, const char *name
)
258 (void) hdl
, (void) zhp
, (void) name
;
263 find_shares_object(differ_info_t
*di
)
270 zfs_destroy_snaps_nvl_os(libzfs_handle_t
*hdl
, nvlist_t
*snaps
)
272 (void) hdl
, (void) snaps
;
277 * Attach/detach the given filesystem to/from the given jail.
280 zfs_jail(zfs_handle_t
*zhp
, int jailid
, int attach
)
282 libzfs_handle_t
*hdl
= zhp
->zfs_hdl
;
283 zfs_cmd_t zc
= {"\0"};
288 (void) snprintf(errbuf
, sizeof (errbuf
),
289 dgettext(TEXT_DOMAIN
, "cannot jail '%s'"), zhp
->zfs_name
);
291 (void) snprintf(errbuf
, sizeof (errbuf
),
292 dgettext(TEXT_DOMAIN
, "cannot unjail '%s'"), zhp
->zfs_name
);
295 switch (zhp
->zfs_type
) {
296 case ZFS_TYPE_VOLUME
:
297 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
,
298 "volumes can not be jailed"));
299 return (zfs_error(hdl
, EZFS_BADTYPE
, errbuf
));
300 case ZFS_TYPE_SNAPSHOT
:
301 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
,
302 "snapshots can not be jailed"));
303 return (zfs_error(hdl
, EZFS_BADTYPE
, errbuf
));
304 case ZFS_TYPE_BOOKMARK
:
305 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
,
306 "bookmarks can not be jailed"));
307 return (zfs_error(hdl
, EZFS_BADTYPE
, errbuf
));
309 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
,
310 "vdevs can not be jailed"));
311 return (zfs_error(hdl
, EZFS_BADTYPE
, errbuf
));
312 case ZFS_TYPE_INVALID
:
313 zfs_error_aux(hdl
, dgettext(TEXT_DOMAIN
,
314 "invalid zfs_type_t: ZFS_TYPE_INVALID"));
315 return (zfs_error(hdl
, EZFS_BADTYPE
, errbuf
));
317 case ZFS_TYPE_FILESYSTEM
:
321 assert(zhp
->zfs_type
== ZFS_TYPE_FILESYSTEM
);
323 (void) strlcpy(zc
.zc_name
, zhp
->zfs_name
, sizeof (zc
.zc_name
));
324 zc
.zc_objset_type
= DMU_OST_ZFS
;
325 zc
.zc_zoneid
= jailid
;
327 cmd
= attach
? ZFS_IOC_JAIL
: ZFS_IOC_UNJAIL
;
328 if ((ret
= zfs_ioctl(hdl
, cmd
, &zc
)) != 0)
329 zfs_standard_error(hdl
, errno
, errbuf
);
335 * Set loader options for next boot.
338 zpool_nextboot(libzfs_handle_t
*hdl
, uint64_t pool_guid
, uint64_t dev_guid
,
341 zfs_cmd_t zc
= {"\0"};
344 args
= fnvlist_alloc();
345 fnvlist_add_uint64(args
, ZPOOL_CONFIG_POOL_GUID
, pool_guid
);
346 fnvlist_add_uint64(args
, ZPOOL_CONFIG_GUID
, dev_guid
);
347 fnvlist_add_string(args
, "command", command
);
348 zcmd_write_src_nvlist(hdl
, &zc
, args
);
349 int error
= zfs_ioctl(hdl
, ZFS_IOC_NEXTBOOT
, &zc
);
350 zcmd_free_nvlists(&zc
);
356 * Return allocated loaded module version, or NULL on error (with errno set)
359 zfs_version_kernel(void)
362 if (sysctlbyname("vfs.zfs.version.module",
363 NULL
, &l
, NULL
, 0) == -1)
365 char *version
= malloc(l
);
368 if (sysctlbyname("vfs.zfs.version.module",
369 version
, &l
, NULL
, 0) == -1) {