191d632c8Sgwr /* 291d632c8Sgwr * CDDL HEADER START 391d632c8Sgwr * 491d632c8Sgwr * The contents of this file are subject to the terms of the 591d632c8Sgwr * Common Development and Distribution License (the "License"). 691d632c8Sgwr * You may not use this file except in compliance with the License. 791d632c8Sgwr * 891d632c8Sgwr * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 991d632c8Sgwr * or http://www.opensolaris.org/os/licensing. 1091d632c8Sgwr * See the License for the specific language governing permissions 1191d632c8Sgwr * and limitations under the License. 1291d632c8Sgwr * 1391d632c8Sgwr * When distributing Covered Code, include this CDDL HEADER in each 1491d632c8Sgwr * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1591d632c8Sgwr * If applicable, add the following below this CDDL HEADER, with the 1691d632c8Sgwr * fields enclosed by brackets "[]" replaced with your own identifying 1791d632c8Sgwr * information: Portions Copyright [yyyy] [name of copyright owner] 1891d632c8Sgwr * 1991d632c8Sgwr * CDDL HEADER END 2091d632c8Sgwr */ 2191d632c8Sgwr 2291d632c8Sgwr /* 23*148c5f43SAlan Wright * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 2491d632c8Sgwr */ 2591d632c8Sgwr 2691d632c8Sgwr /* 2791d632c8Sgwr * Functions supporting Solaris Extended Attributes, 2891d632c8Sgwr * used to provide access to CIFS "named streams". 2991d632c8Sgwr */ 3091d632c8Sgwr 3191d632c8Sgwr #include <sys/systm.h> 3291d632c8Sgwr #include <sys/cred.h> 3391d632c8Sgwr #include <sys/vnode.h> 3491d632c8Sgwr #include <sys/vfs.h> 3591d632c8Sgwr #include <sys/filio.h> 3691d632c8Sgwr #include <sys/uio.h> 3791d632c8Sgwr #include <sys/dirent.h> 3891d632c8Sgwr #include <sys/errno.h> 3991d632c8Sgwr #include <sys/sysmacros.h> 4091d632c8Sgwr #include <sys/kmem.h> 4191d632c8Sgwr #include <sys/stat.h> 4291d632c8Sgwr #include <sys/cmn_err.h> 4391d632c8Sgwr #include <sys/u8_textprep.h> 4491d632c8Sgwr 4591d632c8Sgwr #include <netsmb/smb_osdep.h> 4691d632c8Sgwr #include <netsmb/smb.h> 4791d632c8Sgwr #include <netsmb/smb_conn.h> 4891d632c8Sgwr #include <netsmb/smb_subr.h> 4991d632c8Sgwr #include <netsmb/smb_rq.h> 5091d632c8Sgwr 5191d632c8Sgwr #include <smbfs/smbfs.h> 5291d632c8Sgwr #include <smbfs/smbfs_node.h> 5391d632c8Sgwr #include <smbfs/smbfs_subr.h> 5491d632c8Sgwr 5591d632c8Sgwr #include <fs/fs_subr.h> 5691d632c8Sgwr 5791d632c8Sgwr /* 5891d632c8Sgwr * Solaris wants there to be a directory node to contain 5991d632c8Sgwr * all the extended attributes. The SMB protocol does not 6091d632c8Sgwr * really support a directory here, and uses very different 6191d632c8Sgwr * operations to list attributes, etc. so we "fake up" an 6291d632c8Sgwr * smbnode here to represent the attributes directory. 6391d632c8Sgwr * 6491d632c8Sgwr * We need to give this (fake) directory a unique identity, 6591d632c8Sgwr * and since we're using the full remote pathname as the 6691d632c8Sgwr * unique identity of all nodes, the easiest thing to do 6791d632c8Sgwr * here is append a colon (:) to the given pathname. 6891d632c8Sgwr * 6991d632c8Sgwr * There are several places where smbfs_fullpath and its 7091d632c8Sgwr * callers must decide what separator to use when building 7191d632c8Sgwr * a remote path name, and the rule is now as follows: 7291d632c8Sgwr * 1: When no XATTR involved, use "\\" as the separator. 7391d632c8Sgwr * 2: Traversal into the (fake) XATTR dir adds one ":" 7491d632c8Sgwr * 3: Children of the XATTR dir add nothing (sep=0) 7591d632c8Sgwr * The result should be _one_ colon before the attr name. 7691d632c8Sgwr */ 7791d632c8Sgwr 7891d632c8Sgwr /* ARGSUSED */ 7991d632c8Sgwr int 8091d632c8Sgwr smbfs_get_xattrdir(vnode_t *pvp, vnode_t **vpp, cred_t *cr, int flags) 8191d632c8Sgwr { 8291d632c8Sgwr vnode_t *xvp; 8391d632c8Sgwr smbnode_t *pnp, *xnp; 8491d632c8Sgwr 8591d632c8Sgwr pnp = VTOSMB(pvp); 8691d632c8Sgwr 8702d09e03SGordon Ross /* 8802d09e03SGordon Ross * We don't allow recursive extended attributes 8902d09e03SGordon Ross * (xattr under xattr dir.) so the "parent" node 9002d09e03SGordon Ross * (pnp) must NOT be an XATTR directory or file. 9102d09e03SGordon Ross */ 9202d09e03SGordon Ross if (pnp->n_flag & N_XATTR) 9302d09e03SGordon Ross return (EINVAL); 9402d09e03SGordon Ross 9502d09e03SGordon Ross xnp = smbfs_node_findcreate(pnp->n_mount, 9602d09e03SGordon Ross pnp->n_rpath, pnp->n_rplen, NULL, 0, ':', 9702d09e03SGordon Ross &smbfs_fattr0); /* force create */ 9802d09e03SGordon Ross ASSERT(xnp != NULL); 9902d09e03SGordon Ross xvp = SMBTOV(xnp); 10091d632c8Sgwr /* Note: xvp has a VN_HOLD, which our caller expects. */ 10191d632c8Sgwr 10291d632c8Sgwr /* If it's a new node, initialize. */ 10391d632c8Sgwr if (xvp->v_type == VNON) { 10491d632c8Sgwr 10591d632c8Sgwr mutex_enter(&xvp->v_lock); 10691d632c8Sgwr xvp->v_type = VDIR; 10791d632c8Sgwr xvp->v_flag |= V_XATTRDIR; 10891d632c8Sgwr mutex_exit(&xvp->v_lock); 10991d632c8Sgwr 11091d632c8Sgwr mutex_enter(&xnp->r_statelock); 11191d632c8Sgwr xnp->n_flag |= N_XATTR; 11291d632c8Sgwr mutex_exit(&xnp->r_statelock); 11391d632c8Sgwr } 11491d632c8Sgwr 11591d632c8Sgwr /* Success! */ 11691d632c8Sgwr *vpp = xvp; 11791d632c8Sgwr return (0); 11891d632c8Sgwr } 11991d632c8Sgwr 12091d632c8Sgwr /* 12191d632c8Sgwr * Find the parent of an XATTR directory or file, 12291d632c8Sgwr * by trimming off the ":attrname" part of rpath. 12391d632c8Sgwr * Called on XATTR files to get the XATTR dir, and 12491d632c8Sgwr * called on the XATTR dir to get the real object 12591d632c8Sgwr * under which the (faked up) XATTR dir lives. 12691d632c8Sgwr */ 12791d632c8Sgwr int 12891d632c8Sgwr smbfs_xa_parent(vnode_t *vp, vnode_t **vpp) 12991d632c8Sgwr { 13091d632c8Sgwr smbnode_t *np = VTOSMB(vp); 13102d09e03SGordon Ross smbnode_t *pnp; 13291d632c8Sgwr int rplen; 13391d632c8Sgwr 13402d09e03SGordon Ross *vpp = NULL; 13502d09e03SGordon Ross 13691d632c8Sgwr if ((np->n_flag & N_XATTR) == 0) 13791d632c8Sgwr return (EINVAL); 13891d632c8Sgwr 13991d632c8Sgwr if (vp->v_flag & V_XATTRDIR) { 14091d632c8Sgwr /* 14191d632c8Sgwr * Want the parent of the XATTR directory. 14291d632c8Sgwr * That's easy: just remove trailing ":" 14391d632c8Sgwr */ 14491d632c8Sgwr rplen = np->n_rplen - 1; 14591d632c8Sgwr if (rplen < 1) { 14691d632c8Sgwr SMBVDEBUG("rplen < 1?"); 14791d632c8Sgwr return (ENOENT); 14891d632c8Sgwr } 14991d632c8Sgwr if (np->n_rpath[rplen] != ':') { 15091d632c8Sgwr SMBVDEBUG("last is not colon"); 15191d632c8Sgwr return (ENOENT); 15291d632c8Sgwr } 15391d632c8Sgwr } else { 15491d632c8Sgwr /* 15591d632c8Sgwr * Want the XATTR directory given 15691d632c8Sgwr * one of its XATTR files (children). 15791d632c8Sgwr * Find the ":" and trim after it. 15891d632c8Sgwr */ 15991d632c8Sgwr for (rplen = 1; rplen < np->n_rplen; rplen++) 16091d632c8Sgwr if (np->n_rpath[rplen] == ':') 16191d632c8Sgwr break; 16291d632c8Sgwr /* Should have found ":stream_name" */ 16391d632c8Sgwr if (rplen >= np->n_rplen) { 16491d632c8Sgwr SMBVDEBUG("colon not found"); 16591d632c8Sgwr return (ENOENT); 16691d632c8Sgwr } 16791d632c8Sgwr rplen++; /* keep the ":" */ 16891d632c8Sgwr if (rplen >= np->n_rplen) { 16991d632c8Sgwr SMBVDEBUG("no stream name"); 17091d632c8Sgwr return (ENOENT); 17191d632c8Sgwr } 17291d632c8Sgwr } 17391d632c8Sgwr 17402d09e03SGordon Ross pnp = smbfs_node_findcreate(np->n_mount, 17502d09e03SGordon Ross np->n_rpath, rplen, NULL, 0, 0, 17602d09e03SGordon Ross &smbfs_fattr0); /* force create */ 17702d09e03SGordon Ross ASSERT(pnp != NULL); 17802d09e03SGordon Ross /* Note: have VN_HOLD from smbfs_node_findcreate */ 17902d09e03SGordon Ross *vpp = SMBTOV(pnp); 18091d632c8Sgwr return (0); 18191d632c8Sgwr } 18291d632c8Sgwr 18391d632c8Sgwr /* 18491d632c8Sgwr * This is called by smbfs_pathconf to find out 18591d632c8Sgwr * if some file has any extended attributes. 18691d632c8Sgwr * There's no short-cut way to find out, so we 18791d632c8Sgwr * just list the attributes the usual way and 18891d632c8Sgwr * check for an empty result. 18991d632c8Sgwr * 19091d632c8Sgwr * Returns 1: (exists) or 0: (none found) 19191d632c8Sgwr */ 19291d632c8Sgwr int 19391d632c8Sgwr smbfs_xa_exists(vnode_t *vp, cred_t *cr) 19491d632c8Sgwr { 19591d632c8Sgwr smbnode_t *xnp; 19691d632c8Sgwr vnode_t *xvp; 19791d632c8Sgwr struct smb_cred scred; 19891d632c8Sgwr struct smbfs_fctx ctx; 19991d632c8Sgwr int error, rc = 0; 20091d632c8Sgwr 20191d632c8Sgwr /* Get the xattr dir */ 20291d632c8Sgwr error = smbfs_get_xattrdir(vp, &xvp, cr, LOOKUP_XATTR); 20391d632c8Sgwr if (error) 20491d632c8Sgwr return (0); 20591d632c8Sgwr /* NB: have VN_HOLD on xpv */ 20691d632c8Sgwr xnp = VTOSMB(xvp); 20791d632c8Sgwr 208613a2f6bSGordon Ross smb_credinit(&scred, cr); 20991d632c8Sgwr 21091d632c8Sgwr bzero(&ctx, sizeof (ctx)); 21191d632c8Sgwr ctx.f_flags = SMBFS_RDD_FINDFIRST; 21291d632c8Sgwr ctx.f_dnp = xnp; 21391d632c8Sgwr ctx.f_scred = &scred; 21491d632c8Sgwr ctx.f_ssp = xnp->n_mount->smi_share; 21591d632c8Sgwr 21691d632c8Sgwr error = smbfs_xa_findopen(&ctx, xnp, "*", 1); 21791d632c8Sgwr if (error) 21891d632c8Sgwr goto out; 21991d632c8Sgwr 22091d632c8Sgwr error = smbfs_xa_findnext(&ctx, 1); 22191d632c8Sgwr if (error) 22291d632c8Sgwr goto out; 22391d632c8Sgwr 22491d632c8Sgwr /* Have at least one named stream. */ 22591d632c8Sgwr SMBVDEBUG("ctx.f_name: %s\n", ctx.f_name); 22691d632c8Sgwr rc = 1; 22791d632c8Sgwr 22891d632c8Sgwr out: 22991d632c8Sgwr /* NB: Always call findclose, error or not. */ 23091d632c8Sgwr (void) smbfs_xa_findclose(&ctx); 23191d632c8Sgwr smb_credrele(&scred); 23291d632c8Sgwr VN_RELE(xvp); 23391d632c8Sgwr return (rc); 23491d632c8Sgwr } 23591d632c8Sgwr 23691d632c8Sgwr 23791d632c8Sgwr /* 23891d632c8Sgwr * This is called to get attributes (size, etc.) of either 23991d632c8Sgwr * the "faked up" XATTR directory or a named stream. 24091d632c8Sgwr */ 24191d632c8Sgwr int 24291d632c8Sgwr smbfs_xa_getfattr(struct smbnode *xnp, struct smbfattr *fap, 24391d632c8Sgwr struct smb_cred *scrp) 24491d632c8Sgwr { 24591d632c8Sgwr vnode_t *xvp; /* xattr */ 24691d632c8Sgwr vnode_t *pvp; /* parent */ 24791d632c8Sgwr smbnode_t *pnp; /* parent */ 24891d632c8Sgwr int error, nlen; 24991d632c8Sgwr const char *name, *sname; 25091d632c8Sgwr 25191d632c8Sgwr xvp = SMBTOV(xnp); 25291d632c8Sgwr 25391d632c8Sgwr /* 25491d632c8Sgwr * Simulate smbfs_smb_getfattr() for a named stream. 25591d632c8Sgwr * OK to leave a,c,m times zero (expected w/ XATTR). 25691d632c8Sgwr * The XATTR directory is easy (all fake). 25791d632c8Sgwr */ 25891d632c8Sgwr if (xvp->v_flag & V_XATTRDIR) { 25991d632c8Sgwr fap->fa_attr = SMB_FA_DIR; 26091d632c8Sgwr fap->fa_size = DEV_BSIZE; 26191d632c8Sgwr return (0); 26291d632c8Sgwr } 26391d632c8Sgwr 26491d632c8Sgwr /* 26591d632c8Sgwr * Do a lookup in the XATTR directory, 26691d632c8Sgwr * using the stream name (last part) 26791d632c8Sgwr * from the xattr node. 26891d632c8Sgwr */ 26991d632c8Sgwr error = smbfs_xa_parent(xvp, &pvp); 27091d632c8Sgwr if (error) 27191d632c8Sgwr return (error); 27291d632c8Sgwr /* Note: pvp has a VN_HOLD */ 27391d632c8Sgwr pnp = VTOSMB(pvp); 27491d632c8Sgwr 27591d632c8Sgwr /* Get stream name (ptr and length) */ 27691d632c8Sgwr ASSERT(xnp->n_rplen > pnp->n_rplen); 27791d632c8Sgwr nlen = xnp->n_rplen - pnp->n_rplen; 27891d632c8Sgwr name = xnp->n_rpath + pnp->n_rplen; 27991d632c8Sgwr sname = name; 28091d632c8Sgwr 28191d632c8Sgwr /* Note: this can allocate a new "name" */ 28291d632c8Sgwr error = smbfs_smb_lookup(pnp, &name, &nlen, fap, scrp); 28391d632c8Sgwr if (error == 0 && name != sname) 28491d632c8Sgwr smbfs_name_free(name, nlen); 28591d632c8Sgwr 28691d632c8Sgwr VN_RELE(pvp); 28791d632c8Sgwr 28891d632c8Sgwr return (error); 28991d632c8Sgwr } 29091d632c8Sgwr 29191d632c8Sgwr /* 29291d632c8Sgwr * Fetch the entire attribute list here in findopen. 29391d632c8Sgwr * Will parse the results in findnext. 29491d632c8Sgwr * 29591d632c8Sgwr * This is called on the XATTR directory, so we 29691d632c8Sgwr * have to get the (real) parent object first. 29791d632c8Sgwr */ 29891d632c8Sgwr /* ARGSUSED */ 29991d632c8Sgwr int 30091d632c8Sgwr smbfs_xa_findopen(struct smbfs_fctx *ctx, struct smbnode *dnp, 30191d632c8Sgwr const char *wildcard, int wclen) 30291d632c8Sgwr { 30391d632c8Sgwr vnode_t *pvp; /* parent */ 30491d632c8Sgwr smbnode_t *pnp; 30591d632c8Sgwr struct smb_t2rq *t2p; 30691d632c8Sgwr struct smb_vc *vcp = SSTOVC(ctx->f_ssp); 30791d632c8Sgwr struct mbchain *mbp; 30891d632c8Sgwr int error; 30991d632c8Sgwr 31091d632c8Sgwr ASSERT(dnp->n_flag & N_XATTR); 31191d632c8Sgwr 31291d632c8Sgwr ctx->f_type = ft_XA; 313613a2f6bSGordon Ross ctx->f_namesz = SMB_MAXFNAMELEN + 1; 314613a2f6bSGordon Ross if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp))) 315613a2f6bSGordon Ross ctx->f_namesz *= 2; 316613a2f6bSGordon Ross ctx->f_name = kmem_alloc(ctx->f_namesz, KM_SLEEP); 31791d632c8Sgwr 31891d632c8Sgwr error = smbfs_xa_parent(SMBTOV(dnp), &pvp); 31991d632c8Sgwr if (error) 32091d632c8Sgwr return (error); 32191d632c8Sgwr ASSERT(pvp); 32291d632c8Sgwr /* Note: pvp has a VN_HOLD */ 32391d632c8Sgwr pnp = VTOSMB(pvp); 32491d632c8Sgwr 32591d632c8Sgwr if (ctx->f_t2) { 32691d632c8Sgwr smb_t2_done(ctx->f_t2); 32791d632c8Sgwr ctx->f_t2 = NULL; 32891d632c8Sgwr } 32991d632c8Sgwr 33091d632c8Sgwr error = smb_t2_alloc(SSTOCP(ctx->f_ssp), 33191d632c8Sgwr SMB_TRANS2_QUERY_PATH_INFORMATION, 33291d632c8Sgwr ctx->f_scred, &t2p); 33391d632c8Sgwr if (error) 33491d632c8Sgwr goto out; 33591d632c8Sgwr ctx->f_t2 = t2p; 33691d632c8Sgwr 33791d632c8Sgwr mbp = &t2p->t2_tparam; 338c1374a13SSurya Prakki (void) mb_init(mbp); 339c1374a13SSurya Prakki (void) mb_put_uint16le(mbp, SMB_QFILEINFO_STREAM_INFO); 340c1374a13SSurya Prakki (void) mb_put_uint32le(mbp, 0); 34191d632c8Sgwr error = smbfs_fullpath(mbp, vcp, pnp, NULL, NULL, 0); 34291d632c8Sgwr if (error) 34391d632c8Sgwr goto out; 34491d632c8Sgwr t2p->t2_maxpcount = 2; 34591d632c8Sgwr t2p->t2_maxdcount = INT16_MAX; 34691d632c8Sgwr error = smb_t2_request(t2p); 34791d632c8Sgwr if (error) { 348*148c5f43SAlan Wright if (t2p->t2_sr_error == NT_STATUS_INVALID_PARAMETER) 34991d632c8Sgwr error = ENOTSUP; 35091d632c8Sgwr } 35191d632c8Sgwr /* 35291d632c8Sgwr * No returned parameters to parse. 35391d632c8Sgwr * Returned data are in t2_rdata, 35491d632c8Sgwr * which we'll parse in _findnext. 35591d632c8Sgwr * However, save the wildcard. 35691d632c8Sgwr */ 35791d632c8Sgwr ctx->f_wildcard = wildcard; 35891d632c8Sgwr ctx->f_wclen = wclen; 35991d632c8Sgwr 36091d632c8Sgwr out: 36191d632c8Sgwr VN_RELE(pvp); 36291d632c8Sgwr return (error); 36391d632c8Sgwr } 36491d632c8Sgwr 36591d632c8Sgwr /* 36691d632c8Sgwr * Get the next name in an XATTR directory into f_name 36791d632c8Sgwr */ 36891d632c8Sgwr /* ARGSUSED */ 36991d632c8Sgwr int 37091d632c8Sgwr smbfs_xa_findnext(struct smbfs_fctx *ctx, uint16_t limit) 37191d632c8Sgwr { 37291d632c8Sgwr struct mdchain *mdp; 37391d632c8Sgwr struct smb_t2rq *t2p; 37491d632c8Sgwr uint32_t size, next; 37591d632c8Sgwr uint64_t llongint; 37691d632c8Sgwr int error, skip, used, nmlen; 37791d632c8Sgwr 37891d632c8Sgwr t2p = ctx->f_t2; 37991d632c8Sgwr mdp = &t2p->t2_rdata; 38091d632c8Sgwr 38191d632c8Sgwr if (ctx->f_flags & SMBFS_RDD_FINDSINGLE) { 38291d632c8Sgwr ASSERT(ctx->f_wildcard); 38391d632c8Sgwr SMBVDEBUG("wildcard: %s\n", ctx->f_wildcard); 38491d632c8Sgwr } 38591d632c8Sgwr 38691d632c8Sgwr again: 38791d632c8Sgwr if (ctx->f_flags & SMBFS_RDD_EOF) 38891d632c8Sgwr return (ENOENT); 38991d632c8Sgwr 39091d632c8Sgwr /* Parse FILE_STREAM_INFORMATION */ 39191d632c8Sgwr if ((error = md_get_uint32le(mdp, &next)) != 0) /* offset to */ 39291d632c8Sgwr return (ENOENT); 39391d632c8Sgwr if ((error = md_get_uint32le(mdp, &size)) != 0) /* name len */ 39491d632c8Sgwr return (ENOENT); 395c1374a13SSurya Prakki (void) md_get_uint64le(mdp, &llongint); /* file size */ 39691d632c8Sgwr ctx->f_attr.fa_size = llongint; 397c1374a13SSurya Prakki (void) md_get_uint64le(mdp, NULL); /* alloc. size */ 39891d632c8Sgwr used = 4 + 4 + 8 + 8; /* how much we consumed */ 39991d632c8Sgwr 40091d632c8Sgwr /* 40191d632c8Sgwr * Copy the string, but skip the first char (":") 40291d632c8Sgwr * Watch out for zero-length strings here. 40391d632c8Sgwr */ 40491d632c8Sgwr if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp))) { 40591d632c8Sgwr if (size >= 2) { 40691d632c8Sgwr size -= 2; used += 2; 407c1374a13SSurya Prakki (void) md_get_uint16le(mdp, NULL); 40891d632c8Sgwr } 40991d632c8Sgwr nmlen = min(size, SMB_MAXFNAMELEN * 2); 41091d632c8Sgwr } else { 41191d632c8Sgwr if (size >= 1) { 41291d632c8Sgwr size -= 1; used += 1; 413c1374a13SSurya Prakki (void) md_get_uint8(mdp, NULL); 41491d632c8Sgwr } 41591d632c8Sgwr nmlen = min(size, SMB_MAXFNAMELEN); 41691d632c8Sgwr } 41791d632c8Sgwr 418613a2f6bSGordon Ross ASSERT(nmlen < ctx->f_namesz); 41991d632c8Sgwr ctx->f_nmlen = nmlen; 42091d632c8Sgwr error = md_get_mem(mdp, ctx->f_name, nmlen, MB_MSYSTEM); 42191d632c8Sgwr if (error) 42291d632c8Sgwr return (error); 42391d632c8Sgwr used += nmlen; 42491d632c8Sgwr 42591d632c8Sgwr /* 42691d632c8Sgwr * Convert UCS-2 to UTF-8 42791d632c8Sgwr */ 42891d632c8Sgwr smbfs_fname_tolocal(ctx); 42991d632c8Sgwr if (nmlen) 43091d632c8Sgwr SMBVDEBUG("name: %s\n", ctx->f_name); 43191d632c8Sgwr else 43291d632c8Sgwr SMBVDEBUG("null name!\n"); 43391d632c8Sgwr 43491d632c8Sgwr /* 43591d632c8Sgwr * Skip padding until next offset 43691d632c8Sgwr */ 43791d632c8Sgwr if (next > used) { 43891d632c8Sgwr skip = next - used; 439c1374a13SSurya Prakki (void) md_get_mem(mdp, NULL, skip, MB_MSYSTEM); 44091d632c8Sgwr } 44191d632c8Sgwr if (next == 0) 44291d632c8Sgwr ctx->f_flags |= SMBFS_RDD_EOF; 44391d632c8Sgwr 44491d632c8Sgwr /* 44591d632c8Sgwr * Chop off the trailing ":$DATA" 44691d632c8Sgwr * The 6 here is strlen(":$DATA") 44791d632c8Sgwr */ 44891d632c8Sgwr if (ctx->f_nmlen >= 6) { 44991d632c8Sgwr char *p = ctx->f_name + ctx->f_nmlen - 6; 45091d632c8Sgwr if (strncmp(p, ":$DATA", 6) == 0) { 45191d632c8Sgwr *p = '\0'; /* Chop! */ 45291d632c8Sgwr ctx->f_nmlen -= 6; 45391d632c8Sgwr } 45491d632c8Sgwr } 45591d632c8Sgwr 45691d632c8Sgwr /* 45791d632c8Sgwr * The Chop above will typically leave 45891d632c8Sgwr * an empty name in the first slot, 45991d632c8Sgwr * which we will skip here. 46091d632c8Sgwr */ 46191d632c8Sgwr if (ctx->f_nmlen == 0) 46291d632c8Sgwr goto again; 46391d632c8Sgwr 46491d632c8Sgwr /* 46591d632c8Sgwr * If this is a lookup of a specific name, 46691d632c8Sgwr * skip past any non-matching names. 46791d632c8Sgwr */ 46891d632c8Sgwr if (ctx->f_flags & SMBFS_RDD_FINDSINGLE) { 46991d632c8Sgwr if (ctx->f_wclen != ctx->f_nmlen) 47091d632c8Sgwr goto again; 47191d632c8Sgwr if (u8_strcmp(ctx->f_wildcard, ctx->f_name, 47291d632c8Sgwr ctx->f_nmlen, U8_STRCMP_CI_LOWER, 47391d632c8Sgwr U8_UNICODE_LATEST, &error) || error) 47491d632c8Sgwr goto again; 47591d632c8Sgwr } 47691d632c8Sgwr 47791d632c8Sgwr return (0); 47891d632c8Sgwr } 47991d632c8Sgwr 48091d632c8Sgwr /* 48191d632c8Sgwr * Find first/next/close for XATTR directories. 48291d632c8Sgwr * NB: also used by smbfs_smb_lookup 48391d632c8Sgwr */ 48491d632c8Sgwr 48591d632c8Sgwr int 48691d632c8Sgwr smbfs_xa_findclose(struct smbfs_fctx *ctx) 48791d632c8Sgwr { 48891d632c8Sgwr 48991d632c8Sgwr if (ctx->f_name) 49091d632c8Sgwr kmem_free(ctx->f_name, ctx->f_namesz); 49191d632c8Sgwr if (ctx->f_t2) 49291d632c8Sgwr smb_t2_done(ctx->f_t2); 49391d632c8Sgwr 49491d632c8Sgwr return (0); 49591d632c8Sgwr } 496