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) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2016 Joyent, Inc.
  25  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  26  */
  27 
  28 /*      Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
  29 /*        All Rights Reserved   */
  30 
  31 /*
  32  * University Copyright- Copyright (c) 1982, 1986, 1988
  33  * The Regents of the University of California
  34  * All Rights Reserved
  35  *
  36  * University Acknowledgment- Portions of this document are derived from
  37  * software developed by the University of California, Berkeley, and its
  38  * contributors.
  39  */
  40 
  41 #include <sys/types.h>
  42 #include <sys/param.h>
  43 #include <sys/systm.h>
  44 #include <sys/errno.h>
  45 #include <sys/cred.h>
  46 #include <sys/user.h>
  47 #include <sys/uio.h>
  48 #include <sys/vfs.h>
  49 #include <sys/vnode.h>
  50 #include <sys/pathname.h>
  51 #include <sys/proc.h>
  52 #include <sys/vtrace.h>
  53 #include <sys/sysmacros.h>
  54 #include <sys/debug.h>
  55 #include <sys/dirent.h>
  56 #include <sys/zone.h>
  57 #include <sys/fs/snode.h>
  58 
  59 #include <libfksmbfs.h>
  60 
  61 extern vnode_t *rootdir;
  62 
  63 /*
  64  * Simplified variation on lookuppnvp()
  65  */
  66 int
  67 fake_lookup(vnode_t *dvp, char *path, vnode_t **vpp)
  68 {
  69         char component[MAXNAMELEN];     /* buffer for component */
  70         pathname_t pn;
  71         cred_t *cr;
  72         vnode_t *cvp;   /* current component vp */
  73         vnode_t *nvp;   /* next component vp */
  74         char *p;
  75         int flags = 0;
  76         int error, len;
  77 
  78         bzero(&pn, sizeof (pn));
  79         pn.pn_buf = path;
  80         pn.pn_path = path;
  81         pn.pn_pathlen = strlen(path);
  82         pn.pn_bufsize = pn.pn_pathlen + 1;
  83         p = path;
  84 
  85         cr = CRED();
  86         cvp = (dvp != NULL) ? dvp : rootdir;
  87         VN_HOLD(cvp);
  88         nvp = NULL;
  89 
  90         while (*p != '\0') {
  91                 if (*p == '/') {
  92                         p++;
  93                         continue;
  94                 }
  95 
  96                 len = strcspn(p, "/");
  97                 ASSERT(len > 0);
  98                 if (len >= MAXNAMELEN)
  99                         return (EINVAL);
 100                 (void) strncpy(component, p, len);
 101                 component[len] = '\0';
 102                 pn.pn_path = p;
 103                 pn.pn_pathlen = strlen(p);
 104 
 105                 error = VOP_LOOKUP(cvp, component, &nvp, &pn, flags,
 106                     rootdir, cr, NULL, NULL, NULL);
 107                 VN_RELE(cvp);
 108                 if (error != 0)
 109                         return (error);
 110 
 111                 /* Lookup gave us a hold on nvp */
 112                 cvp = nvp;
 113                 nvp = NULL;
 114                 p += len;
 115         }
 116 
 117         *vpp = cvp;
 118         return (0);
 119 }
 120 
 121 /*
 122  * Lookup the directory and find the start of the
 123  * last component of the given path.
 124  */
 125 int
 126 fake_lookup_dir(char *path, vnode_t **vpp, char **lastcomp)
 127 {
 128         vnode_t *dvp;
 129         char *last;
 130         char *tpn = NULL;
 131         int tpn_sz;
 132         int lc_off;
 133         int error;
 134 
 135         *vpp = NULL;
 136         *lastcomp = NULL;
 137 
 138         tpn_sz = strlen(path) + 1;
 139         tpn = kmem_alloc(tpn_sz, KM_SLEEP);
 140 
 141         /*
 142          * Get a copy of the path, and zap the last /
 143          */
 144         bcopy(path, tpn, tpn_sz);
 145         last = strrchr(tpn, '/');
 146         if (last == NULL) {
 147                 lc_off = 0;
 148                 dvp = rootdir;
 149                 VN_HOLD(dvp);
 150                 error = 0;
 151         } else {
 152                 *last++ = '\0';
 153                 if (*last == '\0') {
 154                         error = EINVAL;
 155                         goto out;
 156                 }
 157                 error = fake_lookup(rootdir, tpn, &dvp);
 158                 if (error != 0) {
 159                         /* dir not found */
 160                         goto out;
 161                 }
 162                 lc_off = last - tpn;
 163                 ASSERT(lc_off >= 0 && lc_off < tpn_sz);
 164         }
 165         *vpp = dvp;
 166         *lastcomp = path + lc_off;
 167 
 168 out:
 169         if (tpn != NULL)
 170                 kmem_free(tpn, tpn_sz);
 171 
 172         return (error);
 173 }