/* * CATIA translation of a pathname component after returning from lookuppnvp */ static char * smb_pathname_catia_v4tov5(smb_request_t *sr, char *name, char *namebuf, int buflen) { if (SMB_TREE_SUPPORTS_CATIA(sr)) { smb_vop_catia_v4tov5(name, namebuf, buflen); return (namebuf); } return (name); }
/* * 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); }
/* * smb_odir_next_odirent * * Find the next directory entry in d_buf. If d_bufptr is NULL (buffer * is empty or we've reached the end of it), read the next set of * entries from the file system (vop_readdir). * * File systems which support VFSFT_EDIRENT_FLAGS will return the * directory entries as a buffer of edirent_t structure. Others will * return a buffer of dirent64_t structures. For simplicity translate * the data into an smb_odirent_t structure. * The ed_name/d_name in d_buf is NULL terminated by the file system. * * Some file systems can have directories larger than SMB_MAXDIRSIZE. * If the odirent offset >= SMB_MAXDIRSIZE return ENOENT and set d_eof * to true to stop subsequent calls to smb_vop_readdir. * * Returns: * 0 - success. odirent is populated with the next directory entry * ENOENT - no more directory entries * errno - error */ static int smb_odir_next_odirent(smb_odir_t *od, smb_odirent_t *odirent) { int rc; int reclen; int eof; dirent64_t *dp; edirent_t *edp; char *np; uint32_t abe_flag = 0; ASSERT(MUTEX_HELD(&od->d_mutex)); bzero(odirent, sizeof (smb_odirent_t)); if (od->d_bufptr != NULL) { if (od->d_flags & SMB_ODIR_FLAG_EDIRENT) reclen = od->d_edp->ed_reclen; else reclen = od->d_dp->d_reclen; if (reclen == 0) { od->d_bufptr = NULL; } else { od->d_bufptr += reclen; if (od->d_bufptr >= od->d_buf + od->d_bufsize) od->d_bufptr = NULL; } } if (od->d_bufptr == NULL) { if (od->d_eof) return (ENOENT); od->d_bufsize = sizeof (od->d_buf); if (od->d_flags & SMB_ODIR_FLAG_ABE) abe_flag = SMB_ABE; rc = smb_vop_readdir(od->d_dnode->vp, od->d_offset, od->d_buf, &od->d_bufsize, &eof, abe_flag, od->d_cred); if ((rc == 0) && (od->d_bufsize == 0)) rc = ENOENT; if (rc != 0) { od->d_bufptr = NULL; od->d_bufsize = 0; return (rc); } od->d_eof = (eof != 0); od->d_bufptr = od->d_buf; } if (od->d_flags & SMB_ODIR_FLAG_EDIRENT) od->d_offset = od->d_edp->ed_off; else od->d_offset = od->d_dp->d_off; if (od->d_offset >= SMB_MAXDIRSIZE) { od->d_bufptr = NULL; od->d_bufsize = 0; od->d_eof = B_TRUE; return (ENOENT); } if (od->d_flags & SMB_ODIR_FLAG_EDIRENT) { edp = od->d_edp; odirent->od_ino = edp->ed_ino; odirent->od_eflags = edp->ed_eflags; np = edp->ed_name; } else { dp = od->d_dp; odirent->od_ino = dp->d_ino; odirent->od_eflags = 0; np = dp->d_name; } if ((od->d_flags & SMB_ODIR_FLAG_CATIA) && ((od->d_flags & SMB_ODIR_FLAG_XATTR) == 0)) { smb_vop_catia_v4tov5(np, odirent->od_name, sizeof (odirent->od_name)); } else { (void) strlcpy(odirent->od_name, np, sizeof (odirent->od_name)); } return (0); }