1e802abbdSTim Haley /* 2e802abbdSTim Haley * CDDL HEADER START 3e802abbdSTim Haley * 4e802abbdSTim Haley * The contents of this file are subject to the terms of the 5e802abbdSTim Haley * Common Development and Distribution License (the "License"). 6e802abbdSTim Haley * You may not use this file except in compliance with the License. 7e802abbdSTim Haley * 8e802abbdSTim Haley * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9e802abbdSTim Haley * or http://www.opensolaris.org/os/licensing. 10e802abbdSTim Haley * See the License for the specific language governing permissions 11e802abbdSTim Haley * and limitations under the License. 12e802abbdSTim Haley * 13e802abbdSTim Haley * When distributing Covered Code, include this CDDL HEADER in each 14e802abbdSTim Haley * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15e802abbdSTim Haley * If applicable, add the following below this CDDL HEADER, with the 16e802abbdSTim Haley * fields enclosed by brackets "[]" replaced with your own identifying 17e802abbdSTim Haley * information: Portions Copyright [yyyy] [name of copyright owner] 18e802abbdSTim Haley * 19e802abbdSTim Haley * CDDL HEADER END 20e802abbdSTim Haley */ 21e802abbdSTim Haley /* 22*fd9ee8b5Sjoyce mcintosh * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 23e802abbdSTim Haley */ 24e802abbdSTim Haley 25e802abbdSTim Haley #include <sys/conf.h> 26e802abbdSTim Haley #include <sys/stat.h> 27e802abbdSTim Haley #include <sys/file.h> 28e802abbdSTim Haley #include <sys/types.h> 29e802abbdSTim Haley #include <sys/pathname.h> 30e802abbdSTim Haley #include <sys/proc.h> 31e802abbdSTim Haley #include <sys/mode.h> 32e802abbdSTim Haley #include <sys/vnode.h> 33e802abbdSTim Haley #include <sys/ddi.h> 34e802abbdSTim Haley #include <sys/sunddi.h> 35e802abbdSTim Haley #include <sys/sunldi.h> 36e802abbdSTim Haley #include <sys/uio.h> 37e802abbdSTim Haley #include <sys/attr.h> 38e802abbdSTim Haley #include <sys/acl.h> 39e802abbdSTim Haley #include <sys/fs/zut.h> 40e802abbdSTim Haley 41e802abbdSTim Haley ldi_ident_t zut_li = NULL; 42e802abbdSTim Haley dev_info_t *zut_dip; 43e802abbdSTim Haley 44e802abbdSTim Haley static int 45e802abbdSTim Haley zut_open_dir(char *path, vnode_t *startvp, cred_t *cr, int flags, 46e802abbdSTim Haley pathname_t *realpn, vnode_t **dvn) 47e802abbdSTim Haley { 48e802abbdSTim Haley pathname_t pn; 49e802abbdSTim Haley vnode_t *vp; 50e802abbdSTim Haley vnode_t *rootvp; 51e802abbdSTim Haley proc_t *p = curproc; 52e802abbdSTim Haley int error; 53e802abbdSTim Haley 54e802abbdSTim Haley pn_alloc(&pn); 55e802abbdSTim Haley (void) strlcpy(pn.pn_buf, path, MAXPATHLEN); 56e802abbdSTim Haley pn.pn_pathlen = strlen(path); 57e802abbdSTim Haley 58e802abbdSTim Haley mutex_enter(&p->p_lock); /* for u_rdir and u_cdir */ 59e802abbdSTim Haley if ((rootvp = PTOU(p)->u_rdir) == NULL) 60e802abbdSTim Haley rootvp = rootdir; 61e802abbdSTim Haley else if (rootvp != rootdir) /* no need to VN_HOLD rootdir */ 62e802abbdSTim Haley VN_HOLD(rootvp); 63e802abbdSTim Haley 64e802abbdSTim Haley if (pn.pn_path[0] == '/') { 65e802abbdSTim Haley vp = rootvp; 66e802abbdSTim Haley } else { 67e802abbdSTim Haley vp = (startvp == NULL) ? PTOU(p)->u_cdir : startvp; 68e802abbdSTim Haley } 69e802abbdSTim Haley VN_HOLD(vp); 70e802abbdSTim Haley mutex_exit(&p->p_lock); 71e802abbdSTim Haley 72e802abbdSTim Haley /* 73e802abbdSTim Haley * Skip over leading slashes 74e802abbdSTim Haley */ 75e802abbdSTim Haley while (pn.pn_path[0] == '/') { 76e802abbdSTim Haley pn.pn_path++; 77e802abbdSTim Haley pn.pn_pathlen--; 78e802abbdSTim Haley } 79e802abbdSTim Haley 80e802abbdSTim Haley error = lookuppnvp(&pn, realpn, flags | FOLLOW, NULL, 81e802abbdSTim Haley dvn, rootvp, vp, cr); 82e802abbdSTim Haley 83e802abbdSTim Haley /* 84e802abbdSTim Haley * If we lack read access to the directory, we should error out. 85e802abbdSTim Haley */ 86e802abbdSTim Haley if (!error) { 87e802abbdSTim Haley if (vfs_has_feature((*dvn)->v_vfsp, VFSFT_ACEMASKONACCESS)) { 88e802abbdSTim Haley error = VOP_ACCESS(*dvn, ACE_LIST_DIRECTORY, 89e802abbdSTim Haley V_ACE_MASK, cr, NULL); 90e802abbdSTim Haley } else { 91e802abbdSTim Haley error = VOP_ACCESS(*dvn, VREAD, 0, cr, NULL); 92e802abbdSTim Haley } 93e802abbdSTim Haley } 94e802abbdSTim Haley 95e802abbdSTim Haley pn_free(&pn); 96e802abbdSTim Haley 97e802abbdSTim Haley return (error); 98e802abbdSTim Haley } 99e802abbdSTim Haley 100e802abbdSTim Haley static int 101e802abbdSTim Haley zut_readdir(intptr_t arg, cred_t *cr, int iflag, int *rvalp) 102e802abbdSTim Haley { 103e802abbdSTim Haley zut_readdir_t *zr; 104e802abbdSTim Haley struct iovec aiov; 105e802abbdSTim Haley struct uio auio; 106e802abbdSTim Haley vnode_t *dvn = NULL; 107e802abbdSTim Haley vnode_t *fvn = NULL; 108e802abbdSTim Haley char *kbuf; 109e802abbdSTim Haley int flags = 0; 110e802abbdSTim Haley int error, rc; 111e802abbdSTim Haley 112e802abbdSTim Haley zr = kmem_zalloc(sizeof (zut_readdir_t), KM_SLEEP); 113e802abbdSTim Haley error = ddi_copyin((void *)arg, zr, sizeof (zut_readdir_t), iflag); 114e802abbdSTim Haley if (error) 115e802abbdSTim Haley goto zutr_bail; 116e802abbdSTim Haley 117e802abbdSTim Haley kbuf = kmem_zalloc(zr->zr_buflen, KM_SLEEP); 118e802abbdSTim Haley 119e802abbdSTim Haley zr->zr_retcode = zut_open_dir(zr->zr_dir, NULL, cr, flags, NULL, &dvn); 120e802abbdSTim Haley if (zr->zr_retcode) 121e802abbdSTim Haley goto zutr_done; 122e802abbdSTim Haley 123e802abbdSTim Haley if (zr->zr_reqflags & ZUT_XATTR) { 124e802abbdSTim Haley vattr_t vattr; 125e802abbdSTim Haley 126e802abbdSTim Haley zr->zr_retcode = VOP_LOOKUP(dvn, zr->zr_file, &fvn, 127e802abbdSTim Haley NULL, flags, NULL, cr, NULL, NULL, NULL); 128e802abbdSTim Haley VN_RELE(dvn); 129e802abbdSTim Haley dvn = NULL; 130e802abbdSTim Haley if (zr->zr_retcode) 131e802abbdSTim Haley goto zutr_done; 132e802abbdSTim Haley 133e802abbdSTim Haley /* 134e802abbdSTim Haley * In order to access hidden attribute directory the 135e802abbdSTim Haley * user must have appropriate read access and be able 136e802abbdSTim Haley * to stat() the file 137e802abbdSTim Haley */ 138e802abbdSTim Haley if (vfs_has_feature(fvn->v_vfsp, VFSFT_ACEMASKONACCESS)) { 139e802abbdSTim Haley zr->zr_retcode = VOP_ACCESS(fvn, ACE_READ_NAMED_ATTRS, 140e802abbdSTim Haley V_ACE_MASK, cr, NULL); 141e802abbdSTim Haley } else { 142e802abbdSTim Haley zr->zr_retcode = VOP_ACCESS(fvn, VREAD, 0, cr, NULL); 143e802abbdSTim Haley } 144e802abbdSTim Haley if (zr->zr_retcode) 145e802abbdSTim Haley goto zutr_done; 146e802abbdSTim Haley 147e802abbdSTim Haley vattr.va_mask = AT_ALL; 148e802abbdSTim Haley zr->zr_retcode = VOP_GETATTR(fvn, &vattr, 0, cr, NULL); 149e802abbdSTim Haley if (zr->zr_retcode) 150e802abbdSTim Haley goto zutr_done; 151e802abbdSTim Haley 152e802abbdSTim Haley zr->zr_retcode = VOP_LOOKUP(fvn, "", &dvn, NULL, 153e802abbdSTim Haley flags | LOOKUP_XATTR, NULL, cr, NULL, NULL, NULL); 154e802abbdSTim Haley VN_RELE(fvn); 155e802abbdSTim Haley if (zr->zr_retcode) 156e802abbdSTim Haley goto zutr_done; 157e802abbdSTim Haley } 158e802abbdSTim Haley 159e802abbdSTim Haley aiov.iov_base = kbuf; 160e802abbdSTim Haley aiov.iov_len = zr->zr_buflen; 161e802abbdSTim Haley auio.uio_iov = &aiov; 162e802abbdSTim Haley auio.uio_iovcnt = 1; 163e802abbdSTim Haley auio.uio_loffset = zr->zr_loffset; 164e802abbdSTim Haley auio.uio_segflg = UIO_SYSSPACE; 165e802abbdSTim Haley auio.uio_resid = zr->zr_buflen; 166e802abbdSTim Haley auio.uio_fmode = 0; 167e802abbdSTim Haley auio.uio_extflg = UIO_COPY_CACHED; 168e802abbdSTim Haley 169e802abbdSTim Haley if (zr->zr_reqflags & ZUT_EXTRDDIR) 170e802abbdSTim Haley flags |= V_RDDIR_ENTFLAGS; 171e802abbdSTim Haley if (zr->zr_reqflags & ZUT_ACCFILTER) 172e802abbdSTim Haley flags |= V_RDDIR_ACCFILTER; 173e802abbdSTim Haley 174e802abbdSTim Haley (void) VOP_RWLOCK(dvn, V_WRITELOCK_FALSE, NULL); 175e802abbdSTim Haley zr->zr_retcode = VOP_READDIR(dvn, &auio, cr, &zr->zr_eof, 176e802abbdSTim Haley NULL, flags); 177e802abbdSTim Haley VOP_RWUNLOCK(dvn, V_WRITELOCK_FALSE, NULL); 178e802abbdSTim Haley VN_RELE(dvn); 179e802abbdSTim Haley 180e802abbdSTim Haley zr->zr_bytes = aiov.iov_base - kbuf; 181e802abbdSTim Haley zr->zr_loffset = auio.uio_loffset; 182e802abbdSTim Haley 183e802abbdSTim Haley error = ddi_copyout(kbuf, (void *)(uintptr_t)zr->zr_buf, 184e802abbdSTim Haley zr->zr_buflen, iflag); 185e802abbdSTim Haley 186e802abbdSTim Haley zutr_done: 187e802abbdSTim Haley kmem_free(kbuf, zr->zr_buflen); 188e802abbdSTim Haley rc = ddi_copyout(zr, (void *)arg, sizeof (zut_readdir_t), iflag); 189e802abbdSTim Haley if (error == 0) 190e802abbdSTim Haley error = rc; 191e802abbdSTim Haley 192e802abbdSTim Haley zutr_bail: 193e802abbdSTim Haley kmem_free(zr, sizeof (zut_readdir_t)); 194e802abbdSTim Haley if (rvalp) 195e802abbdSTim Haley *rvalp = error; 196e802abbdSTim Haley return (error); 197e802abbdSTim Haley } 198e802abbdSTim Haley 199e802abbdSTim Haley static int 200e802abbdSTim Haley zut_stat64(vnode_t *vp, struct stat64 *sb, uint64_t *xvs, int flag, cred_t *cr) 201e802abbdSTim Haley { 202e802abbdSTim Haley xoptattr_t *xoap = NULL; 203e802abbdSTim Haley xvattr_t xv = { 0 }; 204e802abbdSTim Haley int error; 205e802abbdSTim Haley 206e802abbdSTim Haley xva_init(&xv); 207e802abbdSTim Haley 208e802abbdSTim Haley XVA_SET_REQ(&xv, XAT_ARCHIVE); 209e802abbdSTim Haley XVA_SET_REQ(&xv, XAT_SYSTEM); 210e802abbdSTim Haley XVA_SET_REQ(&xv, XAT_READONLY); 211e802abbdSTim Haley XVA_SET_REQ(&xv, XAT_HIDDEN); 212e802abbdSTim Haley XVA_SET_REQ(&xv, XAT_NOUNLINK); 213e802abbdSTim Haley XVA_SET_REQ(&xv, XAT_IMMUTABLE); 214e802abbdSTim Haley XVA_SET_REQ(&xv, XAT_APPENDONLY); 215e802abbdSTim Haley XVA_SET_REQ(&xv, XAT_NODUMP); 216e802abbdSTim Haley XVA_SET_REQ(&xv, XAT_OPAQUE); 217e802abbdSTim Haley XVA_SET_REQ(&xv, XAT_AV_QUARANTINED); 218e802abbdSTim Haley XVA_SET_REQ(&xv, XAT_AV_MODIFIED); 2197a286c47SDai Ngo XVA_SET_REQ(&xv, XAT_REPARSE); 220*fd9ee8b5Sjoyce mcintosh XVA_SET_REQ(&xv, XAT_OFFLINE); 221*fd9ee8b5Sjoyce mcintosh XVA_SET_REQ(&xv, XAT_SPARSE); 222e802abbdSTim Haley 223e802abbdSTim Haley xv.xva_vattr.va_mask |= AT_STAT | AT_NBLOCKS | AT_BLKSIZE | AT_SIZE; 224e802abbdSTim Haley if (error = VOP_GETATTR(vp, &xv.xva_vattr, flag, cr, NULL)) 225e802abbdSTim Haley return (error); 226e802abbdSTim Haley 227e802abbdSTim Haley bzero(sb, sizeof (sb)); 228e802abbdSTim Haley sb->st_dev = xv.xva_vattr.va_fsid; 229e802abbdSTim Haley sb->st_ino = xv.xva_vattr.va_nodeid; 230e802abbdSTim Haley sb->st_mode = VTTOIF(xv.xva_vattr.va_type) | xv.xva_vattr.va_mode; 231e802abbdSTim Haley sb->st_nlink = xv.xva_vattr.va_nlink; 232e802abbdSTim Haley sb->st_uid = xv.xva_vattr.va_uid; 233e802abbdSTim Haley sb->st_gid = xv.xva_vattr.va_gid; 234e802abbdSTim Haley sb->st_rdev = xv.xva_vattr.va_rdev; 235e802abbdSTim Haley sb->st_size = xv.xva_vattr.va_size; 236e802abbdSTim Haley sb->st_atim = xv.xva_vattr.va_atime; 237e802abbdSTim Haley sb->st_mtim = xv.xva_vattr.va_mtime; 238e802abbdSTim Haley sb->st_ctim = xv.xva_vattr.va_ctime; 239e802abbdSTim Haley sb->st_blksize = xv.xva_vattr.va_blksize; 240e802abbdSTim Haley sb->st_blocks = xv.xva_vattr.va_nblocks; 241e802abbdSTim Haley sb->st_fstype[0] = 0; 242e802abbdSTim Haley 243e802abbdSTim Haley if ((xoap = xva_getxoptattr(&xv)) == NULL) 244e802abbdSTim Haley return (0); 245e802abbdSTim Haley 246e802abbdSTim Haley if (XVA_ISSET_RTN(&xv, XAT_ARCHIVE) && xoap->xoa_archive) 247e802abbdSTim Haley *xvs |= (1 << F_ARCHIVE); 248e802abbdSTim Haley if (XVA_ISSET_RTN(&xv, XAT_SYSTEM) && xoap->xoa_system) 249e802abbdSTim Haley *xvs |= (1 << F_SYSTEM); 250e802abbdSTim Haley if (XVA_ISSET_RTN(&xv, XAT_READONLY) && xoap->xoa_readonly) 251e802abbdSTim Haley *xvs |= (1 << F_READONLY); 252e802abbdSTim Haley if (XVA_ISSET_RTN(&xv, XAT_HIDDEN) && xoap->xoa_hidden) 253e802abbdSTim Haley *xvs |= (1 << F_HIDDEN); 254e802abbdSTim Haley if (XVA_ISSET_RTN(&xv, XAT_NOUNLINK) && xoap->xoa_nounlink) 255e802abbdSTim Haley *xvs |= (1 << F_NOUNLINK); 256e802abbdSTim Haley if (XVA_ISSET_RTN(&xv, XAT_IMMUTABLE) && xoap->xoa_immutable) 257e802abbdSTim Haley *xvs |= (1 << F_IMMUTABLE); 258e802abbdSTim Haley if (XVA_ISSET_RTN(&xv, XAT_APPENDONLY) && xoap->xoa_appendonly) 259e802abbdSTim Haley *xvs |= (1 << F_APPENDONLY); 260e802abbdSTim Haley if (XVA_ISSET_RTN(&xv, XAT_NODUMP) && xoap->xoa_nodump) 261e802abbdSTim Haley *xvs |= (1 << F_NODUMP); 262e802abbdSTim Haley if (XVA_ISSET_RTN(&xv, XAT_OPAQUE) && xoap->xoa_opaque) 263e802abbdSTim Haley *xvs |= (1 << F_OPAQUE); 264e802abbdSTim Haley if (XVA_ISSET_RTN(&xv, XAT_AV_QUARANTINED) && xoap->xoa_av_quarantined) 265e802abbdSTim Haley *xvs |= (1 << F_AV_QUARANTINED); 266e802abbdSTim Haley if (XVA_ISSET_RTN(&xv, XAT_AV_MODIFIED) && xoap->xoa_av_modified) 267e802abbdSTim Haley *xvs |= (1 << F_AV_MODIFIED); 2687a286c47SDai Ngo if (XVA_ISSET_RTN(&xv, XAT_REPARSE) && xoap->xoa_reparse) 2697a286c47SDai Ngo *xvs |= (1 << F_REPARSE); 270*fd9ee8b5Sjoyce mcintosh if (XVA_ISSET_RTN(&xv, XAT_OFFLINE) && xoap->xoa_offline) 271*fd9ee8b5Sjoyce mcintosh *xvs |= (1 << F_OFFLINE); 272*fd9ee8b5Sjoyce mcintosh if (XVA_ISSET_RTN(&xv, XAT_SPARSE) && xoap->xoa_sparse) 273*fd9ee8b5Sjoyce mcintosh *xvs |= (1 << F_SPARSE); 274e802abbdSTim Haley 275e802abbdSTim Haley return (0); 276e802abbdSTim Haley } 277e802abbdSTim Haley 278e802abbdSTim Haley /*ARGSUSED*/ 279e802abbdSTim Haley static int 280e802abbdSTim Haley zut_lookup(intptr_t arg, cred_t *cr, int iflag, int *rvalp) 281e802abbdSTim Haley { 282e802abbdSTim Haley zut_lookup_t *zl; 283e802abbdSTim Haley pathname_t rpn; 284e802abbdSTim Haley vnode_t *dvn = NULL; 285e802abbdSTim Haley vnode_t *fvn = NULL; 286e802abbdSTim Haley vnode_t *xdvn = NULL; 287e802abbdSTim Haley vnode_t *xfvn = NULL; 288e802abbdSTim Haley vnode_t *release = NULL; 289e802abbdSTim Haley int flags = 0; 290e802abbdSTim Haley int error, rc; 291e802abbdSTim Haley 292e802abbdSTim Haley zl = kmem_zalloc(sizeof (zut_lookup_t), KM_SLEEP); 293e802abbdSTim Haley 294e802abbdSTim Haley error = ddi_copyin((void *)arg, zl, sizeof (zut_lookup_t), iflag); 295e802abbdSTim Haley if (error) 296e802abbdSTim Haley goto zutl_bail; 297e802abbdSTim Haley 298e802abbdSTim Haley pn_alloc(&rpn); 299e802abbdSTim Haley bzero(rpn.pn_buf, MAXPATHLEN); 300e802abbdSTim Haley 301e802abbdSTim Haley zl->zl_retcode = zut_open_dir(zl->zl_dir, NULL, cr, flags, &rpn, &dvn); 302e802abbdSTim Haley if (zl->zl_retcode) 303e802abbdSTim Haley goto zutl_done; 304e802abbdSTim Haley 305e802abbdSTim Haley if (zl->zl_reqflags & ZUT_IGNORECASE) 306e802abbdSTim Haley flags |= FIGNORECASE; 307e802abbdSTim Haley 308e802abbdSTim Haley zl->zl_retcode = VOP_LOOKUP(dvn, zl->zl_file, &fvn, NULL, flags, NULL, 309e802abbdSTim Haley cr, NULL, &zl->zl_deflags, &rpn); 310e802abbdSTim Haley if (zl->zl_retcode) 311e802abbdSTim Haley goto zutl_done; 312e802abbdSTim Haley 313e802abbdSTim Haley release = fvn; 314e802abbdSTim Haley 315e802abbdSTim Haley if (zl->zl_reqflags & ZUT_XATTR) { 316e802abbdSTim Haley vattr_t vattr; 317e802abbdSTim Haley 318e802abbdSTim Haley /* 319e802abbdSTim Haley * In order to access hidden attribute directory the 320e802abbdSTim Haley * user must have appropriate read access and be able 321e802abbdSTim Haley * to stat() the file 322e802abbdSTim Haley */ 323e802abbdSTim Haley if (vfs_has_feature(fvn->v_vfsp, VFSFT_ACEMASKONACCESS)) { 324e802abbdSTim Haley zl->zl_retcode = VOP_ACCESS(fvn, ACE_READ_NAMED_ATTRS, 325e802abbdSTim Haley V_ACE_MASK, cr, NULL); 326e802abbdSTim Haley } else { 327e802abbdSTim Haley zl->zl_retcode = VOP_ACCESS(fvn, VREAD, 0, cr, NULL); 328e802abbdSTim Haley } 329e802abbdSTim Haley if (zl->zl_retcode) 330e802abbdSTim Haley goto zutl_done; 331e802abbdSTim Haley 332e802abbdSTim Haley vattr.va_mask = AT_ALL; 333e802abbdSTim Haley zl->zl_retcode = VOP_GETATTR(fvn, &vattr, 0, cr, NULL); 334e802abbdSTim Haley if (zl->zl_retcode) 335e802abbdSTim Haley goto zutl_done; 336e802abbdSTim Haley 337e802abbdSTim Haley zl->zl_retcode = VOP_LOOKUP(fvn, "", &xdvn, NULL, 338e802abbdSTim Haley flags | LOOKUP_XATTR, NULL, cr, NULL, NULL, NULL); 339e802abbdSTim Haley if (zl->zl_retcode) 340e802abbdSTim Haley goto zutl_done; 341e802abbdSTim Haley VN_RELE(fvn); 342e802abbdSTim Haley release = xdvn; 343e802abbdSTim Haley 344e802abbdSTim Haley zl->zl_retcode = VOP_LOOKUP(xdvn, zl->zl_xfile, &xfvn, 345e802abbdSTim Haley NULL, flags, NULL, cr, NULL, &zl->zl_deflags, &rpn); 346e802abbdSTim Haley if (zl->zl_retcode) 347e802abbdSTim Haley goto zutl_done; 348e802abbdSTim Haley VN_RELE(xdvn); 349e802abbdSTim Haley release = xfvn; 350e802abbdSTim Haley } 351e802abbdSTim Haley 352e802abbdSTim Haley if (zl->zl_reqflags & ZUT_GETSTAT) { 353e802abbdSTim Haley zl->zl_retcode = zut_stat64(release, 354e802abbdSTim Haley &zl->zl_statbuf, &zl->zl_xvattrs, 0, cr); 355e802abbdSTim Haley } 356e802abbdSTim Haley 357e802abbdSTim Haley zutl_done: 358e802abbdSTim Haley (void) strlcpy(zl->zl_real, rpn.pn_path, MAXPATHLEN); 359e802abbdSTim Haley 360e802abbdSTim Haley rc = ddi_copyout(zl, (void *)arg, sizeof (zut_lookup_t), iflag); 361e802abbdSTim Haley if (error == 0) 362e802abbdSTim Haley error = rc; 363e802abbdSTim Haley 364e802abbdSTim Haley if (release) 365e802abbdSTim Haley VN_RELE(release); 366e802abbdSTim Haley if (dvn) 367e802abbdSTim Haley VN_RELE(dvn); 368e802abbdSTim Haley pn_free(&rpn); 369e802abbdSTim Haley 370e802abbdSTim Haley zutl_bail: 371e802abbdSTim Haley kmem_free(zl, sizeof (zut_lookup_t)); 372e802abbdSTim Haley if (rvalp) 373e802abbdSTim Haley *rvalp = error; 374e802abbdSTim Haley return (error); 375e802abbdSTim Haley } 376e802abbdSTim Haley 377e802abbdSTim Haley /*ARGSUSED*/ 378e802abbdSTim Haley static int 379e802abbdSTim Haley zut_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) 380e802abbdSTim Haley { 381e802abbdSTim Haley int error; 382e802abbdSTim Haley 383e802abbdSTim Haley if (getminor(dev) != 0) 384e802abbdSTim Haley return (ENXIO); 385e802abbdSTim Haley 386e802abbdSTim Haley if (cmd <= ZUT_IOC_MIN_CMD || cmd >= ZUT_IOC_MAX_CMD) 387e802abbdSTim Haley return (EINVAL); 388e802abbdSTim Haley 389e802abbdSTim Haley switch (cmd) { 390e802abbdSTim Haley case ZUT_IOC_LOOKUP: 391e802abbdSTim Haley error = zut_lookup(arg, cr, flag, rvalp); 392e802abbdSTim Haley break; 393e802abbdSTim Haley case ZUT_IOC_READDIR: 394e802abbdSTim Haley error = zut_readdir(arg, cr, flag, rvalp); 395e802abbdSTim Haley default: 396e802abbdSTim Haley break; 397e802abbdSTim Haley } 398e802abbdSTim Haley 399e802abbdSTim Haley return (error); 400e802abbdSTim Haley } 401e802abbdSTim Haley 402e802abbdSTim Haley static int 403e802abbdSTim Haley zut_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 404e802abbdSTim Haley { 405e802abbdSTim Haley if (cmd != DDI_ATTACH) 406e802abbdSTim Haley return (DDI_FAILURE); 407e802abbdSTim Haley 408e802abbdSTim Haley if (ddi_create_minor_node(dip, "zut", S_IFCHR, 0, 409e802abbdSTim Haley DDI_PSEUDO, 0) == DDI_FAILURE) 410e802abbdSTim Haley return (DDI_FAILURE); 411e802abbdSTim Haley 412e802abbdSTim Haley zut_dip = dip; 413e802abbdSTim Haley 414e802abbdSTim Haley ddi_report_dev(dip); 415e802abbdSTim Haley 416e802abbdSTim Haley return (DDI_SUCCESS); 417e802abbdSTim Haley } 418e802abbdSTim Haley 419e802abbdSTim Haley static int 420e802abbdSTim Haley zut_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 421e802abbdSTim Haley { 422e802abbdSTim Haley if (cmd != DDI_DETACH) 423e802abbdSTim Haley return (DDI_FAILURE); 424e802abbdSTim Haley 425e802abbdSTim Haley zut_dip = NULL; 426e802abbdSTim Haley 427e802abbdSTim Haley ddi_prop_remove_all(dip); 428e802abbdSTim Haley ddi_remove_minor_node(dip, NULL); 429e802abbdSTim Haley 430e802abbdSTim Haley return (DDI_SUCCESS); 431e802abbdSTim Haley } 432e802abbdSTim Haley 433e802abbdSTim Haley /*ARGSUSED*/ 434e802abbdSTim Haley static int 435e802abbdSTim Haley zut_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 436e802abbdSTim Haley { 437e802abbdSTim Haley switch (infocmd) { 438e802abbdSTim Haley case DDI_INFO_DEVT2DEVINFO: 439e802abbdSTim Haley *result = zut_dip; 440e802abbdSTim Haley return (DDI_SUCCESS); 441e802abbdSTim Haley 442e802abbdSTim Haley case DDI_INFO_DEVT2INSTANCE: 443e802abbdSTim Haley *result = (void *)0; 444e802abbdSTim Haley return (DDI_SUCCESS); 445e802abbdSTim Haley } 446e802abbdSTim Haley 447e802abbdSTim Haley return (DDI_FAILURE); 448e802abbdSTim Haley } 449e802abbdSTim Haley 450e802abbdSTim Haley /*ARGSUSED*/ 451e802abbdSTim Haley int 452e802abbdSTim Haley zut_open(dev_t *devp, int flag, int otyp, cred_t *cr) 453e802abbdSTim Haley { 454e802abbdSTim Haley minor_t minor = getminor(*devp); 455e802abbdSTim Haley 456e802abbdSTim Haley if (minor == 0) /* This is the control device */ 457e802abbdSTim Haley return (0); 458e802abbdSTim Haley 459e802abbdSTim Haley return (ENXIO); 460e802abbdSTim Haley } 461e802abbdSTim Haley 462e802abbdSTim Haley /*ARGSUSED*/ 463e802abbdSTim Haley int 464e802abbdSTim Haley zut_close(dev_t dev, int flag, int otyp, cred_t *cr) 465e802abbdSTim Haley { 466e802abbdSTim Haley minor_t minor = getminor(dev); 467e802abbdSTim Haley 468e802abbdSTim Haley if (minor == 0) /* This is the control device */ 469e802abbdSTim Haley return (0); 470e802abbdSTim Haley 471e802abbdSTim Haley return (ENXIO); 472e802abbdSTim Haley } 473e802abbdSTim Haley 474e802abbdSTim Haley /* 475e802abbdSTim Haley * /dev/zut is the control node, i.e. minor 0. 476e802abbdSTim Haley * 477e802abbdSTim Haley * There are no other minor nodes, and /dev/zut basically does nothing 478e802abbdSTim Haley * other than serve up ioctls. 479e802abbdSTim Haley */ 480e802abbdSTim Haley static struct cb_ops zut_cb_ops = { 481e802abbdSTim Haley zut_open, /* open */ 482e802abbdSTim Haley zut_close, /* close */ 483e802abbdSTim Haley nodev, /* strategy */ 484e802abbdSTim Haley nodev, /* print */ 485e802abbdSTim Haley nodev, /* dump */ 486e802abbdSTim Haley nodev, /* read */ 487e802abbdSTim Haley nodev, /* write */ 488e802abbdSTim Haley zut_ioctl, /* ioctl */ 489e802abbdSTim Haley nodev, /* devmap */ 490e802abbdSTim Haley nodev, /* mmap */ 491e802abbdSTim Haley nodev, /* segmap */ 492e802abbdSTim Haley nochpoll, /* poll */ 493e802abbdSTim Haley ddi_prop_op, /* prop_op */ 494e802abbdSTim Haley NULL, /* streamtab */ 495e802abbdSTim Haley D_NEW | D_MP | D_64BIT, /* Driver compatibility flag */ 496e802abbdSTim Haley CB_REV, /* version */ 497e802abbdSTim Haley nodev, /* async read */ 498e802abbdSTim Haley nodev, /* async write */ 499e802abbdSTim Haley }; 500e802abbdSTim Haley 501e802abbdSTim Haley static struct dev_ops zut_dev_ops = { 502e802abbdSTim Haley DEVO_REV, /* version */ 503e802abbdSTim Haley 0, /* refcnt */ 504e802abbdSTim Haley zut_info, /* info */ 505e802abbdSTim Haley nulldev, /* identify */ 506e802abbdSTim Haley nulldev, /* probe */ 507e802abbdSTim Haley zut_attach, /* attach */ 508e802abbdSTim Haley zut_detach, /* detach */ 509e802abbdSTim Haley nodev, /* reset */ 510e802abbdSTim Haley &zut_cb_ops, /* driver operations */ 511e802abbdSTim Haley NULL /* no bus operations */ 512e802abbdSTim Haley }; 513e802abbdSTim Haley 514e802abbdSTim Haley static struct modldrv zut_modldrv = { 515e802abbdSTim Haley &mod_driverops, "ZFS unit test " ZUT_VERSION_STRING, 516e802abbdSTim Haley &zut_dev_ops 517e802abbdSTim Haley }; 518e802abbdSTim Haley 519e802abbdSTim Haley static struct modlinkage modlinkage = { 520e802abbdSTim Haley MODREV_1, 521e802abbdSTim Haley (void *)&zut_modldrv, 522e802abbdSTim Haley NULL 523e802abbdSTim Haley }; 524e802abbdSTim Haley 525e802abbdSTim Haley int 526e802abbdSTim Haley _init(void) 527e802abbdSTim Haley { 528e802abbdSTim Haley int error; 529e802abbdSTim Haley 530e802abbdSTim Haley if ((error = mod_install(&modlinkage)) != 0) { 531e802abbdSTim Haley return (error); 532e802abbdSTim Haley } 533e802abbdSTim Haley 534e802abbdSTim Haley error = ldi_ident_from_mod(&modlinkage, &zut_li); 535e802abbdSTim Haley ASSERT(error == 0); 536e802abbdSTim Haley 537e802abbdSTim Haley return (0); 538e802abbdSTim Haley } 539e802abbdSTim Haley 540e802abbdSTim Haley int 541e802abbdSTim Haley _fini(void) 542e802abbdSTim Haley { 543e802abbdSTim Haley int error; 544e802abbdSTim Haley 545e802abbdSTim Haley if ((error = mod_remove(&modlinkage)) != 0) 546e802abbdSTim Haley return (error); 547e802abbdSTim Haley 548e802abbdSTim Haley ldi_ident_release(zut_li); 549e802abbdSTim Haley zut_li = NULL; 550e802abbdSTim Haley 551e802abbdSTim Haley return (error); 552e802abbdSTim Haley } 553e802abbdSTim Haley 554e802abbdSTim Haley int 555e802abbdSTim Haley _info(struct modinfo *modinfop) 556e802abbdSTim Haley { 557e802abbdSTim Haley return (mod_info(&modlinkage, modinfop)); 558e802abbdSTim Haley } 559