summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/fs/smbsrv/smb_vops.c
diff options
context:
space:
mode:
authorjose borrego <Jose.Borrego@Sun.COM>2009-02-01 19:44:54 -0700
committerjose borrego <Jose.Borrego@Sun.COM>2009-02-01 19:44:54 -0700
commit7f667e74610492ddbce8ce60f52ece95d2401949 (patch)
tree2e81974f83f306484e9e5617b0996a0c1186d753 /usr/src/uts/common/fs/smbsrv/smb_vops.c
parent947caa0ed80d272c3bda0c220e088b61b027809a (diff)
downloadillumos-gate-7f667e74610492ddbce8ce60f52ece95d2401949.tar.gz
6792084 smb_node_lookup should not take ownership of the hold on vnode passed as a parameter
6792299 winreg EnumKey should enumerate subkeys of any key 6582194 Replace getdents with readdir 6790756 smb_vss_lookup_nodes doesn't release its hold on vnode if smb_node_lookup fails 6791568 Solaris CIFS server only accepts pre-Windows 2000 user logon name 6793375 Unable to map a share with a user on a trusted domain 6796947 invalid assert in smb_vop_getattr 6581736 IPv6 support 6788345 smbadm list output only shows one trusted domain 6796594 Array overrun in libmlrpc 6797782 Need a SAM abstraction layer 6764696 Insufficient access while attempting to modify UserAccountControl attribute of a machine account 6798908 Refresh after enabling network interfaces should trigger DC discovery 6798825 Replace the smb_vop_readdir mechanism with the smb_odir_t object
Diffstat (limited to 'usr/src/uts/common/fs/smbsrv/smb_vops.c')
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_vops.c756
1 files changed, 58 insertions, 698 deletions
diff --git a/usr/src/uts/common/fs/smbsrv/smb_vops.c b/usr/src/uts/common/fs/smbsrv/smb_vops.c
index 5ebb2d6a3f..84643568f8 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_vops.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_vops.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -40,36 +40,13 @@
#include <smbsrv/smb_vops.h>
#include <smbsrv/string.h>
-#include <smbsrv/smbtrans.h>
#include <smbsrv/smb_fsops.h>
#include <smbsrv/smb_kproto.h>
#include <smbsrv/smb_incl.h>
-void
-smb_vop_setup_xvattr(smb_attr_t *smb_attr, xvattr_t *xvattr);
-
-static int
-smb_vop_readdir_readpage(vnode_t *, void *, uint32_t, int *, cred_t *);
-
-static int
-smb_vop_readdir_entry(vnode_t *, uint32_t *, char *, int *,
- ino64_t *, vnode_t **, char *, int, cred_t *, char *, int);
-
-static int
-smb_vop_getdents_entries(smb_node_t *, uint32_t *, int32_t *, char *, uint32_t,
- smb_request_t *, cred_t *, char *, int *, int, char *);
-
-extern int
-smb_gather_dents_info(char *args, ino_t fileid, int namelen,
- char *name, uint32_t cookie, int32_t *countp,
- smb_attr_t *attr, struct smb_node *snode,
- char *shortname, char *name83);
-
-static void
-smb_sa_to_va_mask(uint_t sa_mask, uint_t *va_maskp);
-
-static
-callb_cpr_t *smb_lock_frlock_callback(flk_cb_when_t, void *);
+static void smb_vop_setup_xvattr(smb_attr_t *smb_attr, xvattr_t *xvattr);
+static void smb_sa_to_va_mask(uint_t sa_mask, uint_t *va_maskp);
+static callb_cpr_t *smb_lock_frlock_callback(flk_cb_when_t, void *);
extern sysid_t lm_alloc_sysidt();
@@ -235,6 +212,8 @@ smb_vop_write(vnode_t *vp, uio_t *uiop, int ioflag, uint32_t *lcount,
*
* File systems without VFSFT_XVATTR do not support DOS attributes or create
* time (crtime). In this case the mtime is used as the crtime.
+ * Likewise if VOP_GETATTR doesn't return any system attributes the dosattr
+ * is 0 and the mtime is used as the crtime.
*/
int
smb_vop_getattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *ret_attr,
@@ -273,69 +252,50 @@ smb_vop_getattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *ret_attr,
ret_attr->sa_vattr = tmp_xvattr.xva_vattr;
ret_attr->sa_dosattr = 0;
- ASSERT(tmp_xvattr.xva_vattr.va_mask & AT_XVATTR);
+ if (tmp_xvattr.xva_vattr.va_mask & AT_XVATTR) {
+ xoap = xva_getxoptattr(&tmp_xvattr);
+ ASSERT(xoap);
- xoap = xva_getxoptattr(&tmp_xvattr);
- ASSERT(xoap);
-
- if (XVA_ISSET_RTN(&tmp_xvattr, XAT_READONLY)) {
- if (xoap->xoa_readonly)
+ if ((XVA_ISSET_RTN(&tmp_xvattr, XAT_READONLY)) &&
+ (xoap->xoa_readonly)) {
ret_attr->sa_dosattr |= FILE_ATTRIBUTE_READONLY;
- }
+ }
- if (XVA_ISSET_RTN(&tmp_xvattr, XAT_HIDDEN)) {
- if (xoap->xoa_hidden)
+ if ((XVA_ISSET_RTN(&tmp_xvattr, XAT_HIDDEN)) &&
+ (xoap->xoa_hidden)) {
ret_attr->sa_dosattr |= FILE_ATTRIBUTE_HIDDEN;
- }
+ }
- if (XVA_ISSET_RTN(&tmp_xvattr, XAT_SYSTEM)) {
- if (xoap->xoa_system)
+ if ((XVA_ISSET_RTN(&tmp_xvattr, XAT_SYSTEM)) &&
+ (xoap->xoa_system)) {
ret_attr->sa_dosattr |= FILE_ATTRIBUTE_SYSTEM;
- }
+ }
- if (XVA_ISSET_RTN(&tmp_xvattr, XAT_ARCHIVE)) {
- if (xoap->xoa_archive)
+ if ((XVA_ISSET_RTN(&tmp_xvattr, XAT_ARCHIVE)) &&
+ (xoap->xoa_archive)) {
ret_attr->sa_dosattr |= FILE_ATTRIBUTE_ARCHIVE;
- }
-
- ret_attr->sa_crtime = xoap->xoa_createtime;
-
- if (unnamed_vp) {
- ret_attr->sa_vattr.va_type = VREG;
-
- if (ret_attr->sa_mask & SMB_AT_SIZE) {
- tmp_xvattr.xva_vattr.va_mask = AT_SIZE;
-
- error = VOP_GETATTR(vp, &tmp_xvattr.xva_vattr,
- flags, cr, &smb_ct);
- if (error != 0)
- return (error);
-
- ret_attr->sa_vattr.va_size =
- tmp_xvattr.xva_vattr.va_size;
-
}
+
+ ret_attr->sa_crtime = xoap->xoa_createtime;
+ } else {
+ ret_attr->sa_crtime = ret_attr->sa_vattr.va_mtime;
}
+ } else {
+ /*
+ * Support for file systems without VFSFT_XVATTR
+ */
+ smb_sa_to_va_mask(ret_attr->sa_mask,
+ &ret_attr->sa_vattr.va_mask);
- if (ret_attr->sa_vattr.va_type == VDIR)
- ret_attr->sa_dosattr |= FILE_ATTRIBUTE_DIRECTORY;
+ error = VOP_GETATTR(use_vp, &ret_attr->sa_vattr,
+ flags, cr, &smb_ct);
+ if (error != 0)
+ return (error);
- return (error);
+ ret_attr->sa_dosattr = 0;
+ ret_attr->sa_crtime = ret_attr->sa_vattr.va_mtime;
}
- /*
- * Support for file systems without VFSFT_XVATTR
- */
- smb_sa_to_va_mask(ret_attr->sa_mask,
- &ret_attr->sa_vattr.va_mask);
-
- error = VOP_GETATTR(use_vp, &ret_attr->sa_vattr, flags, cr, &smb_ct);
- if (error != 0)
- return (error);
-
- ret_attr->sa_dosattr = 0;
- ret_attr->sa_crtime = ret_attr->sa_vattr.va_mtime;
-
if (unnamed_vp) {
ret_attr->sa_vattr.va_type = VREG;
@@ -676,7 +636,7 @@ smb_vop_commit(vnode_t *vp, cred_t *cr)
return (VOP_FSYNC(vp, 1, cr, &smb_ct));
}
-void
+static void
smb_vop_setup_xvattr(smb_attr_t *smb_attr, xvattr_t *xvattr)
{
xoptattr_t *xoap = NULL;
@@ -753,116 +713,27 @@ smb_vop_setup_xvattr(smb_attr_t *smb_attr, xvattr_t *xvattr)
}
}
-
/*
* smb_vop_readdir()
*
- * Upon return, the "name" field will contain either the on-disk name or, if
- * it needs mangling or has a case-insensitive collision, the mangled
- * "shortname."
- *
- * vpp is an optional parameter. If non-NULL, it will contain a pointer to
- * the vnode for the name that is looked up (the vnode will be returned held).
- *
- * od_name is an optional parameter (NULL can be passed if the on-disk name
- * is not needed by the caller).
- */
-
-int
-smb_vop_readdir(vnode_t *dvp, uint32_t *cookiep, char *name, int *namelen,
- ino64_t *inop, vnode_t **vpp, char *od_name, int flags, cred_t *cr)
-{
- int num_bytes;
- int error = 0;
- char *dirbuf = NULL;
-
- ASSERT(dvp);
- ASSERT(cookiep);
- ASSERT(name);
- ASSERT(namelen);
- ASSERT(inop);
- ASSERT(cr);
-
- if (dvp->v_type != VDIR) {
- *namelen = 0;
- return (ENOTDIR);
- }
-
- if (vpp)
- *vpp = NULL;
-
- dirbuf = kmem_zalloc(SMB_MINLEN_RDDIR_BUF, KM_SLEEP);
- num_bytes = SMB_MINLEN_RDDIR_BUF;
-
- /*
- * The goal is to retrieve the first valid entry from *cookiep
- * forward. smb_vop_readdir_readpage() collects an
- * SMB_MINLEN_RDDIR_BUF-size "page" of directory entry information.
- * smb_vop_readdir_entry() attempts to find the first valid entry
- * in that page.
- */
-
- while ((error = smb_vop_readdir_readpage(dvp, dirbuf, *cookiep,
- &num_bytes, cr)) == 0) {
-
- if (num_bytes <= 0)
- break;
-
- name[0] = '\0';
-
- error = smb_vop_readdir_entry(dvp, cookiep, name, namelen,
- inop, vpp, od_name, flags, cr, dirbuf, num_bytes);
-
- if (error)
- break;
-
- if (*name)
- break;
-
- bzero(dirbuf, SMB_MINLEN_RDDIR_BUF);
- num_bytes = SMB_MINLEN_RDDIR_BUF;
- }
-
-
- if (error) {
- kmem_free(dirbuf, SMB_MINLEN_RDDIR_BUF);
- *namelen = 0;
- return (error);
- }
-
- if (num_bytes == 0) { /* EOF */
- kmem_free(dirbuf, SMB_MINLEN_RDDIR_BUF);
- *cookiep = SMB_EOF;
- *namelen = 0;
- return (0);
- }
-
- kmem_free(dirbuf, SMB_MINLEN_RDDIR_BUF);
- return (0);
-}
-
-/*
- * smb_vop_readdir_readpage()
- *
- * Collects an SMB_MINLEN_RDDIR_BUF "page" of directory entries. (The
- * directory entries are returned in an fs-independent format by the
+ * Collects an SMB_MINLEN_RDDIR_BUF "page" of directory entries.
+ * The directory entries are returned in an fs-independent format by the
* underlying file system. That is, the "page" of information returned is
- * not literally stored on-disk in the format returned.)
- *
- * Much of the following is borrowed from getdents64()
+ * not literally stored on-disk in the format returned.
+ * If the file system supports extended directory entries (has features
+ * VFSFT_DIRENTFLAGS), set V_RDDIR_ENTFLAGS to cause the buffer to be
+ * filled with edirent_t structures, instead of dirent64_t structures.
*
- * MAXGETDENTS_SIZE is defined in getdents.c
+ * Some file systems can have directories larger than SMB_MAXDIRSIZE.
+ * After VOP_READDIR, if offset is larger than SMB_MAXDIRSIZE treat as EOF.
*/
-
-#define MAXGETDENTS_SIZE (64 * 1024)
-
-static int
-smb_vop_readdir_readpage(vnode_t *vp, void *buf, uint32_t offset, int *count,
- cred_t *cr)
+int
+smb_vop_readdir(vnode_t *vp, uint32_t offset,
+ void *buf, int *count, int *eof, cred_t *cr)
{
int error = 0;
int rdirent_flags = 0;
- int sink;
+ int rdirent_size;
struct uio auio;
struct iovec aiov;
@@ -870,22 +741,14 @@ smb_vop_readdir_readpage(vnode_t *vp, void *buf, uint32_t offset, int *count,
return (ENOTDIR);
if (vfs_has_feature(vp->v_vfsp, VFSFT_DIRENTFLAGS)) {
- /*
- * Setting V_RDDIR_ENTFLAGS will cause the buffer to
- * be filled with edirent_t structures (instead of
- * dirent64_t structures).
- */
rdirent_flags = V_RDDIR_ENTFLAGS;
-
- if (*count < sizeof (edirent_t))
- return (EINVAL);
+ rdirent_size = sizeof (edirent_t);
} else {
- if (*count < sizeof (dirent64_t))
- return (EINVAL);
+ rdirent_size = sizeof (dirent64_t);
}
- if (*count > MAXGETDENTS_SIZE)
- *count = MAXGETDENTS_SIZE;
+ if (*count < rdirent_size)
+ return (EINVAL);
aiov.iov_base = buf;
aiov.iov_len = *count;
@@ -897,183 +760,14 @@ smb_vop_readdir_readpage(vnode_t *vp, void *buf, uint32_t offset, int *count,
auio.uio_fmode = 0;
(void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, &smb_ct);
- error = VOP_READDIR(vp, &auio, cr, &sink, &smb_ct, rdirent_flags);
+ error = VOP_READDIR(vp, &auio, cr, eof, &smb_ct, rdirent_flags);
VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &smb_ct);
- if (error) {
- if (error == ENOENT) {
- /* Fake EOF if offset is bad due to dropping of lock */
- *count = 0;
- return (0);
- } else {
- return (error);
- }
- }
-
- /*
- * Windows cannot handle an offset > SMB_EOF.
- * Pretend we are at EOF.
- */
-
- if (auio.uio_loffset > SMB_EOF) {
- *count = 0;
- return (0);
- }
-
- *count = *count - auio.uio_resid;
- return (0);
-}
-
-/*
- * smb_vop_readdir_entry()
- *
- * This function retrieves the first valid entry from the
- * SMB_MINLEN_RDDIR_BUF-sized buffer returned by smb_vop_readdir_readpage()
- * to smb_vop_readdir().
- *
- * Both dirent64_t and edirent_t structures need to be handled. The former is
- * needed for file systems that do not support VFSFT_DIRENTFLAGS. The latter
- * is required for proper handling of case collisions on file systems that
- * support case-insensitivity. edirent_t structures are also used for
- * case-sensitive file systems if VFSFT_DIRENTFLAGS is supported.
- */
-
-static int
-smb_vop_readdir_entry(
- vnode_t *dvp,
- uint32_t *cookiep,
- char *name,
- int *namelen,
- ino64_t *inop,
- vnode_t **vpp,
- char *od_name,
- int flags,
- cred_t *cr,
- char *dirbuf,
- int num_bytes)
-{
- uint32_t next_cookie;
- int ebufsize;
- int error = 0;
- int len;
- int rc;
- char shortname[SMB_SHORTNAMELEN];
- char name83[SMB_SHORTNAMELEN];
- char *ebuf = NULL;
- edirent_t *edp;
- dirent64_t *dp = NULL;
- vnode_t *vp = NULL;
-
- ASSERT(dirbuf);
-
- /*
- * Use edirent_t structure for both
- */
- if (vfs_has_feature(dvp->v_vfsp, VFSFT_DIRENTFLAGS)) {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- edp = (edirent_t *)dirbuf;
- } else {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- dp = (dirent64_t *)dirbuf;
- ebufsize = EDIRENT_RECLEN(MAXNAMELEN);
- ebuf = kmem_zalloc(ebufsize, KM_SLEEP);
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- edp = (edirent_t *)ebuf;
- }
-
- while (edp) {
- if (dp)
- DP_TO_EDP(dp, edp);
-
- next_cookie = (uint32_t)edp->ed_off;
- if (edp->ed_ino == 0) {
- *cookiep = next_cookie;
-
- if (dp) {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- DP_ADVANCE(dp, dirbuf, num_bytes);
- if (dp == NULL)
- edp = NULL;
- } else {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- EDP_ADVANCE(edp, dirbuf, num_bytes);
- }
- continue;
- }
-
- len = strlen(edp->ed_name);
-
- if (*namelen < len) {
- *namelen = 0;
+ if (auio.uio_loffset > SMB_MAXDIRSIZE)
+ *eof = 1;
- if (ebuf)
- kmem_free(ebuf, ebufsize);
-
- return (EOVERFLOW);
- }
-
- /*
- * Do not pass SMB_IGNORE_CASE to smb_vop_lookup
- */
-
- error = smb_vop_lookup(dvp, edp->ed_name, vpp ? vpp : &vp,
- od_name, 0, NULL, cr);
-
- if (error) {
- if (error == ENOENT) {
- *cookiep = (uint32_t)next_cookie;
-
- if (dp) {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- DP_ADVANCE(dp, dirbuf, num_bytes);
- if (dp == NULL)
- edp = NULL;
- } else {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- EDP_ADVANCE(edp, dirbuf, num_bytes);
- }
- continue;
- }
-
-
- *namelen = 0;
-
- if (ebuf)
- kmem_free(ebuf, ebufsize);
-
- return (error);
- }
-
- if ((flags & SMB_IGNORE_CASE) && ED_CASE_CONFLICTS(edp)) {
- rc = smb_mangle_name(edp->ed_ino, edp->ed_name,
- shortname, name83, 1);
-
- if (rc == 1) { /* success */
- (void) strlcpy(name, shortname, *namelen + 1);
- *namelen = strlen(shortname);
- } else {
- (void) strlcpy(name, edp->ed_name,
- *namelen + 1);
- name[*namelen] = '\0';
- }
-
- } else {
- (void) strlcpy(name, edp->ed_name, *namelen + 1);
- *namelen = len;
- }
-
- if (vpp == NULL)
- VN_RELE(vp);
-
- if (inop)
- *inop = edp->ed_ino;
-
- *cookiep = (uint32_t)next_cookie;
- break;
- }
-
- if (ebuf)
- kmem_free(ebuf, ebufsize);
+ if (error == 0)
+ *count = *count - auio.uio_resid;
return (error);
}
@@ -1102,266 +796,6 @@ smb_sa_to_va_mask(uint_t sa_mask, uint_t *va_maskp)
}
/*
- * smb_vop_getdents()
- *
- * Upon success, the smb_node corresponding to each entry returned will
- * have a reference taken on it. These will be released in
- * smb_trans2_find_get_dents().
- *
- * If an error is returned from this routine, a list of already processed
- * entries will be returned. The smb_nodes corresponding to these entries
- * will be referenced, and will be released in smb_trans2_find_get_dents().
- *
- * The returned dp->d_name field will contain either the on-disk name or, if
- * it needs mangling or has a case-insensitive collision, the mangled
- * "shortname." In this case, the on-disk name can be retrieved from the
- * smb_node's od_name (the smb_node is passed to smb_gather_dents_info()).
- */
-
-int /*ARGSUSED*/
-smb_vop_getdents(
- smb_node_t *dir_snode,
- uint32_t *cookiep,
- uint64_t *verifierp,
- int32_t *dircountp,
- char *arg,
- char *pattern,
- uint32_t flags,
- smb_request_t *sr,
- cred_t *cr)
-{
- int error = 0;
- int maxentries;
- int num_bytes;
- int resid;
- char *dirbuf = NULL;
- vnode_t *dvp;
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- smb_dent_info_hdr_t *ihdr = (smb_dent_info_hdr_t *)arg;
-
- dvp = dir_snode->vp;
-
- resid = ihdr->uio.uio_resid;
- maxentries = resid / SMB_MAX_DENT_INFO_SIZE;
-
- bzero(ihdr->iov->iov_base, resid);
-
- dirbuf = kmem_alloc(SMB_MINLEN_RDDIR_BUF, KM_SLEEP);
-
- while (maxentries) {
-
- bzero(dirbuf, SMB_MINLEN_RDDIR_BUF);
-
- num_bytes = SMB_MINLEN_RDDIR_BUF;
- error = smb_vop_readdir_readpage(dvp, dirbuf, *cookiep,
- &num_bytes, cr);
-
- if (error || (num_bytes <= 0))
- break;
-
- error = smb_vop_getdents_entries(dir_snode, cookiep, dircountp,
- arg, flags, sr, cr, dirbuf, &maxentries, num_bytes,
- pattern);
-
- if (error)
- goto out;
- }
-
- if (num_bytes < 0) {
- error = -1;
- } else if (num_bytes == 0) {
- *cookiep = SMB_EOF;
- error = 0;
- } else {
- error = 0;
- }
-
-out:
- if (dirbuf)
- kmem_free(dirbuf, SMB_MINLEN_RDDIR_BUF);
-
- return (error);
-}
-
-/*
- * smb_vop_getdents_entries()
- *
- * This function retrieves names from the SMB_MINLEN_RDDIR_BUF-sized buffer
- * returned by smb_vop_readdir_readpage() to smb_vop_getdents().
- *
- * Both dirent64_t and edirent_t structures need to be handled. The former is
- * needed for file systems that do not support VFSFT_DIRENTFLAGS. The latter
- * is required for properly handling case collisions on file systems that
- * support case-insensitivity. edirent_t is also used on case-sensitive
- * file systems where VFSFT_DIRENTFLAGS is available.
- */
-
-static int
-smb_vop_getdents_entries(
- smb_node_t *dir_snode,
- uint32_t *cookiep,
- int32_t *dircountp,
- char *arg,
- uint32_t flags,
- smb_request_t *sr,
- cred_t *cr,
- char *dirbuf,
- int *maxentries,
- int num_bytes,
- char *pattern)
-{
- uint32_t next_cookie;
- int ebufsize;
- char *tmp_name;
- int rc;
- char shortname[SMB_SHORTNAMELEN];
- char name83[SMB_SHORTNAMELEN];
- char *ebuf = NULL;
- dirent64_t *dp = NULL;
- edirent_t *edp;
- smb_node_t *ret_snode;
- smb_attr_t ret_attr;
- vnode_t *dvp;
- vnode_t *fvp;
-
- ASSERT(dirbuf);
-
- dvp = dir_snode->vp;
-
- if (vfs_has_feature(dvp->v_vfsp, VFSFT_DIRENTFLAGS)) {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- edp = (edirent_t *)dirbuf;
- } else {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- dp = (dirent64_t *)dirbuf;
- ebufsize = EDIRENT_RECLEN(MAXNAMELEN);
- ebuf = kmem_zalloc(ebufsize, KM_SLEEP);
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- edp = (edirent_t *)ebuf;
- }
-
- while (edp) {
- if (dp)
- DP_TO_EDP(dp, edp);
-
- if (*maxentries == 0)
- break;
-
- next_cookie = (uint32_t)edp->ed_off;
-
- if (edp->ed_ino == 0) {
- *cookiep = next_cookie;
- if (dp) {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- DP_ADVANCE(dp, dirbuf, num_bytes);
- if (dp == NULL)
- edp = NULL;
- } else {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- EDP_ADVANCE(edp, dirbuf, num_bytes);
- }
- continue;
- }
-
- rc = smb_vop_lookup(dvp, edp->ed_name, &fvp,
- NULL, 0, NULL, cr);
-
- if (rc) {
- if (rc == ENOENT) {
- *cookiep = next_cookie;
- if (dp) {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- DP_ADVANCE(dp, dirbuf,
- num_bytes);
- if (dp == NULL)
- edp = NULL;
- } else {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- EDP_ADVANCE(edp, dirbuf,
- num_bytes);
- }
- continue;
- }
- if (ebuf)
- kmem_free(ebuf, ebufsize);
-
- return (rc);
- }
-
- ret_snode = smb_node_lookup(sr, NULL, cr, fvp,
- edp->ed_name, dir_snode, NULL, &ret_attr);
-
- if (ret_snode == NULL) {
- VN_RELE(fvp);
-
- if (ebuf)
- kmem_free(ebuf, ebufsize);
-
- return (ENOMEM);
- }
-
- if (smb_match_name(edp->ed_ino, edp->ed_name, shortname,
- name83, pattern, (flags & SMB_IGNORE_CASE))) {
-
- tmp_name = edp->ed_name;
-
- if ((flags & SMB_IGNORE_CASE) &&
- ED_CASE_CONFLICTS(edp)) {
- rc = smb_mangle_name(edp->ed_ino, edp->ed_name,
- shortname, name83, 1);
- if (rc == 1)
- tmp_name = shortname;
- } else {
- rc = smb_mangle_name(edp->ed_ino, edp->ed_name,
- shortname, name83, 0);
- }
-
- if (rc != 1) {
- (void) strlcpy(shortname, edp->ed_name,
- SMB_SHORTNAMELEN);
- (void) strlcpy(name83, edp->ed_name,
- SMB_SHORTNAMELEN);
- shortname[SMB_SHORTNAMELEN - 1] = '\0';
- name83[SMB_SHORTNAMELEN - 1] = '\0';
- }
-
- rc = smb_gather_dents_info(arg, edp->ed_ino,
- strlen(tmp_name), tmp_name, next_cookie, dircountp,
- &ret_attr, ret_snode, shortname, name83);
-
- if (rc < 0) {
- if (ebuf)
- kmem_free(ebuf, ebufsize);
- *maxentries = 0;
- return (0);
- }
-
- if (rc > 0)
- (*maxentries)--;
- } else {
- smb_node_release(ret_snode);
- }
-
- *cookiep = next_cookie;
-
- if (dp) {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- DP_ADVANCE(dp, dirbuf, num_bytes);
- if (dp == NULL)
- edp = NULL;
- } else {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- EDP_ADVANCE(edp, dirbuf, num_bytes);
- }
- }
-
- if (ebuf)
- kmem_free(ebuf, ebufsize);
-
- return (0);
-}
-
-/*
* smb_vop_stream_lookup()
*
* The name returned in od_name is the on-disk name of the stream with the
@@ -1472,80 +906,6 @@ smb_vop_stream_remove(vnode_t *vp, char *stream_name, int flags, cred_t *cr)
return (error);
}
-/*
- * smb_vop_stream_readdir()
- *
- * Note: stream_info.size is not filled in in this routine.
- * It needs to be filled in by the caller due to the parameters for getattr.
- *
- * stream_info.name is set to the on-disk stream name with the SMB_STREAM_PREFIX
- * removed.
- */
-
-int
-smb_vop_stream_readdir(vnode_t *fvp, uint32_t *cookiep,
- struct fs_stream_info *stream_info, vnode_t **vpp, vnode_t **xattrdirvpp,
- int flags, cred_t *cr)
-{
- int nsize;
- int error = 0;
- ino64_t ino;
- char *tmp_name;
- vnode_t *xattrdirvp;
- vnode_t *vp;
-
- if ((error = smb_vop_lookup_xattrdir(fvp, &xattrdirvp, LOOKUP_XATTR,
- cr)) != 0)
- return (error);
-
- bzero(stream_info->name, sizeof (stream_info->name));
- stream_info->size = 0;
-
- tmp_name = kmem_zalloc(MAXNAMELEN, KM_SLEEP);
-
- for (;;) {
- nsize = MAXNAMELEN-1;
- error = smb_vop_readdir(xattrdirvp, cookiep, tmp_name, &nsize,
- &ino, &vp, NULL, flags, cr);
-
- if (error || (*cookiep == SMB_EOF))
- break;
-
- if (strncmp(tmp_name, SMB_STREAM_PREFIX,
- SMB_STREAM_PREFIX_LEN)) {
- VN_RELE(vp);
- continue;
- }
-
- tmp_name[nsize] = '\0';
- (void) strlcpy(stream_info->name,
- &(tmp_name[SMB_STREAM_PREFIX_LEN]),
- sizeof (stream_info->name));
-
- nsize -= SMB_STREAM_PREFIX_LEN;
- break;
- }
-
- if ((error == 0) && nsize) {
- if (vpp)
- *vpp = vp;
- else
- VN_RELE(vp);
-
- if (xattrdirvpp)
- *xattrdirvpp = xattrdirvp;
- else
- VN_RELE(xattrdirvp);
-
- } else {
- VN_RELE(xattrdirvp);
- }
-
- kmem_free(tmp_name, MAXNAMELEN);
-
- return (error);
-}
-
int
smb_vop_lookup_xattrdir(vnode_t *fvp, vnode_t **xattrdirvpp, int flags,
cred_t *cr)