15331Samw /*
25331Samw * CDDL HEADER START
35331Samw *
45331Samw * The contents of this file are subject to the terms of the
55331Samw * Common Development and Distribution License (the "License").
65331Samw * You may not use this file except in compliance with the License.
75331Samw *
85331Samw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw * or http://www.opensolaris.org/os/licensing.
105331Samw * See the License for the specific language governing permissions
115331Samw * and limitations under the License.
125331Samw *
135331Samw * When distributing Covered Code, include this CDDL HEADER in each
145331Samw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw * If applicable, add the following below this CDDL HEADER, with the
165331Samw * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw *
195331Samw * CDDL HEADER END
205331Samw */
215331Samw /*
2212508Samw@Sun.COM * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
235331Samw */
245331Samw
255331Samw /*
265331Samw * General Structures Layout
275331Samw * -------------------------
285331Samw *
295331Samw * This is a simplified diagram showing the relationship between most of the
305331Samw * main structures.
315331Samw *
325331Samw * +-------------------+
335331Samw * | SMB_INFO |
345331Samw * +-------------------+
355331Samw * |
365331Samw * |
375331Samw * v
385331Samw * +-------------------+ +-------------------+ +-------------------+
395331Samw * | SESSION |<----->| SESSION |......| SESSION |
405331Samw * +-------------------+ +-------------------+ +-------------------+
415331Samw * |
425331Samw * |
435331Samw * v
445331Samw * +-------------------+ +-------------------+ +-------------------+
455331Samw * | USER |<----->| USER |......| USER |
465331Samw * +-------------------+ +-------------------+ +-------------------+
475331Samw * |
485331Samw * |
495331Samw * v
505331Samw * +-------------------+ +-------------------+ +-------------------+
515331Samw * | TREE |<----->| TREE |......| TREE |
525331Samw * +-------------------+ +-------------------+ +-------------------+
535331Samw * | |
545331Samw * | |
555331Samw * | v
565331Samw * | +-------+ +-------+ +-------+
575331Samw * | | OFILE |<----->| OFILE |......| OFILE |
585331Samw * | +-------+ +-------+ +-------+
595331Samw * |
605331Samw * |
615331Samw * v
625331Samw * +-------+ +------+ +------+
635331Samw * | ODIR |<----->| ODIR |......| ODIR |
645331Samw * +-------+ +------+ +------+
655331Samw *
665331Samw *
675331Samw * Odir State Machine
685331Samw * ------------------
695331Samw *
708670SJose.Borrego@Sun.COM * +-------------------------+
718670SJose.Borrego@Sun.COM * | SMB_ODIR_STATE_OPEN |<----------- open / creation
725331Samw * +-------------------------+
739635SJoyce.McIntosh@Sun.COM * | ^
749635SJoyce.McIntosh@Sun.COM * | (first) | (last)
759635SJoyce.McIntosh@Sun.COM * | lookup | release
769635SJoyce.McIntosh@Sun.COM * v |
778670SJose.Borrego@Sun.COM * +-------------------------+
789635SJoyce.McIntosh@Sun.COM * | SMB_ODIR_STATE_IN_USE |----
799635SJoyce.McIntosh@Sun.COM * +-------------------------+ | lookup / release / read
809635SJoyce.McIntosh@Sun.COM * | ^-------
819635SJoyce.McIntosh@Sun.COM * | close
829635SJoyce.McIntosh@Sun.COM * |
839635SJoyce.McIntosh@Sun.COM * v
848670SJose.Borrego@Sun.COM * +-------------------------+
859635SJoyce.McIntosh@Sun.COM * | SMB_ODIR_STATE_CLOSING |----
869635SJoyce.McIntosh@Sun.COM * +-------------------------+ | close / release / read
879635SJoyce.McIntosh@Sun.COM * | ^-------
889635SJoyce.McIntosh@Sun.COM * | (last) release
899635SJoyce.McIntosh@Sun.COM * |
909635SJoyce.McIntosh@Sun.COM * v
915331Samw * +-------------------------+
928670SJose.Borrego@Sun.COM * | SMB_ODIR_STATE_CLOSED |----------> deletion
935331Samw * +-------------------------+
945331Samw *
958670SJose.Borrego@Sun.COM *
965331Samw * SMB_ODIR_STATE_OPEN
979635SJoyce.McIntosh@Sun.COM * - the odir exists in the list of odirs of its tree
989635SJoyce.McIntosh@Sun.COM * - lookup is valid in this state. It will place a hold on the odir
999635SJoyce.McIntosh@Sun.COM * by incrementing the reference count and the odir will transition
1009635SJoyce.McIntosh@Sun.COM * to SMB_ODIR_STATE_IN_USE
1019635SJoyce.McIntosh@Sun.COM * - read/close/release not valid in this state
1029635SJoyce.McIntosh@Sun.COM *
1039635SJoyce.McIntosh@Sun.COM * SMB_ODIR_STATE_IN_USE
1048670SJose.Borrego@Sun.COM * - the odir exists in the list of odirs of its tree.
1059635SJoyce.McIntosh@Sun.COM * - lookup is valid in this state. It will place a hold on the odir
1069635SJoyce.McIntosh@Sun.COM * by incrementing the reference count.
1079635SJoyce.McIntosh@Sun.COM * - if the last hold is released the odir will transition
1089635SJoyce.McIntosh@Sun.COM * back to SMB_ODIR_STATE_OPEN
1098670SJose.Borrego@Sun.COM * - if a close is received the odir will transition to
1108670SJose.Borrego@Sun.COM * SMB_ODIR_STATE_CLOSING.
1115331Samw *
1125331Samw * SMB_ODIR_STATE_CLOSING
1138670SJose.Borrego@Sun.COM * - the odir exists in the list of odirs of its tree.
1149635SJoyce.McIntosh@Sun.COM * - lookup will fail in this state.
1159635SJoyce.McIntosh@Sun.COM * - when the last hold is released the odir will transition
1169635SJoyce.McIntosh@Sun.COM * to SMB_ODIR_STATE_CLOSED.
1175331Samw *
1185331Samw * SMB_ODIR_STATE_CLOSED
1198670SJose.Borrego@Sun.COM * - the odir exists in the list of odirs of its tree.
1208670SJose.Borrego@Sun.COM * - there are no users of the odir (refcnt == 0)
1218670SJose.Borrego@Sun.COM * - the odir is being removed from the tree's list and deleted.
1229635SJoyce.McIntosh@Sun.COM * - lookup will fail in this state.
1239635SJoyce.McIntosh@Sun.COM * - read/close/release not valid in this state
1245331Samw *
1255331Samw * Comments
1265331Samw * --------
1275331Samw * The state machine of the odir structures is controlled by 3 elements:
1285331Samw * - The list of odirs of the tree it belongs to.
1295331Samw * - The mutex embedded in the structure itself.
1305331Samw * - The reference count.
1315331Samw *
1325331Samw * There's a mutex embedded in the odir structure used to protect its fields
1335331Samw * and there's a lock embedded in the list of odirs of a tree. To
1345331Samw * increment or to decrement the reference count the mutex must be entered.
1355331Samw * To insert the odir into the list of odirs of the tree and to remove
1365331Samw * the odir from it, the lock must be entered in RW_WRITER mode.
1375331Samw *
1388670SJose.Borrego@Sun.COM * In order to avoid deadlocks, when both (mutex and lock of the odir
1398670SJose.Borrego@Sun.COM * list) have to be entered, the lock must be entered first.
1408670SJose.Borrego@Sun.COM *
1418670SJose.Borrego@Sun.COM *
1428670SJose.Borrego@Sun.COM * Odir Interface
1438670SJose.Borrego@Sun.COM * ---------------
1448670SJose.Borrego@Sun.COM * odid = smb_odir_open(pathname)
1458670SJose.Borrego@Sun.COM * Create an odir representing the directory specified in pathname and
1468670SJose.Borrego@Sun.COM * add it into the tree's list of odirs.
1478670SJose.Borrego@Sun.COM * Return an identifier (odid) uniquely identifying the created odir.
1485331Samw *
1498670SJose.Borrego@Sun.COM * smb_odir_openat(smb_node_t *unode)
1508670SJose.Borrego@Sun.COM * Create an odir representing the extended attribute directory
1518670SJose.Borrego@Sun.COM * associated with the file (or directory) represented by unode
1528670SJose.Borrego@Sun.COM * and add it into the tree's list of odirs.
1538670SJose.Borrego@Sun.COM * Return an identifier (odid) uniquely identifying the created odir.
1548670SJose.Borrego@Sun.COM *
1558670SJose.Borrego@Sun.COM * smb_odir_t *odir = smb_tree_lookup_odir(odid)
1568670SJose.Borrego@Sun.COM * Find the odir corresponding to the specified odid in the tree's
1579635SJoyce.McIntosh@Sun.COM * list of odirs. Place a hold on the odir.
1588670SJose.Borrego@Sun.COM *
1598670SJose.Borrego@Sun.COM * smb_odir_read(..., smb_odirent_t *odirent)
1608670SJose.Borrego@Sun.COM * Find the next directory entry in the odir and return it in odirent.
1615331Samw *
1628670SJose.Borrego@Sun.COM * smb_odir_read_fileinfo(..., smb_fileinfo_t *)
1638670SJose.Borrego@Sun.COM * Find the next directory entry in the odir. Return the details of
1648670SJose.Borrego@Sun.COM * the directory entry in smb_fileinfo_t. (See odir internals below)
1658670SJose.Borrego@Sun.COM *
16610001SJoyce.McIntosh@Sun.COM * smb_odir_read_streaminfo(..., smb_streaminfo_t *)
1678670SJose.Borrego@Sun.COM * Find the next named stream entry in the odir. Return the details of
1688670SJose.Borrego@Sun.COM * the named stream in smb_streaminfo_t.
1698670SJose.Borrego@Sun.COM *
1709635SJoyce.McIntosh@Sun.COM * smb_odir_close(smb_odir_t *odir)
1719635SJoyce.McIntosh@Sun.COM * Close the odir.
1729635SJoyce.McIntosh@Sun.COM * The caller of close must have a hold on the odir being closed.
1739635SJoyce.McIntosh@Sun.COM * The hold should be released after closing.
1749635SJoyce.McIntosh@Sun.COM *
1758670SJose.Borrego@Sun.COM * smb_odir_release(smb_odir_t *odir)
1768670SJose.Borrego@Sun.COM * Release the hold on the odir, obtained by lookup.
1778670SJose.Borrego@Sun.COM *
1788670SJose.Borrego@Sun.COM *
1798670SJose.Borrego@Sun.COM * Odir Internals
1808670SJose.Borrego@Sun.COM * --------------
1818670SJose.Borrego@Sun.COM * The odir object represent an open directory search. Each read operation
1828670SJose.Borrego@Sun.COM * provides the caller with a structure containing information pertaining
1838670SJose.Borrego@Sun.COM * to the next directory entry that matches the search criteria, namely
1848670SJose.Borrego@Sun.COM * the filename or match pattern and, in the case of smb_odir_read_fileinfo(),
1858670SJose.Borrego@Sun.COM * the search attributes.
1868670SJose.Borrego@Sun.COM *
1878670SJose.Borrego@Sun.COM * The odir maintains a buffer (d_buf) of directory entries read from
1888670SJose.Borrego@Sun.COM * the filesystem via a vop_readdir. The buffer is populated when a read
1898670SJose.Borrego@Sun.COM * request (smb_odir_next_odirent) finds that the buffer is empty or that
1908670SJose.Borrego@Sun.COM * the end of the buffer has been reached, and also when a new client request
1918670SJose.Borrego@Sun.COM * (find next) begins.
1925331Samw *
1938670SJose.Borrego@Sun.COM * The data in d_buf (that which is returned from the file system) can
1948670SJose.Borrego@Sun.COM * be in one of two formats. If the file system supports extended directory
1958670SJose.Borrego@Sun.COM * entries we request that the data be returned as edirent_t structures. If
1968670SJose.Borrego@Sun.COM * it does not the data will be returned as dirent64_t structures. For
1978670SJose.Borrego@Sun.COM * convenience, when the next directory entry is read from d_buf by
1988670SJose.Borrego@Sun.COM * smb_odir_next_odirent it is translated into an smb_odirent_t.
1998670SJose.Borrego@Sun.COM *
2008670SJose.Borrego@Sun.COM * smb_odir_read_fileinfo
2018670SJose.Borrego@Sun.COM * The processing required to obtain the information to populate the caller's
2028670SJose.Borrego@Sun.COM * smb_fileinfo_t differs depending upon whether the directory search is for a
2038670SJose.Borrego@Sun.COM * single specified filename or for multiple files matching a search pattern.
2048670SJose.Borrego@Sun.COM * Thus smb_odir_read_fileinfo uses two static functions:
2058670SJose.Borrego@Sun.COM * smb_odir_single_fileinfo - obtains the smb_fileinfo_t info for the single
2068670SJose.Borrego@Sun.COM * filename as specified in smb_odir_open request.
2078670SJose.Borrego@Sun.COM * smb_odir_wildcard_fileinfo - obtains the smb_fileinfo_t info for the filename
2088670SJose.Borrego@Sun.COM * returned from the smb_odir_next_odirent. This is called in a loop until
2098670SJose.Borrego@Sun.COM * an entry matching the search criteria is found or no more entries exist.
2108670SJose.Borrego@Sun.COM *
2118670SJose.Borrego@Sun.COM * If a directory entry is a VLNK, the name returned in the smb_fileinfo_t
2128670SJose.Borrego@Sun.COM * is the name of the directory entry but the attributes are the attribites
2138670SJose.Borrego@Sun.COM * of the file that is the target of the link. If the link target cannot
2148670SJose.Borrego@Sun.COM * be found the attributes returned are the attributes of the link itself.
2155331Samw *
21610001SJoyce.McIntosh@Sun.COM * smb_odir_read_streaminfo
2178670SJose.Borrego@Sun.COM * In order for an odir to provide information about stream files it
2188670SJose.Borrego@Sun.COM * must be opened with smb_odir_openat(). smb_odir_read_streaminfo() can
2198670SJose.Borrego@Sun.COM * then be used to obtain the name and size of named stream files.
2205331Samw *
2218670SJose.Borrego@Sun.COM * Resuming a Search
2228670SJose.Borrego@Sun.COM * -----------------
2238670SJose.Borrego@Sun.COM * A directory search often consists of multiple client requests: an initial
2248670SJose.Borrego@Sun.COM * find_first request followed by zero or more find_next requests and a
2258670SJose.Borrego@Sun.COM * find_close request.
2268670SJose.Borrego@Sun.COM * The find_first request will open and lookup the odir, read its desired
2278670SJose.Borrego@Sun.COM * number of entries from the odir, then release the odir and return.
2288670SJose.Borrego@Sun.COM * A find_next request will lookup the odir and read its desired number of
2298670SJose.Borrego@Sun.COM * entries from the odir, then release the odir and return.
2308670SJose.Borrego@Sun.COM * At the end of the search the find_close request will close the odir.
2318670SJose.Borrego@Sun.COM *
2328670SJose.Borrego@Sun.COM * In order to be able to resume a directory search (find_next) the odir
2338670SJose.Borrego@Sun.COM * provides the capability for the caller to save one or more resume points
2348670SJose.Borrego@Sun.COM * (cookies) at the end of a request, and to specify which resume point
2358670SJose.Borrego@Sun.COM * (cookie) to restart from at the beginning of the next search.
2368670SJose.Borrego@Sun.COM * smb_odir_save_cookie(..., cookie)
2378670SJose.Borrego@Sun.COM * smb_odir_resume_at(smb_odir_resume_t *resume)
2388670SJose.Borrego@Sun.COM * A search can be resumed at a specified resume point (cookie), the resume
2398670SJose.Borrego@Sun.COM * point (cookie) stored at a specified index in the d_cookies array, or
2408670SJose.Borrego@Sun.COM * a specified filename. The latter (specified filename) is not yet supported.
2418670SJose.Borrego@Sun.COM *
2428670SJose.Borrego@Sun.COM * See smb_search, smb_find, smb_find_unique, and smb_trans2_find for details
2435331Samw */
2448670SJose.Borrego@Sun.COM
2455331Samw #include <smbsrv/smb_kproto.h>
2465331Samw #include <smbsrv/smb_fsops.h>
24710504SKeyur.Desai@Sun.COM #include <smbsrv/smb_share.h>
2488670SJose.Borrego@Sun.COM #include <sys/extdirent.h>
2495331Samw
2508670SJose.Borrego@Sun.COM /* static functions */
251*12890SJoyce.McIntosh@Sun.COM static uint16_t smb_odir_create(smb_request_t *, smb_node_t *,
2529343SAfshin.Ardakani@Sun.COM char *, uint16_t, cred_t *);
2538670SJose.Borrego@Sun.COM static int smb_odir_single_fileinfo(smb_request_t *, smb_odir_t *,
2548670SJose.Borrego@Sun.COM smb_fileinfo_t *);
2558670SJose.Borrego@Sun.COM static int smb_odir_wildcard_fileinfo(smb_request_t *, smb_odir_t *,
2568670SJose.Borrego@Sun.COM smb_odirent_t *, smb_fileinfo_t *);
2578670SJose.Borrego@Sun.COM static int smb_odir_next_odirent(smb_odir_t *, smb_odirent_t *);
25810001SJoyce.McIntosh@Sun.COM static boolean_t smb_odir_lookup_link(smb_request_t *, smb_odir_t *,
25910001SJoyce.McIntosh@Sun.COM char *, smb_node_t **);
260*12890SJoyce.McIntosh@Sun.COM static boolean_t smb_odir_match_name(smb_odir_t *, smb_odirent_t *);
2615331Samw
2625331Samw
2635331Samw /*
2645331Samw * smb_odir_open
2658670SJose.Borrego@Sun.COM *
2668670SJose.Borrego@Sun.COM * Create an odir representing the directory specified in pathname.
2678670SJose.Borrego@Sun.COM *
2688670SJose.Borrego@Sun.COM * Returns:
2698670SJose.Borrego@Sun.COM * odid - Unique identifier of newly created odir.
2708670SJose.Borrego@Sun.COM * 0 - error, error details set in sr.
2715331Samw */
2728670SJose.Borrego@Sun.COM uint16_t
smb_odir_open(smb_request_t * sr,char * path,uint16_t sattr,uint32_t flags)2739343SAfshin.Ardakani@Sun.COM smb_odir_open(smb_request_t *sr, char *path, uint16_t sattr, uint32_t flags)
2745331Samw {
2758670SJose.Borrego@Sun.COM int rc;
2768670SJose.Borrego@Sun.COM smb_tree_t *tree;
2778670SJose.Borrego@Sun.COM smb_node_t *dnode;
2788670SJose.Borrego@Sun.COM char pattern[MAXNAMELEN];
279*12890SJoyce.McIntosh@Sun.COM uint16_t odid;
2809343SAfshin.Ardakani@Sun.COM cred_t *cr;
2815331Samw
2828670SJose.Borrego@Sun.COM ASSERT(sr);
2838670SJose.Borrego@Sun.COM ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
2848670SJose.Borrego@Sun.COM ASSERT(sr->tid_tree);
2858670SJose.Borrego@Sun.COM ASSERT(sr->tid_tree->t_magic == SMB_TREE_MAGIC);
2865331Samw
2878670SJose.Borrego@Sun.COM tree = sr->tid_tree;
2888670SJose.Borrego@Sun.COM
28911337SWilliam.Krier@Sun.COM smb_convert_wildcards(path);
29011337SWilliam.Krier@Sun.COM
2918670SJose.Borrego@Sun.COM rc = smb_pathname_reduce(sr, sr->user_cr, path,
2928670SJose.Borrego@Sun.COM tree->t_snode, tree->t_snode, &dnode, pattern);
2938670SJose.Borrego@Sun.COM if (rc != 0) {
2948670SJose.Borrego@Sun.COM smbsr_errno(sr, rc);
2958670SJose.Borrego@Sun.COM return (0);
2965331Samw }
2975331Samw
29811963SAfshin.Ardakani@Sun.COM if (!smb_node_is_dir(dnode)) {
2998670SJose.Borrego@Sun.COM smbsr_error(sr, NT_STATUS_OBJECT_PATH_NOT_FOUND,
3008670SJose.Borrego@Sun.COM ERRDOS, ERROR_PATH_NOT_FOUND);
3018670SJose.Borrego@Sun.COM smb_node_release(dnode);
3028670SJose.Borrego@Sun.COM return (0);
3035331Samw }
3045331Samw
3058670SJose.Borrego@Sun.COM if (smb_fsop_access(sr, sr->user_cr, dnode, FILE_LIST_DIRECTORY) != 0) {
3068670SJose.Borrego@Sun.COM smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
3078670SJose.Borrego@Sun.COM ERRDOS, ERROR_ACCESS_DENIED);
3088670SJose.Borrego@Sun.COM smb_node_release(dnode);
3098670SJose.Borrego@Sun.COM return (0);
3108670SJose.Borrego@Sun.COM }
3115331Samw
3129343SAfshin.Ardakani@Sun.COM if (flags & SMB_ODIR_OPENF_BACKUP_INTENT)
3139343SAfshin.Ardakani@Sun.COM cr = smb_user_getprivcred(tree->t_user);
3149343SAfshin.Ardakani@Sun.COM else
3159343SAfshin.Ardakani@Sun.COM cr = tree->t_user->u_cred;
3169343SAfshin.Ardakani@Sun.COM
317*12890SJoyce.McIntosh@Sun.COM odid = smb_odir_create(sr, dnode, pattern, sattr, cr);
3188670SJose.Borrego@Sun.COM smb_node_release(dnode);
319*12890SJoyce.McIntosh@Sun.COM return (odid);
3205331Samw }
3215331Samw
3225331Samw /*
3238670SJose.Borrego@Sun.COM * smb_odir_openat
3248670SJose.Borrego@Sun.COM *
3258670SJose.Borrego@Sun.COM * Create an odir representing the extended attribute directory
3268670SJose.Borrego@Sun.COM * associated with the file (or directory) represented by unode.
3278670SJose.Borrego@Sun.COM *
3288670SJose.Borrego@Sun.COM * Returns:
3298670SJose.Borrego@Sun.COM * odid - Unique identifier of newly created odir.
3308670SJose.Borrego@Sun.COM * 0 - error, error details set in sr.
3318670SJose.Borrego@Sun.COM */
3328670SJose.Borrego@Sun.COM uint16_t
smb_odir_openat(smb_request_t * sr,smb_node_t * unode)3338670SJose.Borrego@Sun.COM smb_odir_openat(smb_request_t *sr, smb_node_t *unode)
3348670SJose.Borrego@Sun.COM {
3358670SJose.Borrego@Sun.COM int rc;
3368670SJose.Borrego@Sun.COM vnode_t *xattr_dvp;
337*12890SJoyce.McIntosh@Sun.COM uint16_t odid;
3388670SJose.Borrego@Sun.COM cred_t *cr;
3398670SJose.Borrego@Sun.COM char pattern[SMB_STREAM_PREFIX_LEN + 2];
3408670SJose.Borrego@Sun.COM
3418670SJose.Borrego@Sun.COM smb_node_t *xattr_dnode;
3428670SJose.Borrego@Sun.COM
3438670SJose.Borrego@Sun.COM ASSERT(sr);
3448670SJose.Borrego@Sun.COM ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
3458670SJose.Borrego@Sun.COM ASSERT(unode);
3468670SJose.Borrego@Sun.COM ASSERT(unode->n_magic == SMB_NODE_MAGIC);
3478670SJose.Borrego@Sun.COM
3488845Samw@Sun.COM if (SMB_TREE_CONTAINS_NODE(sr, unode) == 0 ||
3498845Samw@Sun.COM SMB_TREE_HAS_ACCESS(sr, ACE_LIST_DIRECTORY) == 0) {
3508670SJose.Borrego@Sun.COM smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
3518670SJose.Borrego@Sun.COM ERRDOS, ERROR_ACCESS_DENIED);
3528670SJose.Borrego@Sun.COM return (0);
3538670SJose.Borrego@Sun.COM }
3549343SAfshin.Ardakani@Sun.COM cr = kcred;
3558670SJose.Borrego@Sun.COM
3568670SJose.Borrego@Sun.COM /* find the xattrdir vnode */
3578670SJose.Borrego@Sun.COM rc = smb_vop_lookup_xattrdir(unode->vp, &xattr_dvp, LOOKUP_XATTR, cr);
3588670SJose.Borrego@Sun.COM if (rc != 0) {
3598670SJose.Borrego@Sun.COM smbsr_errno(sr, rc);
3608670SJose.Borrego@Sun.COM return (0);
3618670SJose.Borrego@Sun.COM }
3628670SJose.Borrego@Sun.COM
3638670SJose.Borrego@Sun.COM /* lookup the xattrdir's smb_node */
3648670SJose.Borrego@Sun.COM xattr_dnode = smb_node_lookup(sr, NULL, cr, xattr_dvp, XATTR_DIR,
36510001SJoyce.McIntosh@Sun.COM unode, NULL);
3668670SJose.Borrego@Sun.COM VN_RELE(xattr_dvp);
3678670SJose.Borrego@Sun.COM if (xattr_dnode == NULL) {
3688670SJose.Borrego@Sun.COM smbsr_error(sr, NT_STATUS_NO_MEMORY,
3698670SJose.Borrego@Sun.COM ERRDOS, ERROR_NOT_ENOUGH_MEMORY);
3708670SJose.Borrego@Sun.COM return (0);
3718670SJose.Borrego@Sun.COM }
3728670SJose.Borrego@Sun.COM
3738670SJose.Borrego@Sun.COM (void) snprintf(pattern, sizeof (pattern), "%s*", SMB_STREAM_PREFIX);
374*12890SJoyce.McIntosh@Sun.COM odid = smb_odir_create(sr, xattr_dnode, pattern, SMB_SEARCH_ATTRIBUTES,
3759343SAfshin.Ardakani@Sun.COM cr);
3768670SJose.Borrego@Sun.COM smb_node_release(xattr_dnode);
377*12890SJoyce.McIntosh@Sun.COM return (odid);
3788670SJose.Borrego@Sun.COM }
3798670SJose.Borrego@Sun.COM
3808670SJose.Borrego@Sun.COM /*
3818670SJose.Borrego@Sun.COM * smb_odir_hold
3829635SJoyce.McIntosh@Sun.COM *
3839635SJoyce.McIntosh@Sun.COM * A hold will only be granted if the odir is open or in_use.
3848670SJose.Borrego@Sun.COM */
3858670SJose.Borrego@Sun.COM boolean_t
smb_odir_hold(smb_odir_t * od)3868670SJose.Borrego@Sun.COM smb_odir_hold(smb_odir_t *od)
3878670SJose.Borrego@Sun.COM {
3888670SJose.Borrego@Sun.COM ASSERT(od);
3898670SJose.Borrego@Sun.COM ASSERT(od->d_magic == SMB_ODIR_MAGIC);
3908670SJose.Borrego@Sun.COM
3918670SJose.Borrego@Sun.COM mutex_enter(&od->d_mutex);
3929635SJoyce.McIntosh@Sun.COM
3939635SJoyce.McIntosh@Sun.COM switch (od->d_state) {
3949635SJoyce.McIntosh@Sun.COM case SMB_ODIR_STATE_OPEN:
3959635SJoyce.McIntosh@Sun.COM od->d_refcnt++;
3969635SJoyce.McIntosh@Sun.COM od->d_state = SMB_ODIR_STATE_IN_USE;
3979635SJoyce.McIntosh@Sun.COM break;
3989635SJoyce.McIntosh@Sun.COM case SMB_ODIR_STATE_IN_USE:
3999635SJoyce.McIntosh@Sun.COM od->d_refcnt++;
4009635SJoyce.McIntosh@Sun.COM break;
4019635SJoyce.McIntosh@Sun.COM case SMB_ODIR_STATE_CLOSING:
4029635SJoyce.McIntosh@Sun.COM case SMB_ODIR_STATE_CLOSED:
4039635SJoyce.McIntosh@Sun.COM default:
4048670SJose.Borrego@Sun.COM mutex_exit(&od->d_mutex);
4058670SJose.Borrego@Sun.COM return (B_FALSE);
4068670SJose.Borrego@Sun.COM }
4078670SJose.Borrego@Sun.COM
4088670SJose.Borrego@Sun.COM mutex_exit(&od->d_mutex);
4098670SJose.Borrego@Sun.COM return (B_TRUE);
4108670SJose.Borrego@Sun.COM }
4118670SJose.Borrego@Sun.COM
4128670SJose.Borrego@Sun.COM /*
41311963SAfshin.Ardakani@Sun.COM * If the odir is in SMB_ODIR_STATE_CLOSING and this release results in
41411963SAfshin.Ardakani@Sun.COM * a refcnt of 0, change the state to SMB_ODIR_STATE_CLOSED and post the
41511963SAfshin.Ardakani@Sun.COM * object for deletion. Object deletion is deferred to avoid modifying
41611963SAfshin.Ardakani@Sun.COM * a list while an iteration may be in progress.
4175331Samw */
4185331Samw void
smb_odir_release(smb_odir_t * od)4198670SJose.Borrego@Sun.COM smb_odir_release(smb_odir_t *od)
4205331Samw {
42111963SAfshin.Ardakani@Sun.COM SMB_ODIR_VALID(od);
4225331Samw
4235331Samw mutex_enter(&od->d_mutex);
4249635SJoyce.McIntosh@Sun.COM ASSERT(od->d_refcnt > 0);
4258670SJose.Borrego@Sun.COM
4265331Samw switch (od->d_state) {
4275331Samw case SMB_ODIR_STATE_OPEN:
4289635SJoyce.McIntosh@Sun.COM break;
4299635SJoyce.McIntosh@Sun.COM case SMB_ODIR_STATE_IN_USE:
4308670SJose.Borrego@Sun.COM od->d_refcnt--;
4319635SJoyce.McIntosh@Sun.COM if (od->d_refcnt == 0)
4329635SJoyce.McIntosh@Sun.COM od->d_state = SMB_ODIR_STATE_OPEN;
4335331Samw break;
4345331Samw case SMB_ODIR_STATE_CLOSING:
4358670SJose.Borrego@Sun.COM od->d_refcnt--;
4368670SJose.Borrego@Sun.COM if (od->d_refcnt == 0) {
4378670SJose.Borrego@Sun.COM od->d_state = SMB_ODIR_STATE_CLOSED;
43811963SAfshin.Ardakani@Sun.COM smb_tree_post_odir(od->d_tree, od);
4398670SJose.Borrego@Sun.COM }
4408670SJose.Borrego@Sun.COM break;
4415331Samw case SMB_ODIR_STATE_CLOSED:
4425331Samw default:
4435331Samw break;
4445331Samw }
4455331Samw
4465331Samw mutex_exit(&od->d_mutex);
4475331Samw }
4485331Samw
4495331Samw /*
4508670SJose.Borrego@Sun.COM * smb_odir_close
4515331Samw */
4528670SJose.Borrego@Sun.COM void
smb_odir_close(smb_odir_t * od)4538670SJose.Borrego@Sun.COM smb_odir_close(smb_odir_t *od)
4545331Samw {
4558670SJose.Borrego@Sun.COM ASSERT(od);
4569635SJoyce.McIntosh@Sun.COM ASSERT(od->d_magic == SMB_ODIR_MAGIC);
4575331Samw
4588670SJose.Borrego@Sun.COM mutex_enter(&od->d_mutex);
4599635SJoyce.McIntosh@Sun.COM ASSERT(od->d_refcnt > 0);
4609635SJoyce.McIntosh@Sun.COM switch (od->d_state) {
4619635SJoyce.McIntosh@Sun.COM case SMB_ODIR_STATE_OPEN:
4629635SJoyce.McIntosh@Sun.COM break;
4639635SJoyce.McIntosh@Sun.COM case SMB_ODIR_STATE_IN_USE:
4649635SJoyce.McIntosh@Sun.COM od->d_state = SMB_ODIR_STATE_CLOSING;
4659635SJoyce.McIntosh@Sun.COM break;
4669635SJoyce.McIntosh@Sun.COM case SMB_ODIR_STATE_CLOSING:
4679635SJoyce.McIntosh@Sun.COM case SMB_ODIR_STATE_CLOSED:
4689635SJoyce.McIntosh@Sun.COM default:
4699635SJoyce.McIntosh@Sun.COM break;
4708670SJose.Borrego@Sun.COM }
4718670SJose.Borrego@Sun.COM mutex_exit(&od->d_mutex);
4728670SJose.Borrego@Sun.COM }
4735331Samw
4748670SJose.Borrego@Sun.COM /*
4758670SJose.Borrego@Sun.COM * smb_odir_read
4768670SJose.Borrego@Sun.COM *
4778670SJose.Borrego@Sun.COM * Find the next directory entry matching the search pattern.
4788670SJose.Borrego@Sun.COM * No search attribute matching is performed.
4798670SJose.Borrego@Sun.COM *
4808670SJose.Borrego@Sun.COM * Returns:
4818670SJose.Borrego@Sun.COM * 0 - success.
4828670SJose.Borrego@Sun.COM * - If a matching entry was found eof will be B_FALSE and
4838670SJose.Borrego@Sun.COM * odirent will be populated.
4848670SJose.Borrego@Sun.COM * - If there are no matching entries eof will be B_TRUE.
4858670SJose.Borrego@Sun.COM * -1 - error, error details set in sr.
4868670SJose.Borrego@Sun.COM */
4878670SJose.Borrego@Sun.COM int
smb_odir_read(smb_request_t * sr,smb_odir_t * od,smb_odirent_t * odirent,boolean_t * eof)4888670SJose.Borrego@Sun.COM smb_odir_read(smb_request_t *sr, smb_odir_t *od,
4898670SJose.Borrego@Sun.COM smb_odirent_t *odirent, boolean_t *eof)
4908670SJose.Borrego@Sun.COM {
4919231SAfshin.Ardakani@Sun.COM int rc;
4928670SJose.Borrego@Sun.COM
4938670SJose.Borrego@Sun.COM ASSERT(sr);
4948670SJose.Borrego@Sun.COM ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
4958670SJose.Borrego@Sun.COM ASSERT(od);
4968670SJose.Borrego@Sun.COM ASSERT(od->d_magic == SMB_ODIR_MAGIC);
4978670SJose.Borrego@Sun.COM ASSERT(odirent);
4988670SJose.Borrego@Sun.COM
4998670SJose.Borrego@Sun.COM mutex_enter(&od->d_mutex);
5009635SJoyce.McIntosh@Sun.COM ASSERT(od->d_refcnt > 0);
5018670SJose.Borrego@Sun.COM
5029635SJoyce.McIntosh@Sun.COM switch (od->d_state) {
5039635SJoyce.McIntosh@Sun.COM case SMB_ODIR_STATE_IN_USE:
5049635SJoyce.McIntosh@Sun.COM case SMB_ODIR_STATE_CLOSING:
5059635SJoyce.McIntosh@Sun.COM break;
5069635SJoyce.McIntosh@Sun.COM case SMB_ODIR_STATE_OPEN:
5079635SJoyce.McIntosh@Sun.COM case SMB_ODIR_STATE_CLOSED:
5089635SJoyce.McIntosh@Sun.COM default:
5098670SJose.Borrego@Sun.COM mutex_exit(&od->d_mutex);
5108670SJose.Borrego@Sun.COM return (-1);
5118670SJose.Borrego@Sun.COM }
5128670SJose.Borrego@Sun.COM
5138670SJose.Borrego@Sun.COM for (;;) {
5148670SJose.Borrego@Sun.COM if ((rc = smb_odir_next_odirent(od, odirent)) != 0)
5155331Samw break;
516*12890SJoyce.McIntosh@Sun.COM if (smb_odir_match_name(od, odirent))
5178670SJose.Borrego@Sun.COM break;
5185331Samw }
5198670SJose.Borrego@Sun.COM
5208670SJose.Borrego@Sun.COM mutex_exit(&od->d_mutex);
5218670SJose.Borrego@Sun.COM
5228670SJose.Borrego@Sun.COM switch (rc) {
5238670SJose.Borrego@Sun.COM case 0:
5248670SJose.Borrego@Sun.COM *eof = B_FALSE;
5258670SJose.Borrego@Sun.COM return (0);
5268670SJose.Borrego@Sun.COM case ENOENT:
5278670SJose.Borrego@Sun.COM *eof = B_TRUE;
5288670SJose.Borrego@Sun.COM return (0);
5298670SJose.Borrego@Sun.COM default:
5308670SJose.Borrego@Sun.COM smbsr_errno(sr, rc);
5318670SJose.Borrego@Sun.COM return (-1);
5328670SJose.Borrego@Sun.COM }
5335331Samw }
5345331Samw
5358670SJose.Borrego@Sun.COM /*
5368670SJose.Borrego@Sun.COM * smb_odir_read_fileinfo
5378670SJose.Borrego@Sun.COM *
5388670SJose.Borrego@Sun.COM * Find the next directory entry matching the search pattern
5398670SJose.Borrego@Sun.COM * and attributes: od->d_pattern and od->d_sattr.
5408670SJose.Borrego@Sun.COM *
5418670SJose.Borrego@Sun.COM * If the search pattern specifies a single filename call
5428670SJose.Borrego@Sun.COM * smb_odir_single_fileinfo to get the file attributes and
5438670SJose.Borrego@Sun.COM * populate the caller's smb_fileinfo_t.
5448670SJose.Borrego@Sun.COM *
5458670SJose.Borrego@Sun.COM * If the search pattern contains wildcards call smb_odir_next_odirent
5468670SJose.Borrego@Sun.COM * to get the next directory entry then. Repeat until a matching
5478670SJose.Borrego@Sun.COM * filename is found. Call smb_odir_wildcard_fileinfo to get the
5488670SJose.Borrego@Sun.COM * file attributes and populate the caller's smb_fileinfo_t.
5498670SJose.Borrego@Sun.COM * This is repeated until a file matching the search criteria is found.
5508670SJose.Borrego@Sun.COM *
5518670SJose.Borrego@Sun.COM * Returns:
5528670SJose.Borrego@Sun.COM * 0 - success.
5538670SJose.Borrego@Sun.COM * - If a matching entry was found eof will be B_FALSE and
5548670SJose.Borrego@Sun.COM * fileinfo will be populated.
5558670SJose.Borrego@Sun.COM * - If there are no matching entries eof will be B_TRUE.
5568670SJose.Borrego@Sun.COM * -1 - error, error details set in sr.
5578670SJose.Borrego@Sun.COM */
5588670SJose.Borrego@Sun.COM int
smb_odir_read_fileinfo(smb_request_t * sr,smb_odir_t * od,smb_fileinfo_t * fileinfo,boolean_t * eof)5598670SJose.Borrego@Sun.COM smb_odir_read_fileinfo(smb_request_t *sr, smb_odir_t *od,
5608670SJose.Borrego@Sun.COM smb_fileinfo_t *fileinfo, boolean_t *eof)
5618670SJose.Borrego@Sun.COM {
56210966SJordan.Brown@Sun.COM int rc, errnum;
5638670SJose.Borrego@Sun.COM smb_odirent_t *odirent;
5648670SJose.Borrego@Sun.COM
5658670SJose.Borrego@Sun.COM ASSERT(sr);
5668670SJose.Borrego@Sun.COM ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
5678670SJose.Borrego@Sun.COM ASSERT(od);
5688670SJose.Borrego@Sun.COM ASSERT(od->d_magic == SMB_ODIR_MAGIC);
5698670SJose.Borrego@Sun.COM ASSERT(fileinfo);
5708670SJose.Borrego@Sun.COM
5718670SJose.Borrego@Sun.COM mutex_enter(&od->d_mutex);
5729635SJoyce.McIntosh@Sun.COM ASSERT(od->d_refcnt > 0);
5738670SJose.Borrego@Sun.COM
5749635SJoyce.McIntosh@Sun.COM switch (od->d_state) {
5759635SJoyce.McIntosh@Sun.COM case SMB_ODIR_STATE_IN_USE:
5769635SJoyce.McIntosh@Sun.COM case SMB_ODIR_STATE_CLOSING:
5779635SJoyce.McIntosh@Sun.COM break;
5789635SJoyce.McIntosh@Sun.COM case SMB_ODIR_STATE_OPEN:
5799635SJoyce.McIntosh@Sun.COM case SMB_ODIR_STATE_CLOSED:
5809635SJoyce.McIntosh@Sun.COM default:
5818670SJose.Borrego@Sun.COM mutex_exit(&od->d_mutex);
5828670SJose.Borrego@Sun.COM return (-1);
5838670SJose.Borrego@Sun.COM }
5848670SJose.Borrego@Sun.COM
5859231SAfshin.Ardakani@Sun.COM if (!(od->d_flags & SMB_ODIR_FLAG_WILDCARDS)) {
5868670SJose.Borrego@Sun.COM if (od->d_eof)
5878670SJose.Borrego@Sun.COM rc = ENOENT;
5888670SJose.Borrego@Sun.COM else
5898670SJose.Borrego@Sun.COM rc = smb_odir_single_fileinfo(sr, od, fileinfo);
5908670SJose.Borrego@Sun.COM od->d_eof = B_TRUE;
5918670SJose.Borrego@Sun.COM } else {
5928670SJose.Borrego@Sun.COM odirent = kmem_alloc(sizeof (smb_odirent_t), KM_SLEEP);
5938670SJose.Borrego@Sun.COM for (;;) {
5948670SJose.Borrego@Sun.COM bzero(fileinfo, sizeof (smb_fileinfo_t));
5958670SJose.Borrego@Sun.COM if ((rc = smb_odir_next_odirent(od, odirent)) != 0)
5968670SJose.Borrego@Sun.COM break;
5978670SJose.Borrego@Sun.COM
59810966SJordan.Brown@Sun.COM /* skip non utf8 filename */
59910966SJordan.Brown@Sun.COM if (u8_validate(odirent->od_name,
60010966SJordan.Brown@Sun.COM strlen(odirent->od_name), NULL,
60110966SJordan.Brown@Sun.COM U8_VALIDATE_ENTIRE, &errnum) < 0)
60210966SJordan.Brown@Sun.COM continue;
60310966SJordan.Brown@Sun.COM
604*12890SJoyce.McIntosh@Sun.COM if (!smb_odir_match_name(od, odirent))
6058670SJose.Borrego@Sun.COM continue;
6068670SJose.Borrego@Sun.COM
6078670SJose.Borrego@Sun.COM rc = smb_odir_wildcard_fileinfo(sr, od, odirent,
6088670SJose.Borrego@Sun.COM fileinfo);
6098670SJose.Borrego@Sun.COM if (rc == 0)
6108670SJose.Borrego@Sun.COM break;
6118670SJose.Borrego@Sun.COM }
6128670SJose.Borrego@Sun.COM kmem_free(odirent, sizeof (smb_odirent_t));
6138670SJose.Borrego@Sun.COM }
6148670SJose.Borrego@Sun.COM mutex_exit(&od->d_mutex);
6158670SJose.Borrego@Sun.COM
6168670SJose.Borrego@Sun.COM switch (rc) {
6178670SJose.Borrego@Sun.COM case 0:
6188670SJose.Borrego@Sun.COM *eof = B_FALSE;
6198670SJose.Borrego@Sun.COM return (0);
6208670SJose.Borrego@Sun.COM case ENOENT:
6218670SJose.Borrego@Sun.COM *eof = B_TRUE;
6228670SJose.Borrego@Sun.COM return (0);
6238670SJose.Borrego@Sun.COM default:
6248670SJose.Borrego@Sun.COM smbsr_errno(sr, rc);
6258670SJose.Borrego@Sun.COM return (-1);
6268670SJose.Borrego@Sun.COM }
6278670SJose.Borrego@Sun.COM }
6288670SJose.Borrego@Sun.COM
6295331Samw /*
6308670SJose.Borrego@Sun.COM * smb_odir_read_streaminfo
6318670SJose.Borrego@Sun.COM *
6328670SJose.Borrego@Sun.COM * Find the next directory entry whose name begins with SMB_STREAM_PREFIX,
6338670SJose.Borrego@Sun.COM * and thus represents an NTFS named stream.
6348670SJose.Borrego@Sun.COM * No search attribute matching is performed.
6359231SAfshin.Ardakani@Sun.COM * No case conflict name mangling is required for NTFS named stream names.
6365331Samw *
6378670SJose.Borrego@Sun.COM * Returns:
6388670SJose.Borrego@Sun.COM * 0 - success.
6398670SJose.Borrego@Sun.COM * - If a matching entry was found eof will be B_FALSE and
6408670SJose.Borrego@Sun.COM * sinfo will be populated.
6418670SJose.Borrego@Sun.COM * - If there are no matching entries eof will be B_TRUE.
6428670SJose.Borrego@Sun.COM * -1 - error, error details set in sr.
6435331Samw */
6448670SJose.Borrego@Sun.COM int
smb_odir_read_streaminfo(smb_request_t * sr,smb_odir_t * od,smb_streaminfo_t * sinfo,boolean_t * eof)6458670SJose.Borrego@Sun.COM smb_odir_read_streaminfo(smb_request_t *sr, smb_odir_t *od,
6468670SJose.Borrego@Sun.COM smb_streaminfo_t *sinfo, boolean_t *eof)
6475331Samw {
6488670SJose.Borrego@Sun.COM int rc;
6498670SJose.Borrego@Sun.COM smb_odirent_t *odirent;
65010504SKeyur.Desai@Sun.COM smb_node_t *fnode;
6518670SJose.Borrego@Sun.COM smb_attr_t attr;
6525331Samw
6538670SJose.Borrego@Sun.COM ASSERT(sr);
6548670SJose.Borrego@Sun.COM ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
6555331Samw ASSERT(od);
6565331Samw ASSERT(od->d_magic == SMB_ODIR_MAGIC);
6578670SJose.Borrego@Sun.COM ASSERT(sinfo);
6588670SJose.Borrego@Sun.COM
6598670SJose.Borrego@Sun.COM mutex_enter(&od->d_mutex);
6609635SJoyce.McIntosh@Sun.COM ASSERT(od->d_refcnt > 0);
6618670SJose.Borrego@Sun.COM
6629635SJoyce.McIntosh@Sun.COM switch (od->d_state) {
6639635SJoyce.McIntosh@Sun.COM case SMB_ODIR_STATE_IN_USE:
6649635SJoyce.McIntosh@Sun.COM case SMB_ODIR_STATE_CLOSING:
6659635SJoyce.McIntosh@Sun.COM break;
6669635SJoyce.McIntosh@Sun.COM case SMB_ODIR_STATE_OPEN:
6679635SJoyce.McIntosh@Sun.COM case SMB_ODIR_STATE_CLOSED:
6689635SJoyce.McIntosh@Sun.COM default:
6698670SJose.Borrego@Sun.COM mutex_exit(&od->d_mutex);
6708670SJose.Borrego@Sun.COM return (-1);
6718670SJose.Borrego@Sun.COM }
6728670SJose.Borrego@Sun.COM
6738670SJose.Borrego@Sun.COM /* Check that odir represents an xattr directory */
6749231SAfshin.Ardakani@Sun.COM if (!(od->d_flags & SMB_ODIR_FLAG_XATTR)) {
6758670SJose.Borrego@Sun.COM *eof = B_TRUE;
6768670SJose.Borrego@Sun.COM mutex_exit(&od->d_mutex);
6778670SJose.Borrego@Sun.COM return (0);
6788670SJose.Borrego@Sun.COM }
6798670SJose.Borrego@Sun.COM
6808670SJose.Borrego@Sun.COM odirent = kmem_alloc(sizeof (smb_odirent_t), KM_SLEEP);
6818670SJose.Borrego@Sun.COM
6828670SJose.Borrego@Sun.COM for (;;) {
6838670SJose.Borrego@Sun.COM bzero(sinfo, sizeof (smb_streaminfo_t));
6848670SJose.Borrego@Sun.COM if ((rc = smb_odir_next_odirent(od, odirent)) != 0)
6858670SJose.Borrego@Sun.COM break;
6868670SJose.Borrego@Sun.COM
6878670SJose.Borrego@Sun.COM if (strncmp(odirent->od_name, SMB_STREAM_PREFIX,
6888670SJose.Borrego@Sun.COM SMB_STREAM_PREFIX_LEN)) {
6898670SJose.Borrego@Sun.COM continue;
6908670SJose.Borrego@Sun.COM }
6918670SJose.Borrego@Sun.COM
69210504SKeyur.Desai@Sun.COM rc = smb_fsop_lookup(sr, od->d_cred, 0, od->d_tree->t_snode,
69310504SKeyur.Desai@Sun.COM od->d_dnode, odirent->od_name, &fnode);
6948670SJose.Borrego@Sun.COM if (rc == 0) {
69510504SKeyur.Desai@Sun.COM rc = smb_node_getattr(sr, fnode, &attr);
69610504SKeyur.Desai@Sun.COM smb_node_release(fnode);
6978670SJose.Borrego@Sun.COM }
6988670SJose.Borrego@Sun.COM
6998670SJose.Borrego@Sun.COM if (rc == 0) {
7008670SJose.Borrego@Sun.COM (void) strlcpy(sinfo->si_name,
7018670SJose.Borrego@Sun.COM odirent->od_name + SMB_STREAM_PREFIX_LEN,
7028670SJose.Borrego@Sun.COM sizeof (sinfo->si_name));
7038670SJose.Borrego@Sun.COM sinfo->si_size = attr.sa_vattr.va_size;
70410504SKeyur.Desai@Sun.COM sinfo->si_alloc_size = attr.sa_allocsz;
7058670SJose.Borrego@Sun.COM break;
7068670SJose.Borrego@Sun.COM }
7078670SJose.Borrego@Sun.COM }
7088670SJose.Borrego@Sun.COM mutex_exit(&od->d_mutex);
7098670SJose.Borrego@Sun.COM
7108670SJose.Borrego@Sun.COM kmem_free(odirent, sizeof (smb_odirent_t));
7118670SJose.Borrego@Sun.COM
7128670SJose.Borrego@Sun.COM switch (rc) {
7138670SJose.Borrego@Sun.COM case 0:
7148670SJose.Borrego@Sun.COM *eof = B_FALSE;
7158670SJose.Borrego@Sun.COM return (0);
7168670SJose.Borrego@Sun.COM case ENOENT:
7178670SJose.Borrego@Sun.COM *eof = B_TRUE;
7188670SJose.Borrego@Sun.COM return (0);
7198670SJose.Borrego@Sun.COM default:
7208670SJose.Borrego@Sun.COM smbsr_errno(sr, rc);
7218670SJose.Borrego@Sun.COM return (-1);
7228670SJose.Borrego@Sun.COM }
7238670SJose.Borrego@Sun.COM }
7248670SJose.Borrego@Sun.COM
7258670SJose.Borrego@Sun.COM /*
7268670SJose.Borrego@Sun.COM * smb_odir_save_cookie
7278670SJose.Borrego@Sun.COM *
7288670SJose.Borrego@Sun.COM * Callers can save up to SMB_MAX_SEARCH cookies in the odir
7298670SJose.Borrego@Sun.COM * to be used as resume points for a 'find next' request.
7308670SJose.Borrego@Sun.COM */
7318670SJose.Borrego@Sun.COM void
smb_odir_save_cookie(smb_odir_t * od,int idx,uint32_t cookie)7328670SJose.Borrego@Sun.COM smb_odir_save_cookie(smb_odir_t *od, int idx, uint32_t cookie)
7338670SJose.Borrego@Sun.COM {
7348670SJose.Borrego@Sun.COM ASSERT(od);
7358670SJose.Borrego@Sun.COM ASSERT(od->d_magic == SMB_ODIR_MAGIC);
7368670SJose.Borrego@Sun.COM ASSERT(idx >= 0 && idx < SMB_MAX_SEARCH);
7375331Samw
7385331Samw mutex_enter(&od->d_mutex);
7398670SJose.Borrego@Sun.COM od->d_cookies[idx] = cookie;
7408670SJose.Borrego@Sun.COM mutex_exit(&od->d_mutex);
7418670SJose.Borrego@Sun.COM }
7428670SJose.Borrego@Sun.COM
7438670SJose.Borrego@Sun.COM /*
7448670SJose.Borrego@Sun.COM * smb_odir_resume_at
7458670SJose.Borrego@Sun.COM *
7469343SAfshin.Ardakani@Sun.COM * If SMB_ODIR_FLAG_WILDCARDS is not set the search is for a single
7479343SAfshin.Ardakani@Sun.COM * file and should not be resumed.
7489343SAfshin.Ardakani@Sun.COM *
7499343SAfshin.Ardakani@Sun.COM * Wildcard searching can be resumed from:
7508670SJose.Borrego@Sun.COM * - the cookie saved at a specified index (SMBsearch, SMBfind).
7518670SJose.Borrego@Sun.COM * - a specified cookie (SMB_trans2_find)
7528670SJose.Borrego@Sun.COM * - a specified filename (SMB_trans2_find) - NOT SUPPORTED.
7538670SJose.Borrego@Sun.COM * Defaults to continuing from where the last search ended.
7548670SJose.Borrego@Sun.COM *
7558670SJose.Borrego@Sun.COM * Continuation from where the last search ended (SMB_trans2_find)
7568670SJose.Borrego@Sun.COM * is implemented by saving the last cookie at a specific index (0)
7578670SJose.Borrego@Sun.COM * smb_odir_resume_at indicates a new request, so reset od->d_bufptr
7588670SJose.Borrego@Sun.COM * and d_eof to force a vop_readdir.
7598670SJose.Borrego@Sun.COM */
7608670SJose.Borrego@Sun.COM void
smb_odir_resume_at(smb_odir_t * od,smb_odir_resume_t * resume)7618670SJose.Borrego@Sun.COM smb_odir_resume_at(smb_odir_t *od, smb_odir_resume_t *resume)
7628670SJose.Borrego@Sun.COM {
7638670SJose.Borrego@Sun.COM ASSERT(od);
7648670SJose.Borrego@Sun.COM ASSERT(od->d_magic == SMB_ODIR_MAGIC);
7658670SJose.Borrego@Sun.COM ASSERT(resume);
7668670SJose.Borrego@Sun.COM
7678670SJose.Borrego@Sun.COM mutex_enter(&od->d_mutex);
7688670SJose.Borrego@Sun.COM
7699343SAfshin.Ardakani@Sun.COM if ((od->d_flags & SMB_ODIR_FLAG_WILDCARDS) == 0) {
7709343SAfshin.Ardakani@Sun.COM od->d_eof = B_TRUE;
7719343SAfshin.Ardakani@Sun.COM mutex_exit(&od->d_mutex);
7729343SAfshin.Ardakani@Sun.COM return;
7739343SAfshin.Ardakani@Sun.COM }
7749343SAfshin.Ardakani@Sun.COM
7758670SJose.Borrego@Sun.COM switch (resume->or_type) {
7768670SJose.Borrego@Sun.COM case SMB_ODIR_RESUME_IDX:
7778670SJose.Borrego@Sun.COM ASSERT(resume->or_idx >= 0);
7788670SJose.Borrego@Sun.COM ASSERT(resume->or_idx < SMB_MAX_SEARCH);
7798670SJose.Borrego@Sun.COM
7808670SJose.Borrego@Sun.COM if ((resume->or_idx < 0) ||
7818670SJose.Borrego@Sun.COM (resume->or_idx >= SMB_MAX_SEARCH)) {
7828670SJose.Borrego@Sun.COM resume->or_idx = 0;
7838670SJose.Borrego@Sun.COM }
7848670SJose.Borrego@Sun.COM od->d_offset = od->d_cookies[resume->or_idx];
7858670SJose.Borrego@Sun.COM break;
7868670SJose.Borrego@Sun.COM case SMB_ODIR_RESUME_COOKIE:
7878670SJose.Borrego@Sun.COM od->d_offset = resume->or_cookie;
7888670SJose.Borrego@Sun.COM break;
7898670SJose.Borrego@Sun.COM case SMB_ODIR_RESUME_FNAME:
7908670SJose.Borrego@Sun.COM default:
7918670SJose.Borrego@Sun.COM od->d_offset = od->d_cookies[0];
7928670SJose.Borrego@Sun.COM break;
7935331Samw }
7948670SJose.Borrego@Sun.COM
7958670SJose.Borrego@Sun.COM /* Force a vop_readdir to refresh d_buf */
7968670SJose.Borrego@Sun.COM od->d_bufptr = NULL;
7978670SJose.Borrego@Sun.COM od->d_eof = B_FALSE;
7988670SJose.Borrego@Sun.COM
7998670SJose.Borrego@Sun.COM mutex_exit(&od->d_mutex);
8008670SJose.Borrego@Sun.COM }
8018670SJose.Borrego@Sun.COM
8028670SJose.Borrego@Sun.COM
8038670SJose.Borrego@Sun.COM /* *** static functions *** */
8048670SJose.Borrego@Sun.COM
8058670SJose.Borrego@Sun.COM /*
8068670SJose.Borrego@Sun.COM * smb_odir_create
8078670SJose.Borrego@Sun.COM * Allocate and populate an odir obect and add it to the tree's list.
8088670SJose.Borrego@Sun.COM */
809*12890SJoyce.McIntosh@Sun.COM static uint16_t
smb_odir_create(smb_request_t * sr,smb_node_t * dnode,char * pattern,uint16_t sattr,cred_t * cr)8108670SJose.Borrego@Sun.COM smb_odir_create(smb_request_t *sr, smb_node_t *dnode,
8119343SAfshin.Ardakani@Sun.COM char *pattern, uint16_t sattr, cred_t *cr)
8128670SJose.Borrego@Sun.COM {
8138670SJose.Borrego@Sun.COM smb_odir_t *od;
8148670SJose.Borrego@Sun.COM smb_tree_t *tree;
8158670SJose.Borrego@Sun.COM uint16_t odid;
8168670SJose.Borrego@Sun.COM
8178670SJose.Borrego@Sun.COM ASSERT(sr);
8188670SJose.Borrego@Sun.COM ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
8198670SJose.Borrego@Sun.COM ASSERT(sr->tid_tree);
8208670SJose.Borrego@Sun.COM ASSERT(sr->tid_tree->t_magic == SMB_TREE_MAGIC);
8218670SJose.Borrego@Sun.COM ASSERT(dnode);
8228670SJose.Borrego@Sun.COM ASSERT(dnode->n_magic == SMB_NODE_MAGIC);
8238670SJose.Borrego@Sun.COM
8248670SJose.Borrego@Sun.COM tree = sr->tid_tree;
8258670SJose.Borrego@Sun.COM
8268670SJose.Borrego@Sun.COM if (smb_idpool_alloc(&tree->t_odid_pool, &odid)) {
8278670SJose.Borrego@Sun.COM smbsr_error(sr, NT_STATUS_TOO_MANY_OPENED_FILES,
8288670SJose.Borrego@Sun.COM ERRDOS, ERROR_TOO_MANY_OPEN_FILES);
829*12890SJoyce.McIntosh@Sun.COM return (0);
8308670SJose.Borrego@Sun.COM }
8318670SJose.Borrego@Sun.COM
8328670SJose.Borrego@Sun.COM od = kmem_cache_alloc(tree->t_server->si_cache_odir, KM_SLEEP);
8338670SJose.Borrego@Sun.COM bzero(od, sizeof (smb_odir_t));
8348670SJose.Borrego@Sun.COM
8358670SJose.Borrego@Sun.COM mutex_init(&od->d_mutex, NULL, MUTEX_DEFAULT, NULL);
8369635SJoyce.McIntosh@Sun.COM od->d_refcnt = 0;
8378670SJose.Borrego@Sun.COM od->d_state = SMB_ODIR_STATE_OPEN;
8388670SJose.Borrego@Sun.COM od->d_magic = SMB_ODIR_MAGIC;
8398670SJose.Borrego@Sun.COM od->d_opened_by_pid = sr->smb_pid;
8408670SJose.Borrego@Sun.COM od->d_session = tree->t_session;
8419343SAfshin.Ardakani@Sun.COM od->d_cred = cr;
8428670SJose.Borrego@Sun.COM od->d_tree = tree;
8438670SJose.Borrego@Sun.COM od->d_dnode = dnode;
8448670SJose.Borrego@Sun.COM smb_node_ref(dnode);
8458670SJose.Borrego@Sun.COM od->d_odid = odid;
8468670SJose.Borrego@Sun.COM od->d_sattr = sattr;
8478670SJose.Borrego@Sun.COM (void) strlcpy(od->d_pattern, pattern, sizeof (od->d_pattern));
8489231SAfshin.Ardakani@Sun.COM od->d_flags = 0;
84911337SWilliam.Krier@Sun.COM if (smb_contains_wildcards(od->d_pattern))
8509231SAfshin.Ardakani@Sun.COM od->d_flags |= SMB_ODIR_FLAG_WILDCARDS;
8519231SAfshin.Ardakani@Sun.COM if (vfs_has_feature(dnode->vp->v_vfsp, VFSFT_DIRENTFLAGS))
8529231SAfshin.Ardakani@Sun.COM od->d_flags |= SMB_ODIR_FLAG_EDIRENT;
8539231SAfshin.Ardakani@Sun.COM if (smb_tree_has_feature(tree, SMB_TREE_CASEINSENSITIVE))
8549231SAfshin.Ardakani@Sun.COM od->d_flags |= SMB_ODIR_FLAG_IGNORE_CASE;
855*12890SJoyce.McIntosh@Sun.COM if (smb_tree_has_feature(tree, SMB_TREE_SHORTNAMES))
856*12890SJoyce.McIntosh@Sun.COM od->d_flags |= SMB_ODIR_FLAG_SHORTNAMES;
8579231SAfshin.Ardakani@Sun.COM if (SMB_TREE_SUPPORTS_CATIA(sr))
8589231SAfshin.Ardakani@Sun.COM od->d_flags |= SMB_ODIR_FLAG_CATIA;
85910504SKeyur.Desai@Sun.COM if (SMB_TREE_SUPPORTS_ABE(sr))
86010504SKeyur.Desai@Sun.COM od->d_flags |= SMB_ODIR_FLAG_ABE;
861*12890SJoyce.McIntosh@Sun.COM if (dnode->flags & NODE_XATTR_DIR)
862*12890SJoyce.McIntosh@Sun.COM od->d_flags |= SMB_ODIR_FLAG_XATTR;
8638670SJose.Borrego@Sun.COM od->d_eof = B_FALSE;
8648670SJose.Borrego@Sun.COM
8658670SJose.Borrego@Sun.COM smb_llist_enter(&tree->t_odir_list, RW_WRITER);
8668670SJose.Borrego@Sun.COM smb_llist_insert_tail(&tree->t_odir_list, od);
8678670SJose.Borrego@Sun.COM smb_llist_exit(&tree->t_odir_list);
8688670SJose.Borrego@Sun.COM
8698670SJose.Borrego@Sun.COM atomic_inc_32(&tree->t_session->s_dir_cnt);
870*12890SJoyce.McIntosh@Sun.COM return (odid);
8715331Samw }
8725331Samw
8735331Samw /*
87411963SAfshin.Ardakani@Sun.COM * Delete an odir.
8758670SJose.Borrego@Sun.COM *
87611963SAfshin.Ardakani@Sun.COM * Remove the odir from the tree list before freeing resources
87711963SAfshin.Ardakani@Sun.COM * associated with the odir.
8785331Samw */
87911963SAfshin.Ardakani@Sun.COM void
smb_odir_delete(void * arg)88011963SAfshin.Ardakani@Sun.COM smb_odir_delete(void *arg)
8815331Samw {
88211963SAfshin.Ardakani@Sun.COM smb_tree_t *tree;
88311963SAfshin.Ardakani@Sun.COM smb_odir_t *od = (smb_odir_t *)arg;
88411963SAfshin.Ardakani@Sun.COM
88511963SAfshin.Ardakani@Sun.COM SMB_ODIR_VALID(od);
88611963SAfshin.Ardakani@Sun.COM ASSERT(od->d_refcnt == 0);
8875331Samw ASSERT(od->d_state == SMB_ODIR_STATE_CLOSED);
8885331Samw
88911963SAfshin.Ardakani@Sun.COM tree = od->d_tree;
89011963SAfshin.Ardakani@Sun.COM smb_llist_enter(&tree->t_odir_list, RW_WRITER);
89111963SAfshin.Ardakani@Sun.COM smb_llist_remove(&tree->t_odir_list, od);
89211963SAfshin.Ardakani@Sun.COM smb_idpool_free(&tree->t_odid_pool, od->d_odid);
89311963SAfshin.Ardakani@Sun.COM atomic_dec_32(&tree->t_session->s_dir_cnt);
89411963SAfshin.Ardakani@Sun.COM smb_llist_exit(&tree->t_odir_list);
89511963SAfshin.Ardakani@Sun.COM
89611963SAfshin.Ardakani@Sun.COM mutex_enter(&od->d_mutex);
89711963SAfshin.Ardakani@Sun.COM mutex_exit(&od->d_mutex);
8988670SJose.Borrego@Sun.COM
8996139Sjb150015 od->d_magic = 0;
9008670SJose.Borrego@Sun.COM smb_node_release(od->d_dnode);
9015331Samw mutex_destroy(&od->d_mutex);
9026139Sjb150015 kmem_cache_free(od->d_tree->t_server->si_cache_odir, od);
9035331Samw }
9048670SJose.Borrego@Sun.COM
9058670SJose.Borrego@Sun.COM /*
9068670SJose.Borrego@Sun.COM * smb_odir_next_odirent
9078670SJose.Borrego@Sun.COM *
9088670SJose.Borrego@Sun.COM * Find the next directory entry in d_buf. If d_bufptr is NULL (buffer
9098670SJose.Borrego@Sun.COM * is empty or we've reached the end of it), read the next set of
9108670SJose.Borrego@Sun.COM * entries from the file system (vop_readdir).
9118670SJose.Borrego@Sun.COM *
9128670SJose.Borrego@Sun.COM * File systems which support VFSFT_EDIRENT_FLAGS will return the
9138670SJose.Borrego@Sun.COM * directory entries as a buffer of edirent_t structure. Others will
9148670SJose.Borrego@Sun.COM * return a buffer of dirent64_t structures. For simplicity translate
9158670SJose.Borrego@Sun.COM * the data into an smb_odirent_t structure.
9168670SJose.Borrego@Sun.COM * The ed_name/d_name in d_buf is NULL terminated by the file system.
9178670SJose.Borrego@Sun.COM *
9188670SJose.Borrego@Sun.COM * Some file systems can have directories larger than SMB_MAXDIRSIZE.
9199231SAfshin.Ardakani@Sun.COM * If the odirent offset >= SMB_MAXDIRSIZE return ENOENT and set d_eof
9209231SAfshin.Ardakani@Sun.COM * to true to stop subsequent calls to smb_vop_readdir.
9218670SJose.Borrego@Sun.COM *
9228670SJose.Borrego@Sun.COM * Returns:
9238670SJose.Borrego@Sun.COM * 0 - success. odirent is populated with the next directory entry
9248670SJose.Borrego@Sun.COM * ENOENT - no more directory entries
9258670SJose.Borrego@Sun.COM * errno - error
9268670SJose.Borrego@Sun.COM */
9278670SJose.Borrego@Sun.COM static int
smb_odir_next_odirent(smb_odir_t * od,smb_odirent_t * odirent)9288670SJose.Borrego@Sun.COM smb_odir_next_odirent(smb_odir_t *od, smb_odirent_t *odirent)
9298670SJose.Borrego@Sun.COM {
9308670SJose.Borrego@Sun.COM int rc;
9318670SJose.Borrego@Sun.COM int reclen;
9328670SJose.Borrego@Sun.COM int eof;
9338670SJose.Borrego@Sun.COM dirent64_t *dp;
9348670SJose.Borrego@Sun.COM edirent_t *edp;
9359231SAfshin.Ardakani@Sun.COM char *np;
93610504SKeyur.Desai@Sun.COM uint32_t abe_flag = 0;
9378670SJose.Borrego@Sun.COM
9388670SJose.Borrego@Sun.COM ASSERT(MUTEX_HELD(&od->d_mutex));
9398670SJose.Borrego@Sun.COM
9409437SJoyce.McIntosh@Sun.COM bzero(odirent, sizeof (smb_odirent_t));
9419437SJoyce.McIntosh@Sun.COM
9428670SJose.Borrego@Sun.COM if (od->d_bufptr != NULL) {
9439231SAfshin.Ardakani@Sun.COM if (od->d_flags & SMB_ODIR_FLAG_EDIRENT)
9449231SAfshin.Ardakani@Sun.COM reclen = od->d_edp->ed_reclen;
9459231SAfshin.Ardakani@Sun.COM else
9469231SAfshin.Ardakani@Sun.COM reclen = od->d_dp->d_reclen;
9478670SJose.Borrego@Sun.COM
9488670SJose.Borrego@Sun.COM if (reclen == 0) {
9498670SJose.Borrego@Sun.COM od->d_bufptr = NULL;
9508670SJose.Borrego@Sun.COM } else {
9518670SJose.Borrego@Sun.COM od->d_bufptr += reclen;
9528670SJose.Borrego@Sun.COM if (od->d_bufptr >= od->d_buf + od->d_bufsize)
9538670SJose.Borrego@Sun.COM od->d_bufptr = NULL;
9548670SJose.Borrego@Sun.COM }
9558670SJose.Borrego@Sun.COM }
9568670SJose.Borrego@Sun.COM
9578670SJose.Borrego@Sun.COM if (od->d_bufptr == NULL) {
9588670SJose.Borrego@Sun.COM if (od->d_eof)
9598670SJose.Borrego@Sun.COM return (ENOENT);
9608670SJose.Borrego@Sun.COM
9618670SJose.Borrego@Sun.COM od->d_bufsize = sizeof (od->d_buf);
9628670SJose.Borrego@Sun.COM
96310504SKeyur.Desai@Sun.COM if (od->d_flags & SMB_ODIR_FLAG_ABE)
96410504SKeyur.Desai@Sun.COM abe_flag = SMB_ABE;
96510504SKeyur.Desai@Sun.COM
9668670SJose.Borrego@Sun.COM rc = smb_vop_readdir(od->d_dnode->vp, od->d_offset,
96710504SKeyur.Desai@Sun.COM od->d_buf, &od->d_bufsize, &eof, abe_flag, od->d_cred);
9688670SJose.Borrego@Sun.COM
9698670SJose.Borrego@Sun.COM if ((rc == 0) && (od->d_bufsize == 0))
9708670SJose.Borrego@Sun.COM rc = ENOENT;
9718670SJose.Borrego@Sun.COM
9728670SJose.Borrego@Sun.COM if (rc != 0) {
9738670SJose.Borrego@Sun.COM od->d_bufptr = NULL;
9748670SJose.Borrego@Sun.COM od->d_bufsize = 0;
9758670SJose.Borrego@Sun.COM return (rc);
9768670SJose.Borrego@Sun.COM }
9778670SJose.Borrego@Sun.COM
9788670SJose.Borrego@Sun.COM od->d_eof = (eof != 0);
9798670SJose.Borrego@Sun.COM od->d_bufptr = od->d_buf;
9808670SJose.Borrego@Sun.COM }
9818670SJose.Borrego@Sun.COM
9829231SAfshin.Ardakani@Sun.COM if (od->d_flags & SMB_ODIR_FLAG_EDIRENT)
9839231SAfshin.Ardakani@Sun.COM od->d_offset = od->d_edp->ed_off;
9849231SAfshin.Ardakani@Sun.COM else
9859231SAfshin.Ardakani@Sun.COM od->d_offset = od->d_dp->d_off;
9869231SAfshin.Ardakani@Sun.COM
9878670SJose.Borrego@Sun.COM if (od->d_offset >= SMB_MAXDIRSIZE) {
9888670SJose.Borrego@Sun.COM od->d_bufptr = NULL;
9898670SJose.Borrego@Sun.COM od->d_bufsize = 0;
9909231SAfshin.Ardakani@Sun.COM od->d_eof = B_TRUE;
9918670SJose.Borrego@Sun.COM return (ENOENT);
9928670SJose.Borrego@Sun.COM }
9938670SJose.Borrego@Sun.COM
9949231SAfshin.Ardakani@Sun.COM if (od->d_flags & SMB_ODIR_FLAG_EDIRENT) {
9958670SJose.Borrego@Sun.COM edp = od->d_edp;
9968670SJose.Borrego@Sun.COM odirent->od_ino = edp->ed_ino;
9978670SJose.Borrego@Sun.COM odirent->od_eflags = edp->ed_eflags;
9989231SAfshin.Ardakani@Sun.COM np = edp->ed_name;
9998670SJose.Borrego@Sun.COM } else {
10008670SJose.Borrego@Sun.COM dp = od->d_dp;
10018670SJose.Borrego@Sun.COM odirent->od_ino = dp->d_ino;
10028670SJose.Borrego@Sun.COM odirent->od_eflags = 0;
10039231SAfshin.Ardakani@Sun.COM np = dp->d_name;
10049231SAfshin.Ardakani@Sun.COM }
10059231SAfshin.Ardakani@Sun.COM
10069231SAfshin.Ardakani@Sun.COM if ((od->d_flags & SMB_ODIR_FLAG_CATIA) &&
10079231SAfshin.Ardakani@Sun.COM ((od->d_flags & SMB_ODIR_FLAG_XATTR) == 0)) {
10089231SAfshin.Ardakani@Sun.COM smb_vop_catia_v4tov5(np, odirent->od_name,
10099231SAfshin.Ardakani@Sun.COM sizeof (odirent->od_name));
10109231SAfshin.Ardakani@Sun.COM } else {
10119231SAfshin.Ardakani@Sun.COM (void) strlcpy(odirent->od_name, np,
10128670SJose.Borrego@Sun.COM sizeof (odirent->od_name));
10138670SJose.Borrego@Sun.COM }
10148670SJose.Borrego@Sun.COM
10158670SJose.Borrego@Sun.COM return (0);
10168670SJose.Borrego@Sun.COM }
10178670SJose.Borrego@Sun.COM
10188670SJose.Borrego@Sun.COM /*
10198670SJose.Borrego@Sun.COM * smb_odir_single_fileinfo
10208670SJose.Borrego@Sun.COM *
10218670SJose.Borrego@Sun.COM * Lookup the file identified by od->d_pattern.
10228670SJose.Borrego@Sun.COM *
10238670SJose.Borrego@Sun.COM * If the looked up file is a link, we attempt to lookup the link target
10248670SJose.Borrego@Sun.COM * to use its attributes in place of those of the files's.
10258670SJose.Borrego@Sun.COM * If we fail to lookup the target of the link we use the original
10268670SJose.Borrego@Sun.COM * file's attributes.
10278670SJose.Borrego@Sun.COM * Check if the attributes match the search attributes.
10288670SJose.Borrego@Sun.COM *
10298670SJose.Borrego@Sun.COM * Returns: 0 - success
10308670SJose.Borrego@Sun.COM * ENOENT - no match
10318670SJose.Borrego@Sun.COM * errno - error
10328670SJose.Borrego@Sun.COM */
10338670SJose.Borrego@Sun.COM static int
smb_odir_single_fileinfo(smb_request_t * sr,smb_odir_t * od,smb_fileinfo_t * fileinfo)10348670SJose.Borrego@Sun.COM smb_odir_single_fileinfo(smb_request_t *sr, smb_odir_t *od,
10358670SJose.Borrego@Sun.COM smb_fileinfo_t *fileinfo)
10368670SJose.Borrego@Sun.COM {
10378670SJose.Borrego@Sun.COM int rc;
10388670SJose.Borrego@Sun.COM smb_node_t *fnode, *tgt_node;
103910001SJoyce.McIntosh@Sun.COM smb_attr_t attr;
1040*12890SJoyce.McIntosh@Sun.COM ino64_t fid;
10418670SJose.Borrego@Sun.COM char *name;
10429231SAfshin.Ardakani@Sun.COM boolean_t case_conflict = B_FALSE;
10439231SAfshin.Ardakani@Sun.COM int lookup_flags, flags = 0;
10449231SAfshin.Ardakani@Sun.COM vnode_t *vp;
10458670SJose.Borrego@Sun.COM
10468670SJose.Borrego@Sun.COM ASSERT(sr);
10478670SJose.Borrego@Sun.COM ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
10488670SJose.Borrego@Sun.COM ASSERT(od);
10498670SJose.Borrego@Sun.COM ASSERT(od->d_magic == SMB_ODIR_MAGIC);
10508670SJose.Borrego@Sun.COM
10518670SJose.Borrego@Sun.COM ASSERT(MUTEX_HELD(&od->d_mutex));
10528670SJose.Borrego@Sun.COM bzero(fileinfo, sizeof (smb_fileinfo_t));
10538670SJose.Borrego@Sun.COM
10549343SAfshin.Ardakani@Sun.COM rc = smb_fsop_lookup(sr, od->d_cred, 0, od->d_tree->t_snode,
105510001SJoyce.McIntosh@Sun.COM od->d_dnode, od->d_pattern, &fnode);
10568670SJose.Borrego@Sun.COM if (rc != 0)
10578670SJose.Borrego@Sun.COM return (rc);
10588670SJose.Borrego@Sun.COM
10599231SAfshin.Ardakani@Sun.COM /*
10609231SAfshin.Ardakani@Sun.COM * If case sensitive, do a case insensitive smb_vop_lookup to
10619231SAfshin.Ardakani@Sun.COM * check for case conflict
10629231SAfshin.Ardakani@Sun.COM */
10639231SAfshin.Ardakani@Sun.COM if (od->d_flags & SMB_ODIR_FLAG_IGNORE_CASE) {
10649231SAfshin.Ardakani@Sun.COM lookup_flags = SMB_IGNORE_CASE;
10659231SAfshin.Ardakani@Sun.COM if (od->d_flags & SMB_ODIR_FLAG_CATIA)
10669231SAfshin.Ardakani@Sun.COM lookup_flags |= SMB_CATIA;
10678670SJose.Borrego@Sun.COM
10689231SAfshin.Ardakani@Sun.COM rc = smb_vop_lookup(od->d_dnode->vp, fnode->od_name, &vp,
10699231SAfshin.Ardakani@Sun.COM NULL, lookup_flags, &flags, od->d_tree->t_snode->vp,
107011963SAfshin.Ardakani@Sun.COM NULL, od->d_cred);
10719231SAfshin.Ardakani@Sun.COM if (rc != 0)
10729231SAfshin.Ardakani@Sun.COM return (rc);
10739231SAfshin.Ardakani@Sun.COM VN_RELE(vp);
10749231SAfshin.Ardakani@Sun.COM
10759231SAfshin.Ardakani@Sun.COM if (flags & ED_CASE_CONFLICT)
10769231SAfshin.Ardakani@Sun.COM case_conflict = B_TRUE;
10779231SAfshin.Ardakani@Sun.COM }
10789231SAfshin.Ardakani@Sun.COM
107910001SJoyce.McIntosh@Sun.COM if ((rc = smb_node_getattr(sr, fnode, &attr)) != 0) {
108010001SJoyce.McIntosh@Sun.COM smb_node_release(fnode);
108110001SJoyce.McIntosh@Sun.COM return (rc);
108210001SJoyce.McIntosh@Sun.COM }
108310001SJoyce.McIntosh@Sun.COM
10848670SJose.Borrego@Sun.COM
10858670SJose.Borrego@Sun.COM /* follow link to get target node & attr */
108611963SAfshin.Ardakani@Sun.COM if (smb_node_is_symlink(fnode) &&
108711963SAfshin.Ardakani@Sun.COM smb_odir_lookup_link(sr, od, fnode->od_name, &tgt_node)) {
10888670SJose.Borrego@Sun.COM smb_node_release(fnode);
10898670SJose.Borrego@Sun.COM fnode = tgt_node;
109010001SJoyce.McIntosh@Sun.COM if ((rc = smb_node_getattr(sr, fnode, &attr)) != 0) {
109110001SJoyce.McIntosh@Sun.COM smb_node_release(fnode);
109210001SJoyce.McIntosh@Sun.COM return (rc);
109310001SJoyce.McIntosh@Sun.COM }
10948670SJose.Borrego@Sun.COM }
10958670SJose.Borrego@Sun.COM
10968670SJose.Borrego@Sun.COM /* check search attributes */
109710001SJoyce.McIntosh@Sun.COM if (!smb_sattr_check(attr.sa_dosattr, od->d_sattr)) {
10988670SJose.Borrego@Sun.COM smb_node_release(fnode);
10998670SJose.Borrego@Sun.COM return (ENOENT);
11008670SJose.Borrego@Sun.COM }
11018670SJose.Borrego@Sun.COM
110212508Samw@Sun.COM name = fnode->od_name;
1103*12890SJoyce.McIntosh@Sun.COM if (od->d_flags & SMB_ODIR_FLAG_SHORTNAMES) {
1104*12890SJoyce.McIntosh@Sun.COM fid = attr.sa_vattr.va_nodeid;
1105*12890SJoyce.McIntosh@Sun.COM if (case_conflict || smb_needs_mangled(name)) {
1106*12890SJoyce.McIntosh@Sun.COM smb_mangle(name, fid, fileinfo->fi_shortname,
1107*12890SJoyce.McIntosh@Sun.COM SMB_SHORTNAMELEN);
1108*12890SJoyce.McIntosh@Sun.COM }
1109*12890SJoyce.McIntosh@Sun.COM if (case_conflict)
1110*12890SJoyce.McIntosh@Sun.COM name = fileinfo->fi_shortname;
1111*12890SJoyce.McIntosh@Sun.COM }
111212508Samw@Sun.COM
111312508Samw@Sun.COM (void) strlcpy(fileinfo->fi_name, name, sizeof (fileinfo->fi_name));
111412508Samw@Sun.COM
111510001SJoyce.McIntosh@Sun.COM fileinfo->fi_dosattr = attr.sa_dosattr;
111610001SJoyce.McIntosh@Sun.COM fileinfo->fi_nodeid = attr.sa_vattr.va_nodeid;
111710001SJoyce.McIntosh@Sun.COM fileinfo->fi_size = attr.sa_vattr.va_size;
111810504SKeyur.Desai@Sun.COM fileinfo->fi_alloc_size = attr.sa_allocsz;
111910001SJoyce.McIntosh@Sun.COM fileinfo->fi_atime = attr.sa_vattr.va_atime;
112010001SJoyce.McIntosh@Sun.COM fileinfo->fi_mtime = attr.sa_vattr.va_mtime;
112110001SJoyce.McIntosh@Sun.COM fileinfo->fi_ctime = attr.sa_vattr.va_ctime;
112210001SJoyce.McIntosh@Sun.COM if (attr.sa_crtime.tv_sec)
112310001SJoyce.McIntosh@Sun.COM fileinfo->fi_crtime = attr.sa_crtime;
11248670SJose.Borrego@Sun.COM else
112510001SJoyce.McIntosh@Sun.COM fileinfo->fi_crtime = attr.sa_vattr.va_mtime;
11268670SJose.Borrego@Sun.COM
11278670SJose.Borrego@Sun.COM smb_node_release(fnode);
11288670SJose.Borrego@Sun.COM return (0);
11298670SJose.Borrego@Sun.COM }
11308670SJose.Borrego@Sun.COM
11318670SJose.Borrego@Sun.COM /*
11328670SJose.Borrego@Sun.COM * smb_odir_wildcard_fileinfo
11338670SJose.Borrego@Sun.COM *
11348670SJose.Borrego@Sun.COM * odirent contains a directory entry, obtained from a vop_readdir.
11358670SJose.Borrego@Sun.COM * If a case conflict is identified the filename is mangled and the
113612508Samw@Sun.COM * shortname is used as 'name', in place of odirent->od_name.
11378670SJose.Borrego@Sun.COM *
11388670SJose.Borrego@Sun.COM * If the looked up file is a link, we attempt to lookup the link target
11398670SJose.Borrego@Sun.COM * to use its attributes in place of those of the files's.
11408670SJose.Borrego@Sun.COM * If we fail to lookup the target of the link we use the original
11418670SJose.Borrego@Sun.COM * file's attributes.
11428670SJose.Borrego@Sun.COM * Check if the attributes match the search attributes.
11438670SJose.Borrego@Sun.COM *
11448670SJose.Borrego@Sun.COM * Although some file systems can have directories larger than
11458670SJose.Borrego@Sun.COM * SMB_MAXDIRSIZE smb_odir_next_odirent ensures that no offset larger
11468670SJose.Borrego@Sun.COM * than SMB_MAXDIRSIZE is returned. It is therefore safe to use the
11478670SJose.Borrego@Sun.COM * offset as the cookie (uint32_t).
11488670SJose.Borrego@Sun.COM *
11498670SJose.Borrego@Sun.COM * Returns: 0 - success
11508670SJose.Borrego@Sun.COM * ENOENT - no match, proceed to next entry
11518670SJose.Borrego@Sun.COM * errno - error
11528670SJose.Borrego@Sun.COM */
11538670SJose.Borrego@Sun.COM static int
smb_odir_wildcard_fileinfo(smb_request_t * sr,smb_odir_t * od,smb_odirent_t * odirent,smb_fileinfo_t * fileinfo)11548670SJose.Borrego@Sun.COM smb_odir_wildcard_fileinfo(smb_request_t *sr, smb_odir_t *od,
11558670SJose.Borrego@Sun.COM smb_odirent_t *odirent, smb_fileinfo_t *fileinfo)
11568670SJose.Borrego@Sun.COM {
11578670SJose.Borrego@Sun.COM int rc;
11588670SJose.Borrego@Sun.COM smb_node_t *fnode, *tgt_node;
115910001SJoyce.McIntosh@Sun.COM smb_attr_t attr;
11608670SJose.Borrego@Sun.COM char *name;
11618670SJose.Borrego@Sun.COM boolean_t case_conflict;
11628670SJose.Borrego@Sun.COM
11638670SJose.Borrego@Sun.COM ASSERT(sr);
11648670SJose.Borrego@Sun.COM ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
11658670SJose.Borrego@Sun.COM ASSERT(od);
11668670SJose.Borrego@Sun.COM ASSERT(od->d_magic == SMB_ODIR_MAGIC);
11678670SJose.Borrego@Sun.COM
11688670SJose.Borrego@Sun.COM ASSERT(MUTEX_HELD(&od->d_mutex));
11698670SJose.Borrego@Sun.COM bzero(fileinfo, sizeof (smb_fileinfo_t));
11708670SJose.Borrego@Sun.COM
117112508Samw@Sun.COM rc = smb_fsop_lookup(sr, od->d_cred, SMB_CASE_SENSITIVE,
117212508Samw@Sun.COM od->d_tree->t_snode, od->d_dnode, odirent->od_name, &fnode);
11738670SJose.Borrego@Sun.COM if (rc != 0)
11748670SJose.Borrego@Sun.COM return (rc);
11758670SJose.Borrego@Sun.COM
11768670SJose.Borrego@Sun.COM /* follow link to get target node & attr */
117711963SAfshin.Ardakani@Sun.COM if (smb_node_is_symlink(fnode) &&
117812508Samw@Sun.COM smb_odir_lookup_link(sr, od, odirent->od_name, &tgt_node)) {
11798670SJose.Borrego@Sun.COM smb_node_release(fnode);
11808670SJose.Borrego@Sun.COM fnode = tgt_node;
118110001SJoyce.McIntosh@Sun.COM }
118210001SJoyce.McIntosh@Sun.COM
118311963SAfshin.Ardakani@Sun.COM /* skip system files */
118411963SAfshin.Ardakani@Sun.COM if (smb_node_is_system(fnode)) {
118511963SAfshin.Ardakani@Sun.COM smb_node_release(fnode);
118611963SAfshin.Ardakani@Sun.COM return (ENOENT);
118711963SAfshin.Ardakani@Sun.COM }
118811963SAfshin.Ardakani@Sun.COM
118910001SJoyce.McIntosh@Sun.COM if ((rc = smb_node_getattr(sr, fnode, &attr)) != 0) {
119010001SJoyce.McIntosh@Sun.COM smb_node_release(fnode);
119110001SJoyce.McIntosh@Sun.COM return (rc);
11928670SJose.Borrego@Sun.COM }
11938670SJose.Borrego@Sun.COM
11948670SJose.Borrego@Sun.COM /* check search attributes */
119510001SJoyce.McIntosh@Sun.COM if (!smb_sattr_check(attr.sa_dosattr, od->d_sattr)) {
11968670SJose.Borrego@Sun.COM smb_node_release(fnode);
11978670SJose.Borrego@Sun.COM return (ENOENT);
11988670SJose.Borrego@Sun.COM }
11998670SJose.Borrego@Sun.COM
1200*12890SJoyce.McIntosh@Sun.COM name = odirent->od_name;
1201*12890SJoyce.McIntosh@Sun.COM if (od->d_flags & SMB_ODIR_FLAG_SHORTNAMES) {
1202*12890SJoyce.McIntosh@Sun.COM case_conflict = ((od->d_flags & SMB_ODIR_FLAG_IGNORE_CASE) &&
1203*12890SJoyce.McIntosh@Sun.COM (odirent->od_eflags & ED_CASE_CONFLICT));
1204*12890SJoyce.McIntosh@Sun.COM if (case_conflict || smb_needs_mangled(name)) {
1205*12890SJoyce.McIntosh@Sun.COM smb_mangle(name, odirent->od_ino,
1206*12890SJoyce.McIntosh@Sun.COM fileinfo->fi_shortname, SMB_SHORTNAMELEN);
1207*12890SJoyce.McIntosh@Sun.COM }
1208*12890SJoyce.McIntosh@Sun.COM if (case_conflict)
1209*12890SJoyce.McIntosh@Sun.COM name = fileinfo->fi_shortname;
121012508Samw@Sun.COM }
121112508Samw@Sun.COM
121212508Samw@Sun.COM (void) strlcpy(fileinfo->fi_name, name, sizeof (fileinfo->fi_name));
121312508Samw@Sun.COM
12148670SJose.Borrego@Sun.COM fileinfo->fi_cookie = (uint32_t)od->d_offset;
121510001SJoyce.McIntosh@Sun.COM fileinfo->fi_dosattr = attr.sa_dosattr;
121610001SJoyce.McIntosh@Sun.COM fileinfo->fi_nodeid = attr.sa_vattr.va_nodeid;
121710001SJoyce.McIntosh@Sun.COM fileinfo->fi_size = attr.sa_vattr.va_size;
121810504SKeyur.Desai@Sun.COM fileinfo->fi_alloc_size = attr.sa_allocsz;
121910001SJoyce.McIntosh@Sun.COM fileinfo->fi_atime = attr.sa_vattr.va_atime;
122010001SJoyce.McIntosh@Sun.COM fileinfo->fi_mtime = attr.sa_vattr.va_mtime;
122110001SJoyce.McIntosh@Sun.COM fileinfo->fi_ctime = attr.sa_vattr.va_ctime;
122210001SJoyce.McIntosh@Sun.COM if (attr.sa_crtime.tv_sec)
122310001SJoyce.McIntosh@Sun.COM fileinfo->fi_crtime = attr.sa_crtime;
12248670SJose.Borrego@Sun.COM else
122510001SJoyce.McIntosh@Sun.COM fileinfo->fi_crtime = attr.sa_vattr.va_mtime;
12268670SJose.Borrego@Sun.COM
12278670SJose.Borrego@Sun.COM smb_node_release(fnode);
12288670SJose.Borrego@Sun.COM return (0);
12298670SJose.Borrego@Sun.COM }
12308670SJose.Borrego@Sun.COM
12318670SJose.Borrego@Sun.COM /*
12328670SJose.Borrego@Sun.COM * smb_odir_lookup_link
12338670SJose.Borrego@Sun.COM *
12348670SJose.Borrego@Sun.COM * If the file is a symlink we lookup the object to which the
12358670SJose.Borrego@Sun.COM * symlink refers so that we can return its attributes.
12368670SJose.Borrego@Sun.COM * This can cause a problem if a symlink in a sub-directory
12378670SJose.Borrego@Sun.COM * points to a parent directory (some UNIX GUI's create a symlink
12388670SJose.Borrego@Sun.COM * in $HOME/.desktop that points to the user's home directory).
12398670SJose.Borrego@Sun.COM * Some Windows applications (e.g. virus scanning) loop/hang
12408670SJose.Borrego@Sun.COM * trying to follow this recursive path and there is little
12418670SJose.Borrego@Sun.COM * we can do because the path is constructed on the client.
12428670SJose.Borrego@Sun.COM * smb_dirsymlink_enable allows an end-user to disable
12438670SJose.Borrego@Sun.COM * symlinks to directories. Symlinks to other object types
12448670SJose.Borrego@Sun.COM * should be unaffected.
12458670SJose.Borrego@Sun.COM *
124612508Samw@Sun.COM * Returns: B_TRUE - followed link. tgt_node and tgt_attr set
12478670SJose.Borrego@Sun.COM * B_FALSE - link not followed
12488670SJose.Borrego@Sun.COM */
12498670SJose.Borrego@Sun.COM static boolean_t
smb_odir_lookup_link(smb_request_t * sr,smb_odir_t * od,char * fname,smb_node_t ** tgt_node)12508670SJose.Borrego@Sun.COM smb_odir_lookup_link(smb_request_t *sr, smb_odir_t *od,
125110001SJoyce.McIntosh@Sun.COM char *fname, smb_node_t **tgt_node)
12528670SJose.Borrego@Sun.COM {
12538670SJose.Borrego@Sun.COM int rc;
125412508Samw@Sun.COM uint32_t flags = SMB_FOLLOW_LINKS | SMB_CASE_SENSITIVE;
12558670SJose.Borrego@Sun.COM
125612508Samw@Sun.COM rc = smb_fsop_lookup(sr, od->d_cred, flags,
125710001SJoyce.McIntosh@Sun.COM od->d_tree->t_snode, od->d_dnode, fname, tgt_node);
12588670SJose.Borrego@Sun.COM if (rc != 0) {
12598670SJose.Borrego@Sun.COM *tgt_node = NULL;
12608670SJose.Borrego@Sun.COM return (B_FALSE);
12618670SJose.Borrego@Sun.COM }
12628670SJose.Borrego@Sun.COM
126310001SJoyce.McIntosh@Sun.COM if (smb_node_is_dir(*tgt_node) && (!smb_dirsymlink_enable)) {
12648670SJose.Borrego@Sun.COM smb_node_release(*tgt_node);
12658670SJose.Borrego@Sun.COM *tgt_node = NULL;
12668670SJose.Borrego@Sun.COM return (B_FALSE);
12678670SJose.Borrego@Sun.COM }
12688670SJose.Borrego@Sun.COM
12698670SJose.Borrego@Sun.COM return (B_TRUE);
12708670SJose.Borrego@Sun.COM }
1271*12890SJoyce.McIntosh@Sun.COM
1272*12890SJoyce.McIntosh@Sun.COM /*
1273*12890SJoyce.McIntosh@Sun.COM * smb_odir_match_name
1274*12890SJoyce.McIntosh@Sun.COM *
1275*12890SJoyce.McIntosh@Sun.COM * Check if the directory entry name matches the search pattern:
1276*12890SJoyce.McIntosh@Sun.COM * - Don't match reserved dos filenames.
1277*12890SJoyce.McIntosh@Sun.COM * - Check if odirent->od_name matches od->d_pattern.
1278*12890SJoyce.McIntosh@Sun.COM * - If shortnames are supported, generate the shortname from
1279*12890SJoyce.McIntosh@Sun.COM * odirent->od_name and check if it matches od->d_pattern.
1280*12890SJoyce.McIntosh@Sun.COM */
1281*12890SJoyce.McIntosh@Sun.COM boolean_t
smb_odir_match_name(smb_odir_t * od,smb_odirent_t * odirent)1282*12890SJoyce.McIntosh@Sun.COM smb_odir_match_name(smb_odir_t *od, smb_odirent_t *odirent)
1283*12890SJoyce.McIntosh@Sun.COM {
1284*12890SJoyce.McIntosh@Sun.COM char *name = odirent->od_name;
1285*12890SJoyce.McIntosh@Sun.COM char shortname[SMB_SHORTNAMELEN];
1286*12890SJoyce.McIntosh@Sun.COM ino64_t ino = odirent->od_ino;
1287*12890SJoyce.McIntosh@Sun.COM
1288*12890SJoyce.McIntosh@Sun.COM if (smb_is_reserved_dos_name(name))
1289*12890SJoyce.McIntosh@Sun.COM return (B_FALSE);
1290*12890SJoyce.McIntosh@Sun.COM
1291*12890SJoyce.McIntosh@Sun.COM if (smb_match_ci(od->d_pattern, name))
1292*12890SJoyce.McIntosh@Sun.COM return (B_TRUE);
1293*12890SJoyce.McIntosh@Sun.COM
1294*12890SJoyce.McIntosh@Sun.COM if (od->d_flags & SMB_ODIR_FLAG_SHORTNAMES) {
1295*12890SJoyce.McIntosh@Sun.COM smb_mangle(name, ino, shortname, SMB_SHORTNAMELEN);
1296*12890SJoyce.McIntosh@Sun.COM if (smb_match_ci(od->d_pattern, shortname))
1297*12890SJoyce.McIntosh@Sun.COM return (B_TRUE);
1298*12890SJoyce.McIntosh@Sun.COM }
1299*12890SJoyce.McIntosh@Sun.COM
1300*12890SJoyce.McIntosh@Sun.COM return (B_FALSE);
1301*12890SJoyce.McIntosh@Sun.COM }
1302