/* * smb_vop_rename() * * The rename is for files in the same tree (identical TID) only. */ int smb_vop_rename(vnode_t *from_dvp, char *from_name, vnode_t *to_dvp, char *to_name, int flags, cred_t *cr) { int error; int option_flags = 0; char *from, *to, *fbuf, *tbuf; if (flags & SMB_IGNORE_CASE) option_flags = FIGNORECASE; if (flags & SMB_CATIA) { tbuf = kmem_zalloc(MAXNAMELEN, KM_SLEEP); to = smb_vop_catia_v5tov4(to_name, tbuf, MAXNAMELEN); if (strchr(to, '/') != NULL) { kmem_free(tbuf, MAXNAMELEN); return (EILSEQ); } fbuf = kmem_zalloc(MAXNAMELEN, KM_SLEEP); from = smb_vop_catia_v5tov4(from_name, fbuf, MAXNAMELEN); error = VOP_RENAME(from_dvp, from, to_dvp, to, cr, &smb_ct, option_flags); kmem_free(tbuf, MAXNAMELEN); kmem_free(fbuf, MAXNAMELEN); return (error); } error = VOP_RENAME(from_dvp, from_name, to_dvp, to_name, cr, &smb_ct, option_flags); return (error); }
int smb_vop_mkdir(vnode_t *dvp, char *name, smb_attr_t *attr, vnode_t **vpp, int flags, cred_t *cr, vsecattr_t *vsap) { int error; int option_flags = 0; xvattr_t xvattr; vattr_t *vap; char *np = name; char namebuf[MAXNAMELEN]; if (flags & SMB_IGNORE_CASE) option_flags = FIGNORECASE; attr->sa_vattr.va_mask = 0; if (vfs_has_feature(dvp->v_vfsp, VFSFT_XVATTR)) { smb_vop_setup_xvattr(attr, &xvattr); vap = &xvattr.xva_vattr; } else { smb_sa_to_va_mask(attr->sa_mask, &attr->sa_vattr.va_mask); vap = &attr->sa_vattr; } if (flags & SMB_CATIA) { np = smb_vop_catia_v5tov4(name, namebuf, sizeof (namebuf)); if (strchr(np, '/') != NULL) return (EILSEQ); } error = VOP_MKDIR(dvp, np, vap, vpp, cr, &smb_ct, option_flags, vsap); return (error); }
/* * smb_vop_link(target-dir-vp, source-file-vp, target-name) * * Create a link - same tree (identical TID) only. */ int smb_vop_link(vnode_t *to_dvp, vnode_t *from_vp, char *to_name, int flags, cred_t *cr) { int option_flags = 0; char *np, *buf; int rc; if (flags & SMB_IGNORE_CASE) option_flags = FIGNORECASE; if (flags & SMB_CATIA) { buf = kmem_zalloc(MAXNAMELEN, KM_SLEEP); np = smb_vop_catia_v5tov4(to_name, buf, MAXNAMELEN); if (strchr(np, '/') != NULL) { kmem_free(buf, MAXNAMELEN); return (EILSEQ); } rc = VOP_LINK(to_dvp, from_vp, np, cr, &smb_ct, option_flags); kmem_free(buf, MAXNAMELEN); return (rc); } rc = VOP_LINK(to_dvp, from_vp, to_name, cr, &smb_ct, option_flags); return (rc); }
/* * CATIA Translation of a pathname component prior to passing it to lookuppnvp * * If the translated component name contains a '/' NULL is returned. * The caller should treat this as error EILSEQ. It is not valid to * have a directory name with a '/'. */ static char * smb_pathname_catia_v5tov4(smb_request_t *sr, char *name, char *namebuf, int buflen) { char *namep; if (SMB_TREE_SUPPORTS_CATIA(sr)) { namep = smb_vop_catia_v5tov4(name, namebuf, buflen); if (strchr(namep, '/') != NULL) return (NULL); return (namep); } return (name); }
/* * smb_vop_rmdir() * * Only simple rmdir supported, consistent with NT semantics * (can only remove an empty directory). * * The third argument to VOP_RMDIR is the current directory of * the process. It allows rmdir wants to EINVAL if one tries to * remove ".". Since SMB servers do not know what their clients' * current directories are, we fake it by supplying a vnode known * to exist and illegal to remove (rootdir). */ int smb_vop_rmdir(vnode_t *dvp, char *name, int flags, cred_t *cr) { int error; int option_flags = 0; char *np = name; char namebuf[MAXNAMELEN]; if (flags & SMB_IGNORE_CASE) option_flags = FIGNORECASE; if (flags & SMB_CATIA) np = smb_vop_catia_v5tov4(name, namebuf, sizeof (namebuf)); error = VOP_RMDIR(dvp, np, rootdir, cr, &smb_ct, option_flags); return (error); }
/* * smb_vop_lookup * * dvp: directory vnode (in) * name: name of file to be looked up (in) * vpp: looked-up vnode (out) * od_name: on-disk name of file (out). * This parameter is optional. If a pointer is passed in, it * must be allocated with MAXNAMELEN bytes * rootvp: vnode of the tree root (in) * This parameter is always passed in non-NULL except at the time * of share set up. * direntflags: dirent flags returned from VOP_LOOKUP */ int smb_vop_lookup( vnode_t *dvp, char *name, vnode_t **vpp, char *od_name, int flags, int *direntflags, vnode_t *rootvp, cred_t *cr) { int error = 0; int option_flags = 0; pathname_t rpn; char *np = name; char namebuf[MAXNAMELEN]; if (*name == '\0') return (EINVAL); ASSERT(vpp); *vpp = NULL; *direntflags = 0; if ((name[0] == '.') && (name[1] == '.') && (name[2] == 0)) { if (rootvp && (dvp == rootvp)) { VN_HOLD(dvp); *vpp = dvp; return (0); } if (dvp->v_flag & VROOT) { vfs_t *vfsp; vnode_t *cvp = dvp; /* * Set dvp and check for races with forced unmount * (see lookuppnvp()) */ vfsp = cvp->v_vfsp; vfs_rlock_wait(vfsp); if (((dvp = cvp->v_vfsp->vfs_vnodecovered) == NULL) || (cvp->v_vfsp->vfs_flag & VFS_UNMOUNTED)) { vfs_unlock(vfsp); return (EIO); } vfs_unlock(vfsp); } } if (flags & SMB_IGNORE_CASE) option_flags = FIGNORECASE; if (flags & SMB_CATIA) np = smb_vop_catia_v5tov4(name, namebuf, sizeof (namebuf)); pn_alloc(&rpn); error = VOP_LOOKUP(dvp, np, vpp, NULL, option_flags, NULL, cr, &smb_ct, direntflags, &rpn); if ((error == 0) && od_name) { bzero(od_name, MAXNAMELEN); np = (option_flags == FIGNORECASE) ? rpn.pn_buf : name; if (flags & SMB_CATIA) smb_vop_catia_v4tov5(np, od_name, MAXNAMELEN); else (void) strlcpy(od_name, np, MAXNAMELEN); } pn_free(&rpn); return (error); }