The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/openzfs/lib/libzfs/os/freebsd/libzfs_compat.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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 https://opensource.org/licenses/CDDL-1.0.
   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 "../../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>
   34 
   35 #ifdef IN_BASE
   36 #define ZFS_KMOD        "zfs"
   37 #else
   38 #define ZFS_KMOD        "openzfs"
   39 #endif
   40 
   41 
   42 static int
   43 execvPe(const char *name, const char *path, char * const *argv,
   44     char * const *envp)
   45 {
   46         const char **memp;
   47         size_t cnt, lp, ln;
   48         int eacces, save_errno;
   49         char buf[MAXPATHLEN];
   50         const char *bp, *np, *op, *p;
   51         struct stat sb;
   52 
   53         eacces = 0;
   54 
   55         /* If it's an absolute or relative path name, it's easy. */
   56         if (strchr(name, '/')) {
   57                 bp = name;
   58                 op = NULL;
   59                 goto retry;
   60         }
   61         bp = buf;
   62 
   63         /* If it's an empty path name, fail in the usual POSIX way. */
   64         if (*name == '\0') {
   65                 errno = ENOENT;
   66                 return (-1);
   67         }
   68 
   69         op = path;
   70         ln = strlen(name);
   71         while (op != NULL) {
   72                 np = strchrnul(op, ':');
   73 
   74                 /*
   75                  * It's a SHELL path -- double, leading and trailing colons
   76                  * mean the current directory.
   77                  */
   78                 if (np == op) {
   79                         /* Empty component. */
   80                         p = ".";
   81                         lp = 1;
   82                 } else {
   83                         /* Non-empty component. */
   84                         p = op;
   85                         lp = np - op;
   86                 }
   87 
   88                 /* Advance to the next component or terminate after this. */
   89                 if (*np == '\0')
   90                         op = NULL;
   91                 else
   92                         op = np + 1;
   93 
   94                 /*
   95                  * If the path is too long complain.  This is a possible
   96                  * security issue; given a way to make the path too long
   97                  * the user may execute the wrong program.
   98                  */
   99                 if (lp + ln + 2 > sizeof (buf)) {
  100                         (void) write(STDERR_FILENO, "execvP: ", 8);
  101                         (void) write(STDERR_FILENO, p, lp);
  102                         (void) write(STDERR_FILENO, ": path too long\n",
  103                             16);
  104                         continue;
  105                 }
  106                 memcpy(buf, p, lp);
  107                 buf[lp] = '/';
  108                 memcpy(buf + lp + 1, name, ln);
  109                 buf[lp + ln + 1] = '\0';
  110 
  111 retry:          (void) execve(bp, argv, envp);
  112                 switch (errno) {
  113                 case E2BIG:
  114                         goto done;
  115                 case ELOOP:
  116                 case ENAMETOOLONG:
  117                 case ENOENT:
  118                         break;
  119                 case ENOEXEC:
  120                         for (cnt = 0; argv[cnt]; ++cnt)
  121                                 ;
  122 
  123                         /*
  124                          * cnt may be 0 above; always allocate at least
  125                          * 3 entries so that we can at least fit "sh", bp, and
  126                          * the NULL terminator.  We can rely on cnt to take into
  127                          * account the NULL terminator in all other scenarios,
  128                          * as we drop argv[0].
  129                          */
  130                         memp = alloca(MAX(3, cnt + 2) * sizeof (char *));
  131                         if (memp == NULL) {
  132                                 /* errno = ENOMEM; XXX override ENOEXEC? */
  133                                 goto done;
  134                         }
  135                         if (cnt > 0) {
  136                                 memp[0] = argv[0];
  137                                 memp[1] = bp;
  138                                 memcpy(memp + 2, argv + 1,
  139                                     cnt * sizeof (char *));
  140                         } else {
  141                                 memp[0] = "sh";
  142                                 memp[1] = bp;
  143                                 memp[2] = NULL;
  144                         }
  145                         (void) execve(_PATH_BSHELL,
  146                             __DECONST(char **, memp), envp);
  147                         goto done;
  148                 case ENOMEM:
  149                         goto done;
  150                 case ENOTDIR:
  151                         break;
  152                 case ETXTBSY:
  153                         /*
  154                          * We used to retry here, but sh(1) doesn't.
  155                          */
  156                         goto done;
  157                 default:
  158                         /*
  159                          * EACCES may be for an inaccessible directory or
  160                          * a non-executable file.  Call stat() to decide
  161                          * which.  This also handles ambiguities for EFAULT
  162                          * and EIO, and undocumented errors like ESTALE.
  163                          * We hope that the race for a stat() is unimportant.
  164                          */
  165                         save_errno = errno;
  166                         if (stat(bp, &sb) != 0)
  167                                 break;
  168                         if (save_errno == EACCES) {
  169                                 eacces = 1;
  170                                 continue;
  171                         }
  172                         errno = save_errno;
  173                         goto done;
  174                 }
  175         }
  176         if (eacces)
  177                 errno = EACCES;
  178         else
  179                 errno = ENOENT;
  180 done:
  181         return (-1);
  182 }
  183 
  184 int
  185 execvpe(const char *name, char * const argv[], char * const envp[])
  186 {
  187         const char *path;
  188 
  189         /* Get the path we're searching. */
  190         if ((path = getenv("PATH")) == NULL)
  191                 path = _PATH_DEFPATH;
  192 
  193         return (execvPe(name, path, argv, envp));
  194 }
  195 
  196 static __thread char errbuf[ERRBUFLEN];
  197 
  198 const char *
  199 libzfs_error_init(int error)
  200 {
  201         char *msg = errbuf;
  202         size_t msglen = sizeof (errbuf);
  203 
  204         if (modfind("zfs") < 0) {
  205                 size_t len = snprintf(msg, msglen, dgettext(TEXT_DOMAIN,
  206                     "Failed to load %s module: "), ZFS_KMOD);
  207                 if (len >= msglen)
  208                         len = msglen - 1;
  209                 msg += len;
  210                 msglen -= len;
  211         }
  212 
  213         (void) snprintf(msg, msglen, "%s", strerror(error));
  214 
  215         return (errbuf);
  216 }
  217 
  218 int
  219 zfs_ioctl(libzfs_handle_t *hdl, int request, zfs_cmd_t *zc)
  220 {
  221         return (lzc_ioctl_fd(hdl->libzfs_fd, request, zc));
  222 }
  223 
  224 /*
  225  * Verify the required ZFS_DEV device is available and optionally attempt
  226  * to load the ZFS modules.  Under normal circumstances the modules
  227  * should already have been loaded by some external mechanism.
  228  */
  229 int
  230 libzfs_load_module(void)
  231 {
  232         /*
  233          * XXX: kldfind(ZFS_KMOD) would be nice here, but we retain
  234          * modfind("zfs") so out-of-base openzfs userland works with the
  235          * in-base module.
  236          */
  237         if (modfind("zfs") < 0) {
  238                 /* Not present in kernel, try loading it. */
  239                 if (kldload(ZFS_KMOD) < 0 && errno != EEXIST) {
  240                         return (errno);
  241                 }
  242         }
  243         return (0);
  244 }
  245 
  246 int
  247 zpool_relabel_disk(libzfs_handle_t *hdl, const char *path, const char *msg)
  248 {
  249         (void) hdl, (void) path, (void) msg;
  250         return (0);
  251 }
  252 
  253 int
  254 zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, const char *name)
  255 {
  256         (void) hdl, (void) zhp, (void) name;
  257         return (0);
  258 }
  259 
  260 int
  261 find_shares_object(differ_info_t *di)
  262 {
  263         (void) di;
  264         return (0);
  265 }
  266 
  267 int
  268 zfs_destroy_snaps_nvl_os(libzfs_handle_t *hdl, nvlist_t *snaps)
  269 {
  270         (void) hdl, (void) snaps;
  271         return (0);
  272 }
  273 
  274 /*
  275  * Attach/detach the given filesystem to/from the given jail.
  276  */
  277 int
  278 zfs_jail(zfs_handle_t *zhp, int jailid, int attach)
  279 {
  280         libzfs_handle_t *hdl = zhp->zfs_hdl;
  281         zfs_cmd_t zc = {"\0"};
  282         unsigned long cmd;
  283         int ret;
  284 
  285         if (attach) {
  286                 (void) snprintf(errbuf, sizeof (errbuf),
  287                     dgettext(TEXT_DOMAIN, "cannot jail '%s'"), zhp->zfs_name);
  288         } else {
  289                 (void) snprintf(errbuf, sizeof (errbuf),
  290                     dgettext(TEXT_DOMAIN, "cannot unjail '%s'"), zhp->zfs_name);
  291         }
  292 
  293         switch (zhp->zfs_type) {
  294         case ZFS_TYPE_VOLUME:
  295                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
  296                     "volumes can not be jailed"));
  297                 return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
  298         case ZFS_TYPE_SNAPSHOT:
  299                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
  300                     "snapshots can not be jailed"));
  301                 return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
  302         case ZFS_TYPE_BOOKMARK:
  303                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
  304                     "bookmarks can not be jailed"));
  305                 return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
  306         case ZFS_TYPE_VDEV:
  307                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
  308                     "vdevs can not be jailed"));
  309                 return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
  310         case ZFS_TYPE_INVALID:
  311                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
  312                     "invalid zfs_type_t: ZFS_TYPE_INVALID"));
  313                 return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
  314         case ZFS_TYPE_POOL:
  315         case ZFS_TYPE_FILESYSTEM:
  316                 /* OK */
  317                 ;
  318         }
  319         assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM);
  320 
  321         (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
  322         zc.zc_objset_type = DMU_OST_ZFS;
  323         zc.zc_zoneid = jailid;
  324 
  325         cmd = attach ? ZFS_IOC_JAIL : ZFS_IOC_UNJAIL;
  326         if ((ret = zfs_ioctl(hdl, cmd, &zc)) != 0)
  327                 zfs_standard_error(hdl, errno, errbuf);
  328 
  329         return (ret);
  330 }
  331 
  332 /*
  333  * Set loader options for next boot.
  334  */
  335 int
  336 zpool_nextboot(libzfs_handle_t *hdl, uint64_t pool_guid, uint64_t dev_guid,
  337     const char *command)
  338 {
  339         zfs_cmd_t zc = {"\0"};
  340         nvlist_t *args;
  341 
  342         args = fnvlist_alloc();
  343         fnvlist_add_uint64(args, ZPOOL_CONFIG_POOL_GUID, pool_guid);
  344         fnvlist_add_uint64(args, ZPOOL_CONFIG_GUID, dev_guid);
  345         fnvlist_add_string(args, "command", command);
  346         zcmd_write_src_nvlist(hdl, &zc, args);
  347         int error = zfs_ioctl(hdl, ZFS_IOC_NEXTBOOT, &zc);
  348         zcmd_free_nvlists(&zc);
  349         nvlist_free(args);
  350         return (error);
  351 }
  352 
  353 /*
  354  * Return allocated loaded module version, or NULL on error (with errno set)
  355  */
  356 char *
  357 zfs_version_kernel(void)
  358 {
  359         size_t l;
  360         if (sysctlbyname("vfs.zfs.version.module",
  361             NULL, &l, NULL, 0) == -1)
  362                 return (NULL);
  363         char *version = malloc(l);
  364         if (version == NULL)
  365                 return (NULL);
  366         if (sysctlbyname("vfs.zfs.version.module",
  367             version, &l, NULL, 0) == -1) {
  368                 free(version);
  369                 return (NULL);
  370         }
  371         return (version);
  372 }

Cache object: 312141305f4500671b05d75a997d3598


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.