CI: Add FreeBSD 14.2 RELEASE+STABLE builds
[zfs.git] / lib / libzfs / os / freebsd / libzfs_compat.c
blob2abf7755b5189c7b57a8de9ae1e9e5bfc1255821
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
23 * Copyright (c) 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
25 #include "../../libzfs_impl.h"
26 #include <libzfs.h>
27 #include <libzutil.h>
28 #include <sys/sysctl.h>
29 #include <libintl.h>
30 #include <sys/linker.h>
31 #include <sys/module.h>
32 #include <sys/stat.h>
33 #include <sys/param.h>
35 #ifdef IN_BASE
36 #define ZFS_KMOD "zfs"
37 #else
38 #define ZFS_KMOD "openzfs"
39 #endif
41 #ifndef HAVE_EXECVPE
42 /* FreeBSD prior to 15 lacks execvpe */
43 static int
44 execvPe(const char *name, const char *path, char * const *argv,
45 char * const *envp)
47 const char **memp;
48 size_t cnt, lp, ln;
49 int eacces, save_errno;
50 char buf[MAXPATHLEN];
51 const char *bp, *np, *op, *p;
52 struct stat sb;
54 eacces = 0;
56 /* If it's an absolute or relative path name, it's easy. */
57 if (strchr(name, '/')) {
58 bp = name;
59 op = NULL;
60 goto retry;
62 bp = buf;
64 /* If it's an empty path name, fail in the usual POSIX way. */
65 if (*name == '\0') {
66 errno = ENOENT;
67 return (-1);
70 op = path;
71 ln = strlen(name);
72 while (op != NULL) {
73 np = strchrnul(op, ':');
76 * It's a SHELL path -- double, leading and trailing colons
77 * mean the current directory.
79 if (np == op) {
80 /* Empty component. */
81 p = ".";
82 lp = 1;
83 } else {
84 /* Non-empty component. */
85 p = op;
86 lp = np - op;
89 /* Advance to the next component or terminate after this. */
90 if (*np == '\0')
91 op = NULL;
92 else
93 op = np + 1;
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",
104 16);
105 continue;
107 memcpy(buf, p, lp);
108 buf[lp] = '/';
109 memcpy(buf + lp + 1, name, ln);
110 buf[lp + ln + 1] = '\0';
112 retry: (void) execve(bp, argv, envp);
113 switch (errno) {
114 case E2BIG:
115 goto done;
116 case ELOOP:
117 case ENAMETOOLONG:
118 case ENOENT:
119 break;
120 case ENOEXEC:
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 *));
132 if (memp == NULL) {
133 /* errno = ENOMEM; XXX override ENOEXEC? */
134 goto done;
136 if (cnt > 0) {
137 memp[0] = argv[0];
138 memp[1] = bp;
139 memcpy(memp + 2, argv + 1,
140 cnt * sizeof (char *));
141 } else {
142 memp[0] = "sh";
143 memp[1] = bp;
144 memp[2] = NULL;
146 (void) execve(_PATH_BSHELL,
147 __DECONST(char **, memp), envp);
148 goto done;
149 case ENOMEM:
150 goto done;
151 case ENOTDIR:
152 break;
153 case ETXTBSY:
155 * We used to retry here, but sh(1) doesn't.
157 goto done;
158 default:
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.
166 save_errno = errno;
167 if (stat(bp, &sb) != 0)
168 break;
169 if (save_errno == EACCES) {
170 eacces = 1;
171 continue;
173 errno = save_errno;
174 goto done;
177 if (eacces)
178 errno = EACCES;
179 else
180 errno = ENOENT;
181 done:
182 return (-1);
186 execvpe(const char *name, char * const argv[], char * const envp[])
188 const char *path;
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];
200 const char *
201 libzfs_error_init(int error)
203 char *msg = errbuf;
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);
209 if (len >= msglen)
210 len = msglen - 1;
211 msg += len;
212 msglen -= len;
215 (void) snprintf(msg, msglen, "%s", zfs_strerror(error));
217 return (errbuf);
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
237 * in-base module.
239 if (modfind("zfs") < 0) {
240 /* Not present in kernel, try loading it. */
241 if (kldload(ZFS_KMOD) < 0 && errno != EEXIST) {
242 return (errno);
245 return (0);
249 zpool_relabel_disk(libzfs_handle_t *hdl, const char *path, const char *msg)
251 (void) hdl, (void) path, (void) msg;
252 return (0);
256 zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, const char *name)
258 (void) hdl, (void) zhp, (void) name;
259 return (0);
263 find_shares_object(differ_info_t *di)
265 (void) di;
266 return (0);
270 zfs_destroy_snaps_nvl_os(libzfs_handle_t *hdl, nvlist_t *snaps)
272 (void) hdl, (void) snaps;
273 return (0);
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"};
284 unsigned long cmd;
285 int ret;
287 if (attach) {
288 (void) snprintf(errbuf, sizeof (errbuf),
289 dgettext(TEXT_DOMAIN, "cannot jail '%s'"), zhp->zfs_name);
290 } else {
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));
308 case ZFS_TYPE_VDEV:
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));
316 case ZFS_TYPE_POOL:
317 case ZFS_TYPE_FILESYSTEM:
318 /* OK */
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);
331 return (ret);
335 * Set loader options for next boot.
338 zpool_nextboot(libzfs_handle_t *hdl, uint64_t pool_guid, uint64_t dev_guid,
339 const char *command)
341 zfs_cmd_t zc = {"\0"};
342 nvlist_t *args;
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);
351 nvlist_free(args);
352 return (error);
356 * Return allocated loaded module version, or NULL on error (with errno set)
358 char *
359 zfs_version_kernel(void)
361 size_t l;
362 if (sysctlbyname("vfs.zfs.version.module",
363 NULL, &l, NULL, 0) == -1)
364 return (NULL);
365 char *version = malloc(l);
366 if (version == NULL)
367 return (NULL);
368 if (sysctlbyname("vfs.zfs.version.module",
369 version, &l, NULL, 0) == -1) {
370 free(version);
371 return (NULL);
373 return (version);