1da6c28aaSamw /* 2da6c28aaSamw * CDDL HEADER START 3da6c28aaSamw * 4da6c28aaSamw * The contents of this file are subject to the terms of the 5da6c28aaSamw * Common Development and Distribution License (the "License"). 6da6c28aaSamw * You may not use this file except in compliance with the License. 7da6c28aaSamw * 8da6c28aaSamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9da6c28aaSamw * or http://www.opensolaris.org/os/licensing. 10da6c28aaSamw * See the License for the specific language governing permissions 11da6c28aaSamw * and limitations under the License. 12da6c28aaSamw * 13da6c28aaSamw * When distributing Covered Code, include this CDDL HEADER in each 14da6c28aaSamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15da6c28aaSamw * If applicable, add the following below this CDDL HEADER, with the 16da6c28aaSamw * fields enclosed by brackets "[]" replaced with your own identifying 17da6c28aaSamw * information: Portions Copyright [yyyy] [name of copyright owner] 18da6c28aaSamw * 19da6c28aaSamw * CDDL HEADER END 20da6c28aaSamw */ 21da6c28aaSamw /* 22*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23da6c28aaSamw * Use is subject to license terms. 24da6c28aaSamw */ 25da6c28aaSamw 26da6c28aaSamw /* 27da6c28aaSamw * General Structures Layout 28da6c28aaSamw * ------------------------- 29da6c28aaSamw * 30da6c28aaSamw * This is a simplified diagram showing the relationship between most of the 31da6c28aaSamw * main structures. 32da6c28aaSamw * 33da6c28aaSamw * +-------------------+ 34da6c28aaSamw * | SMB_INFO | 35da6c28aaSamw * +-------------------+ 36da6c28aaSamw * | 37da6c28aaSamw * | 38da6c28aaSamw * v 39da6c28aaSamw * +-------------------+ +-------------------+ +-------------------+ 40da6c28aaSamw * | SESSION |<----->| SESSION |......| SESSION | 41da6c28aaSamw * +-------------------+ +-------------------+ +-------------------+ 42da6c28aaSamw * | 43da6c28aaSamw * | 44da6c28aaSamw * v 45da6c28aaSamw * +-------------------+ +-------------------+ +-------------------+ 46da6c28aaSamw * | USER |<----->| USER |......| USER | 47da6c28aaSamw * +-------------------+ +-------------------+ +-------------------+ 48da6c28aaSamw * | 49da6c28aaSamw * | 50da6c28aaSamw * v 51da6c28aaSamw * +-------------------+ +-------------------+ +-------------------+ 52da6c28aaSamw * | TREE |<----->| TREE |......| TREE | 53da6c28aaSamw * +-------------------+ +-------------------+ +-------------------+ 54da6c28aaSamw * | | 55da6c28aaSamw * | | 56da6c28aaSamw * | v 57da6c28aaSamw * | +-------+ +-------+ +-------+ 58da6c28aaSamw * | | OFILE |<----->| OFILE |......| OFILE | 59da6c28aaSamw * | +-------+ +-------+ +-------+ 60da6c28aaSamw * | 61da6c28aaSamw * | 62da6c28aaSamw * v 63da6c28aaSamw * +-------+ +------+ +------+ 64da6c28aaSamw * | ODIR |<----->| ODIR |......| ODIR | 65da6c28aaSamw * +-------+ +------+ +------+ 66da6c28aaSamw * 67da6c28aaSamw * 68da6c28aaSamw * Odir State Machine 69da6c28aaSamw * ------------------ 70da6c28aaSamw * 717f667e74Sjose borrego * +-------------------------+ 727f667e74Sjose borrego * | SMB_ODIR_STATE_OPEN |<----------- open / creation 73da6c28aaSamw * +-------------------------+ 74a1511e6bSjoyce mcintosh * | ^ 75a1511e6bSjoyce mcintosh * | (first) | (last) 76a1511e6bSjoyce mcintosh * | lookup | release 77a1511e6bSjoyce mcintosh * v | 78a1511e6bSjoyce mcintosh * +-------------------------+ 79a1511e6bSjoyce mcintosh * | SMB_ODIR_STATE_IN_USE |---- 80a1511e6bSjoyce mcintosh * +-------------------------+ | lookup / release / read 81a1511e6bSjoyce mcintosh * | ^------- 827f667e74Sjose borrego * | close 83da6c28aaSamw * | 84da6c28aaSamw * v 85da6c28aaSamw * +-------------------------+ 86a1511e6bSjoyce mcintosh * | SMB_ODIR_STATE_CLOSING |---- 87a1511e6bSjoyce mcintosh * +-------------------------+ | close / release / read 88a1511e6bSjoyce mcintosh * | ^------- 89a1511e6bSjoyce mcintosh * | (last) release 90da6c28aaSamw * | 91da6c28aaSamw * v 927f667e74Sjose borrego * +-------------------------+ 937f667e74Sjose borrego * | SMB_ODIR_STATE_CLOSED |----------> deletion 94da6c28aaSamw * +-------------------------+ 95da6c28aaSamw * 96da6c28aaSamw * 977f667e74Sjose borrego * SMB_ODIR_STATE_OPEN 98a1511e6bSjoyce mcintosh * - the odir exists in the list of odirs of its tree 99a1511e6bSjoyce mcintosh * - lookup is valid in this state. It will place a hold on the odir 100a1511e6bSjoyce mcintosh * by incrementing the reference count and the odir will transition 101a1511e6bSjoyce mcintosh * to SMB_ODIR_STATE_IN_USE 102a1511e6bSjoyce mcintosh * - read/close/release not valid in this state 103a1511e6bSjoyce mcintosh * 104a1511e6bSjoyce mcintosh * SMB_ODIR_STATE_IN_USE 1057f667e74Sjose borrego * - the odir exists in the list of odirs of its tree. 106a1511e6bSjoyce mcintosh * - lookup is valid in this state. It will place a hold on the odir 107a1511e6bSjoyce mcintosh * by incrementing the reference count. 108a1511e6bSjoyce mcintosh * - if the last hold is released the odir will transition 109a1511e6bSjoyce mcintosh * back to SMB_ODIR_STATE_OPEN 1107f667e74Sjose borrego * - if a close is received the odir will transition to 1117f667e74Sjose borrego * SMB_ODIR_STATE_CLOSING. 112da6c28aaSamw * 113da6c28aaSamw * SMB_ODIR_STATE_CLOSING 1147f667e74Sjose borrego * - the odir exists in the list of odirs of its tree. 115a1511e6bSjoyce mcintosh * - lookup will fail in this state. 116a1511e6bSjoyce mcintosh * - when the last hold is released the odir will transition 117a1511e6bSjoyce mcintosh * to SMB_ODIR_STATE_CLOSED. 118da6c28aaSamw * 119da6c28aaSamw * SMB_ODIR_STATE_CLOSED 1207f667e74Sjose borrego * - the odir exists in the list of odirs of its tree. 1217f667e74Sjose borrego * - there are no users of the odir (refcnt == 0) 1227f667e74Sjose borrego * - the odir is being removed from the tree's list and deleted. 123a1511e6bSjoyce mcintosh * - lookup will fail in this state. 124a1511e6bSjoyce mcintosh * - read/close/release not valid in this state 125da6c28aaSamw * 126da6c28aaSamw * Comments 127da6c28aaSamw * -------- 128da6c28aaSamw * The state machine of the odir structures is controlled by 3 elements: 129da6c28aaSamw * - The list of odirs of the tree it belongs to. 130da6c28aaSamw * - The mutex embedded in the structure itself. 131da6c28aaSamw * - The reference count. 132da6c28aaSamw * 133da6c28aaSamw * There's a mutex embedded in the odir structure used to protect its fields 134da6c28aaSamw * and there's a lock embedded in the list of odirs of a tree. To 135da6c28aaSamw * increment or to decrement the reference count the mutex must be entered. 136da6c28aaSamw * To insert the odir into the list of odirs of the tree and to remove 137da6c28aaSamw * the odir from it, the lock must be entered in RW_WRITER mode. 138da6c28aaSamw * 1397f667e74Sjose borrego * In order to avoid deadlocks, when both (mutex and lock of the odir 140da6c28aaSamw * list) have to be entered, the lock must be entered first. 141da6c28aaSamw * 142da6c28aaSamw * 1437f667e74Sjose borrego * Odir Interface 1447f667e74Sjose borrego * --------------- 1457f667e74Sjose borrego * odid = smb_odir_open(pathname) 1467f667e74Sjose borrego * Create an odir representing the directory specified in pathname and 1477f667e74Sjose borrego * add it into the tree's list of odirs. 1487f667e74Sjose borrego * Return an identifier (odid) uniquely identifying the created odir. 149da6c28aaSamw * 1507f667e74Sjose borrego * smb_odir_openat(smb_node_t *unode) 1517f667e74Sjose borrego * Create an odir representing the extended attribute directory 1527f667e74Sjose borrego * associated with the file (or directory) represented by unode 1537f667e74Sjose borrego * and add it into the tree's list of odirs. 1547f667e74Sjose borrego * Return an identifier (odid) uniquely identifying the created odir. 155da6c28aaSamw * 1567f667e74Sjose borrego * smb_odir_t *odir = smb_tree_lookup_odir(odid) 1577f667e74Sjose borrego * Find the odir corresponding to the specified odid in the tree's 158a1511e6bSjoyce mcintosh * list of odirs. Place a hold on the odir. 159da6c28aaSamw * 1607f667e74Sjose borrego * smb_odir_read(..., smb_odirent_t *odirent) 1617f667e74Sjose borrego * Find the next directory entry in the odir and return it in odirent. 1627f667e74Sjose borrego * 1637f667e74Sjose borrego * smb_odir_read_fileinfo(..., smb_fileinfo_t *) 1647f667e74Sjose borrego * Find the next directory entry in the odir. Return the details of 1657f667e74Sjose borrego * the directory entry in smb_fileinfo_t. (See odir internals below) 1667f667e74Sjose borrego * 167037cac00Sjoyce mcintosh * smb_odir_read_streaminfo(..., smb_streaminfo_t *) 1687f667e74Sjose borrego * Find the next named stream entry in the odir. Return the details of 1697f667e74Sjose borrego * the named stream in smb_streaminfo_t. 1707f667e74Sjose borrego * 171a1511e6bSjoyce mcintosh * smb_odir_close(smb_odir_t *odir) 172a1511e6bSjoyce mcintosh * Close the odir. 173a1511e6bSjoyce mcintosh * The caller of close must have a hold on the odir being closed. 174a1511e6bSjoyce mcintosh * The hold should be released after closing. 175a1511e6bSjoyce mcintosh * 1767f667e74Sjose borrego * smb_odir_release(smb_odir_t *odir) 1777f667e74Sjose borrego * Release the hold on the odir, obtained by lookup. 1787f667e74Sjose borrego * 1797f667e74Sjose borrego * 1807f667e74Sjose borrego * Odir Internals 1817f667e74Sjose borrego * -------------- 1827f667e74Sjose borrego * The odir object represent an open directory search. Each read operation 1837f667e74Sjose borrego * provides the caller with a structure containing information pertaining 1847f667e74Sjose borrego * to the next directory entry that matches the search criteria, namely 1857f667e74Sjose borrego * the filename or match pattern and, in the case of smb_odir_read_fileinfo(), 1867f667e74Sjose borrego * the search attributes. 1877f667e74Sjose borrego * 1887f667e74Sjose borrego * The odir maintains a buffer (d_buf) of directory entries read from 1897f667e74Sjose borrego * the filesystem via a vop_readdir. The buffer is populated when a read 1907f667e74Sjose borrego * request (smb_odir_next_odirent) finds that the buffer is empty or that 1917f667e74Sjose borrego * the end of the buffer has been reached, and also when a new client request 1927f667e74Sjose borrego * (find next) begins. 1937f667e74Sjose borrego * 1947f667e74Sjose borrego * The data in d_buf (that which is returned from the file system) can 1957f667e74Sjose borrego * be in one of two formats. If the file system supports extended directory 1967f667e74Sjose borrego * entries we request that the data be returned as edirent_t structures. If 1977f667e74Sjose borrego * it does not the data will be returned as dirent64_t structures. For 1987f667e74Sjose borrego * convenience, when the next directory entry is read from d_buf by 1997f667e74Sjose borrego * smb_odir_next_odirent it is translated into an smb_odirent_t. 2007f667e74Sjose borrego * 2017f667e74Sjose borrego * smb_odir_read_fileinfo 2027f667e74Sjose borrego * The processing required to obtain the information to populate the caller's 2037f667e74Sjose borrego * smb_fileinfo_t differs depending upon whether the directory search is for a 2047f667e74Sjose borrego * single specified filename or for multiple files matching a search pattern. 2057f667e74Sjose borrego * Thus smb_odir_read_fileinfo uses two static functions: 2067f667e74Sjose borrego * smb_odir_single_fileinfo - obtains the smb_fileinfo_t info for the single 2077f667e74Sjose borrego * filename as specified in smb_odir_open request. 2087f667e74Sjose borrego * smb_odir_wildcard_fileinfo - obtains the smb_fileinfo_t info for the filename 2097f667e74Sjose borrego * returned from the smb_odir_next_odirent. This is called in a loop until 2107f667e74Sjose borrego * an entry matching the search criteria is found or no more entries exist. 2117f667e74Sjose borrego * 2127f667e74Sjose borrego * If a directory entry is a VLNK, the name returned in the smb_fileinfo_t 2137f667e74Sjose borrego * is the name of the directory entry but the attributes are the attribites 2147f667e74Sjose borrego * of the file that is the target of the link. If the link target cannot 2157f667e74Sjose borrego * be found the attributes returned are the attributes of the link itself. 2167f667e74Sjose borrego * 217037cac00Sjoyce mcintosh * smb_odir_read_streaminfo 2187f667e74Sjose borrego * In order for an odir to provide information about stream files it 2197f667e74Sjose borrego * must be opened with smb_odir_openat(). smb_odir_read_streaminfo() can 2207f667e74Sjose borrego * then be used to obtain the name and size of named stream files. 2217f667e74Sjose borrego * 2227f667e74Sjose borrego * Resuming a Search 2237f667e74Sjose borrego * ----------------- 2247f667e74Sjose borrego * A directory search often consists of multiple client requests: an initial 2257f667e74Sjose borrego * find_first request followed by zero or more find_next requests and a 2267f667e74Sjose borrego * find_close request. 2277f667e74Sjose borrego * The find_first request will open and lookup the odir, read its desired 2287f667e74Sjose borrego * number of entries from the odir, then release the odir and return. 2297f667e74Sjose borrego * A find_next request will lookup the odir and read its desired number of 2307f667e74Sjose borrego * entries from the odir, then release the odir and return. 2317f667e74Sjose borrego * At the end of the search the find_close request will close the odir. 2327f667e74Sjose borrego * 2337f667e74Sjose borrego * In order to be able to resume a directory search (find_next) the odir 2347f667e74Sjose borrego * provides the capability for the caller to save one or more resume points 2357f667e74Sjose borrego * (cookies) at the end of a request, and to specify which resume point 2367f667e74Sjose borrego * (cookie) to restart from at the beginning of the next search. 2377f667e74Sjose borrego * smb_odir_save_cookie(..., cookie) 2387f667e74Sjose borrego * smb_odir_resume_at(smb_odir_resume_t *resume) 2397f667e74Sjose borrego * A search can be resumed at a specified resume point (cookie), the resume 2407f667e74Sjose borrego * point (cookie) stored at a specified index in the d_cookies array, or 2417f667e74Sjose borrego * a specified filename. The latter (specified filename) is not yet supported. 2427f667e74Sjose borrego * 2437f667e74Sjose borrego * See smb_search, smb_find, smb_find_unique, and smb_trans2_find for details 244da6c28aaSamw */ 2457f667e74Sjose borrego 246da6c28aaSamw #include <smbsrv/smb_kproto.h> 247da6c28aaSamw #include <smbsrv/smb_fsops.h> 248e3f2c991SKeyur Desai #include <smbsrv/smb_share.h> 2497f667e74Sjose borrego #include <sys/extdirent.h> 250da6c28aaSamw 2517f667e74Sjose borrego /* static functions */ 2527f667e74Sjose borrego static smb_odir_t *smb_odir_create(smb_request_t *, smb_node_t *, 253eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States char *, uint16_t, cred_t *); 2547f667e74Sjose borrego static int smb_odir_single_fileinfo(smb_request_t *, smb_odir_t *, 2557f667e74Sjose borrego smb_fileinfo_t *); 2567f667e74Sjose borrego static int smb_odir_wildcard_fileinfo(smb_request_t *, smb_odir_t *, 2577f667e74Sjose borrego smb_odirent_t *, smb_fileinfo_t *); 2587f667e74Sjose borrego static int smb_odir_next_odirent(smb_odir_t *, smb_odirent_t *); 259037cac00Sjoyce mcintosh static boolean_t smb_odir_lookup_link(smb_request_t *, smb_odir_t *, 260037cac00Sjoyce mcintosh char *, smb_node_t **); 261da6c28aaSamw 262da6c28aaSamw 263da6c28aaSamw /* 264da6c28aaSamw * smb_odir_open 2657f667e74Sjose borrego * 2667f667e74Sjose borrego * Create an odir representing the directory specified in pathname. 2677f667e74Sjose borrego * 2687f667e74Sjose borrego * Returns: 2697f667e74Sjose borrego * odid - Unique identifier of newly created odir. 2707f667e74Sjose borrego * 0 - error, error details set in sr. 271da6c28aaSamw */ 2727f667e74Sjose borrego uint16_t 273eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States smb_odir_open(smb_request_t *sr, char *path, uint16_t sattr, uint32_t flags) 274da6c28aaSamw { 2757f667e74Sjose borrego int rc; 2767f667e74Sjose borrego smb_tree_t *tree; 2777f667e74Sjose borrego smb_node_t *dnode; 2787f667e74Sjose borrego char pattern[MAXNAMELEN]; 2797f667e74Sjose borrego smb_odir_t *od; 280eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States cred_t *cr; 281da6c28aaSamw 2827f667e74Sjose borrego ASSERT(sr); 2837f667e74Sjose borrego ASSERT(sr->sr_magic == SMB_REQ_MAGIC); 2847f667e74Sjose borrego ASSERT(sr->tid_tree); 2857f667e74Sjose borrego ASSERT(sr->tid_tree->t_magic == SMB_TREE_MAGIC); 286da6c28aaSamw 2877f667e74Sjose borrego tree = sr->tid_tree; 2887f667e74Sjose borrego 289fe1c642dSBill Krier smb_convert_wildcards(path); 290fe1c642dSBill Krier 2917f667e74Sjose borrego rc = smb_pathname_reduce(sr, sr->user_cr, path, 2927f667e74Sjose borrego tree->t_snode, tree->t_snode, &dnode, pattern); 2937f667e74Sjose borrego if (rc != 0) { 2947f667e74Sjose borrego smbsr_errno(sr, rc); 2957f667e74Sjose borrego return (0); 296da6c28aaSamw } 297da6c28aaSamw 298*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (!smb_node_is_dir(dnode)) { 2997f667e74Sjose borrego smbsr_error(sr, NT_STATUS_OBJECT_PATH_NOT_FOUND, 3007f667e74Sjose borrego ERRDOS, ERROR_PATH_NOT_FOUND); 3017f667e74Sjose borrego smb_node_release(dnode); 3027f667e74Sjose borrego return (0); 303da6c28aaSamw } 304da6c28aaSamw 3057f667e74Sjose borrego if (smb_fsop_access(sr, sr->user_cr, dnode, FILE_LIST_DIRECTORY) != 0) { 3067f667e74Sjose borrego smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 3077f667e74Sjose borrego ERRDOS, ERROR_ACCESS_DENIED); 3087f667e74Sjose borrego smb_node_release(dnode); 3097f667e74Sjose borrego return (0); 3107f667e74Sjose borrego } 311da6c28aaSamw 312eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States if (flags & SMB_ODIR_OPENF_BACKUP_INTENT) 313eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States cr = smb_user_getprivcred(tree->t_user); 314eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States else 315eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States cr = tree->t_user->u_cred; 316eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 317eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States od = smb_odir_create(sr, dnode, pattern, sattr, cr); 3187f667e74Sjose borrego smb_node_release(dnode); 3197f667e74Sjose borrego return (od ? od->d_odid : 0); 3207f667e74Sjose borrego } 3217f667e74Sjose borrego 3227f667e74Sjose borrego /* 3237f667e74Sjose borrego * smb_odir_openat 3247f667e74Sjose borrego * 3257f667e74Sjose borrego * Create an odir representing the extended attribute directory 3267f667e74Sjose borrego * associated with the file (or directory) represented by unode. 3277f667e74Sjose borrego * 3287f667e74Sjose borrego * Returns: 3297f667e74Sjose borrego * odid - Unique identifier of newly created odir. 3307f667e74Sjose borrego * 0 - error, error details set in sr. 3317f667e74Sjose borrego */ 3327f667e74Sjose borrego uint16_t 3337f667e74Sjose borrego smb_odir_openat(smb_request_t *sr, smb_node_t *unode) 3347f667e74Sjose borrego { 3357f667e74Sjose borrego int rc; 3367f667e74Sjose borrego vnode_t *xattr_dvp; 3377f667e74Sjose borrego smb_odir_t *od; 3387f667e74Sjose borrego cred_t *cr; 3397f667e74Sjose borrego char pattern[SMB_STREAM_PREFIX_LEN + 2]; 3407f667e74Sjose borrego 3417f667e74Sjose borrego smb_node_t *xattr_dnode; 3427f667e74Sjose borrego 3437f667e74Sjose borrego ASSERT(sr); 3447f667e74Sjose borrego ASSERT(sr->sr_magic == SMB_REQ_MAGIC); 3457f667e74Sjose borrego ASSERT(unode); 3467f667e74Sjose borrego ASSERT(unode->n_magic == SMB_NODE_MAGIC); 3477f667e74Sjose borrego 348743a77edSAlan Wright if (SMB_TREE_CONTAINS_NODE(sr, unode) == 0 || 349743a77edSAlan Wright SMB_TREE_HAS_ACCESS(sr, ACE_LIST_DIRECTORY) == 0) { 3507f667e74Sjose borrego smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 3517f667e74Sjose borrego ERRDOS, ERROR_ACCESS_DENIED); 3527f667e74Sjose borrego return (0); 3537f667e74Sjose borrego } 354eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States cr = kcred; 3557f667e74Sjose borrego 3567f667e74Sjose borrego /* find the xattrdir vnode */ 3577f667e74Sjose borrego rc = smb_vop_lookup_xattrdir(unode->vp, &xattr_dvp, LOOKUP_XATTR, cr); 3587f667e74Sjose borrego if (rc != 0) { 3597f667e74Sjose borrego smbsr_errno(sr, rc); 3607f667e74Sjose borrego return (0); 3617f667e74Sjose borrego } 3627f667e74Sjose borrego 3637f667e74Sjose borrego /* lookup the xattrdir's smb_node */ 3647f667e74Sjose borrego xattr_dnode = smb_node_lookup(sr, NULL, cr, xattr_dvp, XATTR_DIR, 365037cac00Sjoyce mcintosh unode, NULL); 3667f667e74Sjose borrego VN_RELE(xattr_dvp); 3677f667e74Sjose borrego if (xattr_dnode == NULL) { 3687f667e74Sjose borrego smbsr_error(sr, NT_STATUS_NO_MEMORY, 3697f667e74Sjose borrego ERRDOS, ERROR_NOT_ENOUGH_MEMORY); 3707f667e74Sjose borrego return (0); 3717f667e74Sjose borrego } 3727f667e74Sjose borrego 3737f667e74Sjose borrego (void) snprintf(pattern, sizeof (pattern), "%s*", SMB_STREAM_PREFIX); 374eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States od = smb_odir_create(sr, xattr_dnode, pattern, SMB_SEARCH_ATTRIBUTES, 375eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States cr); 3767f667e74Sjose borrego smb_node_release(xattr_dnode); 3777f667e74Sjose borrego if (od == NULL) 3787f667e74Sjose borrego return (0); 3797f667e74Sjose borrego 3808b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States od->d_flags |= SMB_ODIR_FLAG_XATTR; 3817f667e74Sjose borrego return (od->d_odid); 3827f667e74Sjose borrego } 3837f667e74Sjose borrego 3847f667e74Sjose borrego /* 3857f667e74Sjose borrego * smb_odir_hold 386a1511e6bSjoyce mcintosh * 387a1511e6bSjoyce mcintosh * A hold will only be granted if the odir is open or in_use. 3887f667e74Sjose borrego */ 3897f667e74Sjose borrego boolean_t 3907f667e74Sjose borrego smb_odir_hold(smb_odir_t *od) 3917f667e74Sjose borrego { 3927f667e74Sjose borrego ASSERT(od); 3937f667e74Sjose borrego ASSERT(od->d_magic == SMB_ODIR_MAGIC); 3947f667e74Sjose borrego 3957f667e74Sjose borrego mutex_enter(&od->d_mutex); 396a1511e6bSjoyce mcintosh 397a1511e6bSjoyce mcintosh switch (od->d_state) { 398a1511e6bSjoyce mcintosh case SMB_ODIR_STATE_OPEN: 399a1511e6bSjoyce mcintosh od->d_refcnt++; 400a1511e6bSjoyce mcintosh od->d_state = SMB_ODIR_STATE_IN_USE; 401a1511e6bSjoyce mcintosh break; 402a1511e6bSjoyce mcintosh case SMB_ODIR_STATE_IN_USE: 403a1511e6bSjoyce mcintosh od->d_refcnt++; 404a1511e6bSjoyce mcintosh break; 405a1511e6bSjoyce mcintosh case SMB_ODIR_STATE_CLOSING: 406a1511e6bSjoyce mcintosh case SMB_ODIR_STATE_CLOSED: 407a1511e6bSjoyce mcintosh default: 4087f667e74Sjose borrego mutex_exit(&od->d_mutex); 4097f667e74Sjose borrego return (B_FALSE); 4107f667e74Sjose borrego } 4117f667e74Sjose borrego 4127f667e74Sjose borrego mutex_exit(&od->d_mutex); 4137f667e74Sjose borrego return (B_TRUE); 4147f667e74Sjose borrego } 4157f667e74Sjose borrego 4167f667e74Sjose borrego /* 417*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * If the odir is in SMB_ODIR_STATE_CLOSING and this release results in 418*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * a refcnt of 0, change the state to SMB_ODIR_STATE_CLOSED and post the 419*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * object for deletion. Object deletion is deferred to avoid modifying 420*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * a list while an iteration may be in progress. 4217f667e74Sjose borrego */ 4227f667e74Sjose borrego void 4237f667e74Sjose borrego smb_odir_release(smb_odir_t *od) 4247f667e74Sjose borrego { 425*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_ODIR_VALID(od); 4267f667e74Sjose borrego 4277f667e74Sjose borrego mutex_enter(&od->d_mutex); 428a1511e6bSjoyce mcintosh ASSERT(od->d_refcnt > 0); 4297f667e74Sjose borrego 4307f667e74Sjose borrego switch (od->d_state) { 4317f667e74Sjose borrego case SMB_ODIR_STATE_OPEN: 432a1511e6bSjoyce mcintosh break; 433a1511e6bSjoyce mcintosh case SMB_ODIR_STATE_IN_USE: 4347f667e74Sjose borrego od->d_refcnt--; 435a1511e6bSjoyce mcintosh if (od->d_refcnt == 0) 436a1511e6bSjoyce mcintosh od->d_state = SMB_ODIR_STATE_OPEN; 4377f667e74Sjose borrego break; 4387f667e74Sjose borrego case SMB_ODIR_STATE_CLOSING: 4397f667e74Sjose borrego od->d_refcnt--; 4407f667e74Sjose borrego if (od->d_refcnt == 0) { 4417f667e74Sjose borrego od->d_state = SMB_ODIR_STATE_CLOSED; 442*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_tree_post_odir(od->d_tree, od); 4437f667e74Sjose borrego } 4447f667e74Sjose borrego break; 4457f667e74Sjose borrego case SMB_ODIR_STATE_CLOSED: 4467f667e74Sjose borrego default: 4477f667e74Sjose borrego break; 4487f667e74Sjose borrego } 4497f667e74Sjose borrego 4507f667e74Sjose borrego mutex_exit(&od->d_mutex); 451da6c28aaSamw } 452da6c28aaSamw 453da6c28aaSamw /* 454da6c28aaSamw * smb_odir_close 455da6c28aaSamw */ 456da6c28aaSamw void 4577f667e74Sjose borrego smb_odir_close(smb_odir_t *od) 458da6c28aaSamw { 459da6c28aaSamw ASSERT(od); 460a1511e6bSjoyce mcintosh ASSERT(od->d_magic == SMB_ODIR_MAGIC); 461da6c28aaSamw 462da6c28aaSamw mutex_enter(&od->d_mutex); 463a1511e6bSjoyce mcintosh ASSERT(od->d_refcnt > 0); 464a1511e6bSjoyce mcintosh switch (od->d_state) { 465a1511e6bSjoyce mcintosh case SMB_ODIR_STATE_OPEN: 466a1511e6bSjoyce mcintosh break; 467a1511e6bSjoyce mcintosh case SMB_ODIR_STATE_IN_USE: 4687f667e74Sjose borrego od->d_state = SMB_ODIR_STATE_CLOSING; 469a1511e6bSjoyce mcintosh break; 470a1511e6bSjoyce mcintosh case SMB_ODIR_STATE_CLOSING: 471a1511e6bSjoyce mcintosh case SMB_ODIR_STATE_CLOSED: 472a1511e6bSjoyce mcintosh default: 473a1511e6bSjoyce mcintosh break; 474a1511e6bSjoyce mcintosh } 475da6c28aaSamw mutex_exit(&od->d_mutex); 4767f667e74Sjose borrego } 477da6c28aaSamw 478da6c28aaSamw /* 4797f667e74Sjose borrego * smb_odir_read 480da6c28aaSamw * 4817f667e74Sjose borrego * Find the next directory entry matching the search pattern. 4827f667e74Sjose borrego * No search attribute matching is performed. 4837f667e74Sjose borrego * 4847f667e74Sjose borrego * Returns: 4857f667e74Sjose borrego * 0 - success. 4867f667e74Sjose borrego * - If a matching entry was found eof will be B_FALSE and 4877f667e74Sjose borrego * odirent will be populated. 4887f667e74Sjose borrego * - If there are no matching entries eof will be B_TRUE. 4897f667e74Sjose borrego * -1 - error, error details set in sr. 490da6c28aaSamw */ 4917f667e74Sjose borrego int 4927f667e74Sjose borrego smb_odir_read(smb_request_t *sr, smb_odir_t *od, 4937f667e74Sjose borrego smb_odirent_t *odirent, boolean_t *eof) 494da6c28aaSamw { 4957f667e74Sjose borrego int rc; 4968b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States boolean_t ignore_case; 497da6c28aaSamw 4987f667e74Sjose borrego ASSERT(sr); 4997f667e74Sjose borrego ASSERT(sr->sr_magic == SMB_REQ_MAGIC); 500da6c28aaSamw ASSERT(od); 501da6c28aaSamw ASSERT(od->d_magic == SMB_ODIR_MAGIC); 5027f667e74Sjose borrego ASSERT(odirent); 503da6c28aaSamw 504da6c28aaSamw mutex_enter(&od->d_mutex); 505a1511e6bSjoyce mcintosh ASSERT(od->d_refcnt > 0); 5067f667e74Sjose borrego 507a1511e6bSjoyce mcintosh switch (od->d_state) { 508a1511e6bSjoyce mcintosh case SMB_ODIR_STATE_IN_USE: 509a1511e6bSjoyce mcintosh case SMB_ODIR_STATE_CLOSING: 510a1511e6bSjoyce mcintosh break; 511a1511e6bSjoyce mcintosh case SMB_ODIR_STATE_OPEN: 512a1511e6bSjoyce mcintosh case SMB_ODIR_STATE_CLOSED: 513a1511e6bSjoyce mcintosh default: 514da6c28aaSamw mutex_exit(&od->d_mutex); 5157f667e74Sjose borrego return (-1); 5167f667e74Sjose borrego } 5177f667e74Sjose borrego 5188b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States ignore_case = (od->d_flags & SMB_ODIR_FLAG_IGNORE_CASE); 5198b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 5207f667e74Sjose borrego for (;;) { 5217f667e74Sjose borrego if ((rc = smb_odir_next_odirent(od, odirent)) != 0) 522da6c28aaSamw break; 5237f667e74Sjose borrego if (smb_match_name(odirent->od_ino, odirent->od_name, 5248b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States od->d_pattern, ignore_case)) 525da6c28aaSamw break; 526da6c28aaSamw } 5277f667e74Sjose borrego 5287f667e74Sjose borrego mutex_exit(&od->d_mutex); 5297f667e74Sjose borrego 5307f667e74Sjose borrego switch (rc) { 5317f667e74Sjose borrego case 0: 5327f667e74Sjose borrego *eof = B_FALSE; 5337f667e74Sjose borrego return (0); 5347f667e74Sjose borrego case ENOENT: 5357f667e74Sjose borrego *eof = B_TRUE; 5367f667e74Sjose borrego return (0); 5377f667e74Sjose borrego default: 5387f667e74Sjose borrego smbsr_errno(sr, rc); 5397f667e74Sjose borrego return (-1); 5407f667e74Sjose borrego } 5417f667e74Sjose borrego } 5427f667e74Sjose borrego 5437f667e74Sjose borrego /* 5447f667e74Sjose borrego * smb_odir_read_fileinfo 5457f667e74Sjose borrego * 5467f667e74Sjose borrego * Find the next directory entry matching the search pattern 5477f667e74Sjose borrego * and attributes: od->d_pattern and od->d_sattr. 5487f667e74Sjose borrego * 5497f667e74Sjose borrego * If the search pattern specifies a single filename call 5507f667e74Sjose borrego * smb_odir_single_fileinfo to get the file attributes and 5517f667e74Sjose borrego * populate the caller's smb_fileinfo_t. 5527f667e74Sjose borrego * 5537f667e74Sjose borrego * If the search pattern contains wildcards call smb_odir_next_odirent 5547f667e74Sjose borrego * to get the next directory entry then. Repeat until a matching 5557f667e74Sjose borrego * filename is found. Call smb_odir_wildcard_fileinfo to get the 5567f667e74Sjose borrego * file attributes and populate the caller's smb_fileinfo_t. 5577f667e74Sjose borrego * This is repeated until a file matching the search criteria is found. 5587f667e74Sjose borrego * 5597f667e74Sjose borrego * Returns: 5607f667e74Sjose borrego * 0 - success. 5617f667e74Sjose borrego * - If a matching entry was found eof will be B_FALSE and 5627f667e74Sjose borrego * fileinfo will be populated. 5637f667e74Sjose borrego * - If there are no matching entries eof will be B_TRUE. 5647f667e74Sjose borrego * -1 - error, error details set in sr. 5657f667e74Sjose borrego */ 5667f667e74Sjose borrego int 5677f667e74Sjose borrego smb_odir_read_fileinfo(smb_request_t *sr, smb_odir_t *od, 5687f667e74Sjose borrego smb_fileinfo_t *fileinfo, boolean_t *eof) 5697f667e74Sjose borrego { 570bbf6f00cSJordan Brown int rc, errnum; 5717f667e74Sjose borrego smb_odirent_t *odirent; 5728b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States boolean_t ignore_case; 5737f667e74Sjose borrego 5747f667e74Sjose borrego ASSERT(sr); 5757f667e74Sjose borrego ASSERT(sr->sr_magic == SMB_REQ_MAGIC); 5767f667e74Sjose borrego ASSERT(od); 5777f667e74Sjose borrego ASSERT(od->d_magic == SMB_ODIR_MAGIC); 5787f667e74Sjose borrego ASSERT(fileinfo); 5797f667e74Sjose borrego 5807f667e74Sjose borrego mutex_enter(&od->d_mutex); 581a1511e6bSjoyce mcintosh ASSERT(od->d_refcnt > 0); 5827f667e74Sjose borrego 583a1511e6bSjoyce mcintosh switch (od->d_state) { 584a1511e6bSjoyce mcintosh case SMB_ODIR_STATE_IN_USE: 585a1511e6bSjoyce mcintosh case SMB_ODIR_STATE_CLOSING: 586a1511e6bSjoyce mcintosh break; 587a1511e6bSjoyce mcintosh case SMB_ODIR_STATE_OPEN: 588a1511e6bSjoyce mcintosh case SMB_ODIR_STATE_CLOSED: 589a1511e6bSjoyce mcintosh default: 5907f667e74Sjose borrego mutex_exit(&od->d_mutex); 5917f667e74Sjose borrego return (-1); 5927f667e74Sjose borrego } 5937f667e74Sjose borrego 5948b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States ignore_case = (od->d_flags & SMB_ODIR_FLAG_IGNORE_CASE); 5958b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 5968b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (!(od->d_flags & SMB_ODIR_FLAG_WILDCARDS)) { 5977f667e74Sjose borrego if (od->d_eof) 5987f667e74Sjose borrego rc = ENOENT; 5997f667e74Sjose borrego else 6007f667e74Sjose borrego rc = smb_odir_single_fileinfo(sr, od, fileinfo); 6017f667e74Sjose borrego od->d_eof = B_TRUE; 6027f667e74Sjose borrego } else { 6037f667e74Sjose borrego odirent = kmem_alloc(sizeof (smb_odirent_t), KM_SLEEP); 6047f667e74Sjose borrego for (;;) { 6057f667e74Sjose borrego bzero(fileinfo, sizeof (smb_fileinfo_t)); 6067f667e74Sjose borrego if ((rc = smb_odir_next_odirent(od, odirent)) != 0) 6077f667e74Sjose borrego break; 6087f667e74Sjose borrego 609bbf6f00cSJordan Brown /* skip non utf8 filename */ 610bbf6f00cSJordan Brown if (u8_validate(odirent->od_name, 611bbf6f00cSJordan Brown strlen(odirent->od_name), NULL, 612bbf6f00cSJordan Brown U8_VALIDATE_ENTIRE, &errnum) < 0) 613bbf6f00cSJordan Brown continue; 614bbf6f00cSJordan Brown 6157f667e74Sjose borrego if (!smb_match_name(odirent->od_ino, odirent->od_name, 6168b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States od->d_pattern, ignore_case)) 6177f667e74Sjose borrego continue; 6187f667e74Sjose borrego 6197f667e74Sjose borrego rc = smb_odir_wildcard_fileinfo(sr, od, odirent, 6207f667e74Sjose borrego fileinfo); 6217f667e74Sjose borrego if (rc == 0) 6227f667e74Sjose borrego break; 6237f667e74Sjose borrego } 6247f667e74Sjose borrego kmem_free(odirent, sizeof (smb_odirent_t)); 6257f667e74Sjose borrego } 6267f667e74Sjose borrego mutex_exit(&od->d_mutex); 6277f667e74Sjose borrego 6287f667e74Sjose borrego switch (rc) { 6297f667e74Sjose borrego case 0: 6307f667e74Sjose borrego *eof = B_FALSE; 6317f667e74Sjose borrego return (0); 6327f667e74Sjose borrego case ENOENT: 6337f667e74Sjose borrego *eof = B_TRUE; 6347f667e74Sjose borrego return (0); 6357f667e74Sjose borrego default: 6367f667e74Sjose borrego smbsr_errno(sr, rc); 6377f667e74Sjose borrego return (-1); 6387f667e74Sjose borrego } 6397f667e74Sjose borrego } 6407f667e74Sjose borrego 6417f667e74Sjose borrego 6427f667e74Sjose borrego /* 6437f667e74Sjose borrego * smb_odir_read_streaminfo 6447f667e74Sjose borrego * 6457f667e74Sjose borrego * Find the next directory entry whose name begins with SMB_STREAM_PREFIX, 6467f667e74Sjose borrego * and thus represents an NTFS named stream. 6477f667e74Sjose borrego * No search attribute matching is performed. 6488b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * No case conflict name mangling is required for NTFS named stream names. 6497f667e74Sjose borrego * 6507f667e74Sjose borrego * Returns: 6517f667e74Sjose borrego * 0 - success. 6527f667e74Sjose borrego * - If a matching entry was found eof will be B_FALSE and 6537f667e74Sjose borrego * sinfo will be populated. 6547f667e74Sjose borrego * - If there are no matching entries eof will be B_TRUE. 6557f667e74Sjose borrego * -1 - error, error details set in sr. 6567f667e74Sjose borrego */ 6577f667e74Sjose borrego int 6587f667e74Sjose borrego smb_odir_read_streaminfo(smb_request_t *sr, smb_odir_t *od, 6597f667e74Sjose borrego smb_streaminfo_t *sinfo, boolean_t *eof) 6607f667e74Sjose borrego { 6617f667e74Sjose borrego int rc; 6627f667e74Sjose borrego smb_odirent_t *odirent; 663e3f2c991SKeyur Desai smb_node_t *fnode; 6647f667e74Sjose borrego smb_attr_t attr; 6657f667e74Sjose borrego 6667f667e74Sjose borrego ASSERT(sr); 6677f667e74Sjose borrego ASSERT(sr->sr_magic == SMB_REQ_MAGIC); 6687f667e74Sjose borrego ASSERT(od); 6697f667e74Sjose borrego ASSERT(od->d_magic == SMB_ODIR_MAGIC); 6707f667e74Sjose borrego ASSERT(sinfo); 6717f667e74Sjose borrego 6727f667e74Sjose borrego mutex_enter(&od->d_mutex); 673a1511e6bSjoyce mcintosh ASSERT(od->d_refcnt > 0); 6747f667e74Sjose borrego 675a1511e6bSjoyce mcintosh switch (od->d_state) { 676a1511e6bSjoyce mcintosh case SMB_ODIR_STATE_IN_USE: 677a1511e6bSjoyce mcintosh case SMB_ODIR_STATE_CLOSING: 678a1511e6bSjoyce mcintosh break; 679a1511e6bSjoyce mcintosh case SMB_ODIR_STATE_OPEN: 680a1511e6bSjoyce mcintosh case SMB_ODIR_STATE_CLOSED: 681a1511e6bSjoyce mcintosh default: 6827f667e74Sjose borrego mutex_exit(&od->d_mutex); 6837f667e74Sjose borrego return (-1); 6847f667e74Sjose borrego } 6857f667e74Sjose borrego 6867f667e74Sjose borrego /* Check that odir represents an xattr directory */ 6878b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (!(od->d_flags & SMB_ODIR_FLAG_XATTR)) { 6887f667e74Sjose borrego *eof = B_TRUE; 6897f667e74Sjose borrego mutex_exit(&od->d_mutex); 6907f667e74Sjose borrego return (0); 6917f667e74Sjose borrego } 6927f667e74Sjose borrego 6937f667e74Sjose borrego odirent = kmem_alloc(sizeof (smb_odirent_t), KM_SLEEP); 6947f667e74Sjose borrego 6957f667e74Sjose borrego for (;;) { 6967f667e74Sjose borrego bzero(sinfo, sizeof (smb_streaminfo_t)); 6977f667e74Sjose borrego if ((rc = smb_odir_next_odirent(od, odirent)) != 0) 6987f667e74Sjose borrego break; 6997f667e74Sjose borrego 7007f667e74Sjose borrego if (strncmp(odirent->od_name, SMB_STREAM_PREFIX, 7017f667e74Sjose borrego SMB_STREAM_PREFIX_LEN)) { 7027f667e74Sjose borrego continue; 7037f667e74Sjose borrego } 7047f667e74Sjose borrego 705e3f2c991SKeyur Desai rc = smb_fsop_lookup(sr, od->d_cred, 0, od->d_tree->t_snode, 706e3f2c991SKeyur Desai od->d_dnode, odirent->od_name, &fnode); 7077f667e74Sjose borrego if (rc == 0) { 708e3f2c991SKeyur Desai rc = smb_node_getattr(sr, fnode, &attr); 709e3f2c991SKeyur Desai smb_node_release(fnode); 7107f667e74Sjose borrego } 7117f667e74Sjose borrego 7127f667e74Sjose borrego if (rc == 0) { 7137f667e74Sjose borrego (void) strlcpy(sinfo->si_name, 7147f667e74Sjose borrego odirent->od_name + SMB_STREAM_PREFIX_LEN, 7157f667e74Sjose borrego sizeof (sinfo->si_name)); 7167f667e74Sjose borrego sinfo->si_size = attr.sa_vattr.va_size; 717e3f2c991SKeyur Desai sinfo->si_alloc_size = attr.sa_allocsz; 7187f667e74Sjose borrego break; 7197f667e74Sjose borrego } 7207f667e74Sjose borrego } 7217f667e74Sjose borrego mutex_exit(&od->d_mutex); 7227f667e74Sjose borrego 7237f667e74Sjose borrego kmem_free(odirent, sizeof (smb_odirent_t)); 7247f667e74Sjose borrego 7257f667e74Sjose borrego switch (rc) { 7267f667e74Sjose borrego case 0: 7277f667e74Sjose borrego *eof = B_FALSE; 7287f667e74Sjose borrego return (0); 7297f667e74Sjose borrego case ENOENT: 7307f667e74Sjose borrego *eof = B_TRUE; 7317f667e74Sjose borrego return (0); 7327f667e74Sjose borrego default: 7337f667e74Sjose borrego smbsr_errno(sr, rc); 7347f667e74Sjose borrego return (-1); 7357f667e74Sjose borrego } 7367f667e74Sjose borrego } 7377f667e74Sjose borrego 7387f667e74Sjose borrego /* 7397f667e74Sjose borrego * smb_odir_save_cookie 7407f667e74Sjose borrego * 7417f667e74Sjose borrego * Callers can save up to SMB_MAX_SEARCH cookies in the odir 7427f667e74Sjose borrego * to be used as resume points for a 'find next' request. 7437f667e74Sjose borrego */ 7447f667e74Sjose borrego void 7457f667e74Sjose borrego smb_odir_save_cookie(smb_odir_t *od, int idx, uint32_t cookie) 7467f667e74Sjose borrego { 7477f667e74Sjose borrego ASSERT(od); 7487f667e74Sjose borrego ASSERT(od->d_magic == SMB_ODIR_MAGIC); 7497f667e74Sjose borrego ASSERT(idx >= 0 && idx < SMB_MAX_SEARCH); 7507f667e74Sjose borrego 7517f667e74Sjose borrego mutex_enter(&od->d_mutex); 7527f667e74Sjose borrego od->d_cookies[idx] = cookie; 7537f667e74Sjose borrego mutex_exit(&od->d_mutex); 7547f667e74Sjose borrego } 7557f667e74Sjose borrego 7567f667e74Sjose borrego /* 7577f667e74Sjose borrego * smb_odir_resume_at 7587f667e74Sjose borrego * 759eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States * If SMB_ODIR_FLAG_WILDCARDS is not set the search is for a single 760eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States * file and should not be resumed. 761eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States * 762eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States * Wildcard searching can be resumed from: 7637f667e74Sjose borrego * - the cookie saved at a specified index (SMBsearch, SMBfind). 7647f667e74Sjose borrego * - a specified cookie (SMB_trans2_find) 7657f667e74Sjose borrego * - a specified filename (SMB_trans2_find) - NOT SUPPORTED. 7667f667e74Sjose borrego * Defaults to continuing from where the last search ended. 7677f667e74Sjose borrego * 7687f667e74Sjose borrego * Continuation from where the last search ended (SMB_trans2_find) 7697f667e74Sjose borrego * is implemented by saving the last cookie at a specific index (0) 7707f667e74Sjose borrego * smb_odir_resume_at indicates a new request, so reset od->d_bufptr 7717f667e74Sjose borrego * and d_eof to force a vop_readdir. 7727f667e74Sjose borrego */ 7737f667e74Sjose borrego void 7747f667e74Sjose borrego smb_odir_resume_at(smb_odir_t *od, smb_odir_resume_t *resume) 7757f667e74Sjose borrego { 7767f667e74Sjose borrego ASSERT(od); 7777f667e74Sjose borrego ASSERT(od->d_magic == SMB_ODIR_MAGIC); 7787f667e74Sjose borrego ASSERT(resume); 7797f667e74Sjose borrego 7807f667e74Sjose borrego mutex_enter(&od->d_mutex); 7817f667e74Sjose borrego 782eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States if ((od->d_flags & SMB_ODIR_FLAG_WILDCARDS) == 0) { 783eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States od->d_eof = B_TRUE; 784eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States mutex_exit(&od->d_mutex); 785eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States return; 786eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States } 787eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 7887f667e74Sjose borrego switch (resume->or_type) { 7897f667e74Sjose borrego case SMB_ODIR_RESUME_IDX: 7907f667e74Sjose borrego ASSERT(resume->or_idx >= 0); 7917f667e74Sjose borrego ASSERT(resume->or_idx < SMB_MAX_SEARCH); 7927f667e74Sjose borrego 7937f667e74Sjose borrego if ((resume->or_idx < 0) || 7947f667e74Sjose borrego (resume->or_idx >= SMB_MAX_SEARCH)) { 7957f667e74Sjose borrego resume->or_idx = 0; 7967f667e74Sjose borrego } 7977f667e74Sjose borrego od->d_offset = od->d_cookies[resume->or_idx]; 7987f667e74Sjose borrego break; 7997f667e74Sjose borrego case SMB_ODIR_RESUME_COOKIE: 8007f667e74Sjose borrego od->d_offset = resume->or_cookie; 8017f667e74Sjose borrego break; 8027f667e74Sjose borrego case SMB_ODIR_RESUME_FNAME: 8037f667e74Sjose borrego default: 8047f667e74Sjose borrego od->d_offset = od->d_cookies[0]; 8057f667e74Sjose borrego break; 8067f667e74Sjose borrego } 8077f667e74Sjose borrego 8087f667e74Sjose borrego /* Force a vop_readdir to refresh d_buf */ 8097f667e74Sjose borrego od->d_bufptr = NULL; 8107f667e74Sjose borrego od->d_eof = B_FALSE; 8117f667e74Sjose borrego 8127f667e74Sjose borrego mutex_exit(&od->d_mutex); 8137f667e74Sjose borrego } 8147f667e74Sjose borrego 8157f667e74Sjose borrego 8167f667e74Sjose borrego /* *** static functions *** */ 8177f667e74Sjose borrego 8187f667e74Sjose borrego /* 8197f667e74Sjose borrego * smb_odir_create 8207f667e74Sjose borrego * Allocate and populate an odir obect and add it to the tree's list. 8217f667e74Sjose borrego */ 8227f667e74Sjose borrego static smb_odir_t * 8237f667e74Sjose borrego smb_odir_create(smb_request_t *sr, smb_node_t *dnode, 824eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States char *pattern, uint16_t sattr, cred_t *cr) 8257f667e74Sjose borrego { 8267f667e74Sjose borrego smb_odir_t *od; 8277f667e74Sjose borrego smb_tree_t *tree; 8287f667e74Sjose borrego uint16_t odid; 8297f667e74Sjose borrego 8307f667e74Sjose borrego ASSERT(sr); 8317f667e74Sjose borrego ASSERT(sr->sr_magic == SMB_REQ_MAGIC); 8327f667e74Sjose borrego ASSERT(sr->tid_tree); 8337f667e74Sjose borrego ASSERT(sr->tid_tree->t_magic == SMB_TREE_MAGIC); 8347f667e74Sjose borrego ASSERT(dnode); 8357f667e74Sjose borrego ASSERT(dnode->n_magic == SMB_NODE_MAGIC); 8367f667e74Sjose borrego 8377f667e74Sjose borrego tree = sr->tid_tree; 8387f667e74Sjose borrego 8397f667e74Sjose borrego if (smb_idpool_alloc(&tree->t_odid_pool, &odid)) { 8407f667e74Sjose borrego smbsr_error(sr, NT_STATUS_TOO_MANY_OPENED_FILES, 8417f667e74Sjose borrego ERRDOS, ERROR_TOO_MANY_OPEN_FILES); 8427f667e74Sjose borrego return (NULL); 8437f667e74Sjose borrego } 8447f667e74Sjose borrego 8457f667e74Sjose borrego od = kmem_cache_alloc(tree->t_server->si_cache_odir, KM_SLEEP); 8467f667e74Sjose borrego bzero(od, sizeof (smb_odir_t)); 8477f667e74Sjose borrego 8487f667e74Sjose borrego mutex_init(&od->d_mutex, NULL, MUTEX_DEFAULT, NULL); 849a1511e6bSjoyce mcintosh od->d_refcnt = 0; 8507f667e74Sjose borrego od->d_state = SMB_ODIR_STATE_OPEN; 8517f667e74Sjose borrego od->d_magic = SMB_ODIR_MAGIC; 8527f667e74Sjose borrego od->d_opened_by_pid = sr->smb_pid; 8537f667e74Sjose borrego od->d_session = tree->t_session; 854eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States od->d_cred = cr; 8557f667e74Sjose borrego od->d_tree = tree; 8567f667e74Sjose borrego od->d_dnode = dnode; 8577f667e74Sjose borrego smb_node_ref(dnode); 8587f667e74Sjose borrego od->d_odid = odid; 8597f667e74Sjose borrego od->d_sattr = sattr; 8607f667e74Sjose borrego (void) strlcpy(od->d_pattern, pattern, sizeof (od->d_pattern)); 8618b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States od->d_flags = 0; 862fe1c642dSBill Krier if (smb_contains_wildcards(od->d_pattern)) 8638b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States od->d_flags |= SMB_ODIR_FLAG_WILDCARDS; 8648b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (vfs_has_feature(dnode->vp->v_vfsp, VFSFT_DIRENTFLAGS)) 8658b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States od->d_flags |= SMB_ODIR_FLAG_EDIRENT; 8668b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (smb_tree_has_feature(tree, SMB_TREE_CASEINSENSITIVE)) 8678b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States od->d_flags |= SMB_ODIR_FLAG_IGNORE_CASE; 8688b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (SMB_TREE_SUPPORTS_CATIA(sr)) 8698b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States od->d_flags |= SMB_ODIR_FLAG_CATIA; 870e3f2c991SKeyur Desai if (SMB_TREE_SUPPORTS_ABE(sr)) 871e3f2c991SKeyur Desai od->d_flags |= SMB_ODIR_FLAG_ABE; 8727f667e74Sjose borrego od->d_eof = B_FALSE; 8737f667e74Sjose borrego 8747f667e74Sjose borrego smb_llist_enter(&tree->t_odir_list, RW_WRITER); 8757f667e74Sjose borrego smb_llist_insert_tail(&tree->t_odir_list, od); 8767f667e74Sjose borrego smb_llist_exit(&tree->t_odir_list); 8777f667e74Sjose borrego 8787f667e74Sjose borrego atomic_inc_32(&tree->t_session->s_dir_cnt); 8797f667e74Sjose borrego return (od); 880da6c28aaSamw } 881da6c28aaSamw 882da6c28aaSamw /* 883*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Delete an odir. 8847f667e74Sjose borrego * 885*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Remove the odir from the tree list before freeing resources 886*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * associated with the odir. 887da6c28aaSamw */ 888*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States void 889*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_odir_delete(void *arg) 890da6c28aaSamw { 891*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_tree_t *tree; 892*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_odir_t *od = (smb_odir_t *)arg; 893*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 894*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_ODIR_VALID(od); 895*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ASSERT(od->d_refcnt == 0); 896da6c28aaSamw ASSERT(od->d_state == SMB_ODIR_STATE_CLOSED); 897da6c28aaSamw 898*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States tree = od->d_tree; 899*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_llist_enter(&tree->t_odir_list, RW_WRITER); 900*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_llist_remove(&tree->t_odir_list, od); 901*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_idpool_free(&tree->t_odid_pool, od->d_odid); 902*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States atomic_dec_32(&tree->t_session->s_dir_cnt); 903*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_llist_exit(&tree->t_odir_list); 904*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 905*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States mutex_enter(&od->d_mutex); 906*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States mutex_exit(&od->d_mutex); 907da6c28aaSamw 9087f667e74Sjose borrego od->d_magic = 0; 9097f667e74Sjose borrego smb_node_release(od->d_dnode); 910da6c28aaSamw mutex_destroy(&od->d_mutex); 911faa1795aSjb150015 kmem_cache_free(od->d_tree->t_server->si_cache_odir, od); 912da6c28aaSamw } 9137f667e74Sjose borrego 9147f667e74Sjose borrego /* 9157f667e74Sjose borrego * smb_odir_next_odirent 9167f667e74Sjose borrego * 9177f667e74Sjose borrego * Find the next directory entry in d_buf. If d_bufptr is NULL (buffer 9187f667e74Sjose borrego * is empty or we've reached the end of it), read the next set of 9197f667e74Sjose borrego * entries from the file system (vop_readdir). 9207f667e74Sjose borrego * 9217f667e74Sjose borrego * File systems which support VFSFT_EDIRENT_FLAGS will return the 9227f667e74Sjose borrego * directory entries as a buffer of edirent_t structure. Others will 9237f667e74Sjose borrego * return a buffer of dirent64_t structures. For simplicity translate 9247f667e74Sjose borrego * the data into an smb_odirent_t structure. 9257f667e74Sjose borrego * The ed_name/d_name in d_buf is NULL terminated by the file system. 9267f667e74Sjose borrego * 9277f667e74Sjose borrego * Some file systems can have directories larger than SMB_MAXDIRSIZE. 9288b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * If the odirent offset >= SMB_MAXDIRSIZE return ENOENT and set d_eof 9298b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * to true to stop subsequent calls to smb_vop_readdir. 9307f667e74Sjose borrego * 9317f667e74Sjose borrego * Returns: 9327f667e74Sjose borrego * 0 - success. odirent is populated with the next directory entry 9337f667e74Sjose borrego * ENOENT - no more directory entries 9347f667e74Sjose borrego * errno - error 9357f667e74Sjose borrego */ 9367f667e74Sjose borrego static int 9377f667e74Sjose borrego smb_odir_next_odirent(smb_odir_t *od, smb_odirent_t *odirent) 9387f667e74Sjose borrego { 9397f667e74Sjose borrego int rc; 9407f667e74Sjose borrego int reclen; 9417f667e74Sjose borrego int eof; 9427f667e74Sjose borrego dirent64_t *dp; 9437f667e74Sjose borrego edirent_t *edp; 9448b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States char *np; 945e3f2c991SKeyur Desai uint32_t abe_flag = 0; 9467f667e74Sjose borrego 9477f667e74Sjose borrego ASSERT(MUTEX_HELD(&od->d_mutex)); 9487f667e74Sjose borrego 94948557149Sjoyce mcintosh bzero(odirent, sizeof (smb_odirent_t)); 95048557149Sjoyce mcintosh 9517f667e74Sjose borrego if (od->d_bufptr != NULL) { 9528b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (od->d_flags & SMB_ODIR_FLAG_EDIRENT) 9538b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States reclen = od->d_edp->ed_reclen; 9548b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States else 9558b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States reclen = od->d_dp->d_reclen; 9567f667e74Sjose borrego 9577f667e74Sjose borrego if (reclen == 0) { 9587f667e74Sjose borrego od->d_bufptr = NULL; 9597f667e74Sjose borrego } else { 9607f667e74Sjose borrego od->d_bufptr += reclen; 9617f667e74Sjose borrego if (od->d_bufptr >= od->d_buf + od->d_bufsize) 9627f667e74Sjose borrego od->d_bufptr = NULL; 9637f667e74Sjose borrego } 9647f667e74Sjose borrego } 9657f667e74Sjose borrego 9667f667e74Sjose borrego if (od->d_bufptr == NULL) { 9677f667e74Sjose borrego if (od->d_eof) 9687f667e74Sjose borrego return (ENOENT); 9697f667e74Sjose borrego 9707f667e74Sjose borrego od->d_bufsize = sizeof (od->d_buf); 9717f667e74Sjose borrego 972e3f2c991SKeyur Desai if (od->d_flags & SMB_ODIR_FLAG_ABE) 973e3f2c991SKeyur Desai abe_flag = SMB_ABE; 974e3f2c991SKeyur Desai 9757f667e74Sjose borrego rc = smb_vop_readdir(od->d_dnode->vp, od->d_offset, 976e3f2c991SKeyur Desai od->d_buf, &od->d_bufsize, &eof, abe_flag, od->d_cred); 9777f667e74Sjose borrego 9787f667e74Sjose borrego if ((rc == 0) && (od->d_bufsize == 0)) 9797f667e74Sjose borrego rc = ENOENT; 9807f667e74Sjose borrego 9817f667e74Sjose borrego if (rc != 0) { 9827f667e74Sjose borrego od->d_bufptr = NULL; 9837f667e74Sjose borrego od->d_bufsize = 0; 9847f667e74Sjose borrego return (rc); 9857f667e74Sjose borrego } 9867f667e74Sjose borrego 9877f667e74Sjose borrego od->d_eof = (eof != 0); 9887f667e74Sjose borrego od->d_bufptr = od->d_buf; 9897f667e74Sjose borrego } 9907f667e74Sjose borrego 9918b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (od->d_flags & SMB_ODIR_FLAG_EDIRENT) 9928b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States od->d_offset = od->d_edp->ed_off; 9938b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States else 9948b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States od->d_offset = od->d_dp->d_off; 9958b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 9967f667e74Sjose borrego if (od->d_offset >= SMB_MAXDIRSIZE) { 9977f667e74Sjose borrego od->d_bufptr = NULL; 9987f667e74Sjose borrego od->d_bufsize = 0; 9998b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States od->d_eof = B_TRUE; 10007f667e74Sjose borrego return (ENOENT); 10017f667e74Sjose borrego } 10027f667e74Sjose borrego 10038b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (od->d_flags & SMB_ODIR_FLAG_EDIRENT) { 10047f667e74Sjose borrego edp = od->d_edp; 10057f667e74Sjose borrego odirent->od_ino = edp->ed_ino; 10067f667e74Sjose borrego odirent->od_eflags = edp->ed_eflags; 10078b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States np = edp->ed_name; 10087f667e74Sjose borrego } else { 10097f667e74Sjose borrego dp = od->d_dp; 10107f667e74Sjose borrego odirent->od_ino = dp->d_ino; 10117f667e74Sjose borrego odirent->od_eflags = 0; 10128b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States np = dp->d_name; 10138b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States } 10148b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 10158b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if ((od->d_flags & SMB_ODIR_FLAG_CATIA) && 10168b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States ((od->d_flags & SMB_ODIR_FLAG_XATTR) == 0)) { 10178b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_vop_catia_v4tov5(np, odirent->od_name, 10188b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States sizeof (odirent->od_name)); 10198b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States } else { 10208b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States (void) strlcpy(odirent->od_name, np, 10217f667e74Sjose borrego sizeof (odirent->od_name)); 10227f667e74Sjose borrego } 10237f667e74Sjose borrego 10247f667e74Sjose borrego return (0); 10257f667e74Sjose borrego } 10267f667e74Sjose borrego 10277f667e74Sjose borrego /* 10287f667e74Sjose borrego * smb_odir_single_fileinfo 10297f667e74Sjose borrego * 10307f667e74Sjose borrego * Lookup the file identified by od->d_pattern. 10317f667e74Sjose borrego * 10327f667e74Sjose borrego * If the looked up file is a link, we attempt to lookup the link target 10337f667e74Sjose borrego * to use its attributes in place of those of the files's. 10347f667e74Sjose borrego * If we fail to lookup the target of the link we use the original 10357f667e74Sjose borrego * file's attributes. 10367f667e74Sjose borrego * Check if the attributes match the search attributes. 10377f667e74Sjose borrego * 10387f667e74Sjose borrego * Returns: 0 - success 10397f667e74Sjose borrego * ENOENT - no match 10407f667e74Sjose borrego * errno - error 10417f667e74Sjose borrego */ 10427f667e74Sjose borrego static int 10437f667e74Sjose borrego smb_odir_single_fileinfo(smb_request_t *sr, smb_odir_t *od, 10447f667e74Sjose borrego smb_fileinfo_t *fileinfo) 10457f667e74Sjose borrego { 10467f667e74Sjose borrego int rc; 10477f667e74Sjose borrego smb_node_t *fnode, *tgt_node; 1048037cac00Sjoyce mcintosh smb_attr_t attr; 10497f667e74Sjose borrego ino64_t ino; 10507f667e74Sjose borrego char *name; 10518b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States boolean_t case_conflict = B_FALSE; 10528b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States int lookup_flags, flags = 0; 10538b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States vnode_t *vp; 10547f667e74Sjose borrego 10557f667e74Sjose borrego ASSERT(sr); 10567f667e74Sjose borrego ASSERT(sr->sr_magic == SMB_REQ_MAGIC); 10577f667e74Sjose borrego ASSERT(od); 10587f667e74Sjose borrego ASSERT(od->d_magic == SMB_ODIR_MAGIC); 10597f667e74Sjose borrego 10607f667e74Sjose borrego ASSERT(MUTEX_HELD(&od->d_mutex)); 10617f667e74Sjose borrego bzero(fileinfo, sizeof (smb_fileinfo_t)); 10627f667e74Sjose borrego 1063eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States rc = smb_fsop_lookup(sr, od->d_cred, 0, od->d_tree->t_snode, 1064037cac00Sjoyce mcintosh od->d_dnode, od->d_pattern, &fnode); 10657f667e74Sjose borrego if (rc != 0) 10667f667e74Sjose borrego return (rc); 10677f667e74Sjose borrego 10688b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States /* 10698b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * If case sensitive, do a case insensitive smb_vop_lookup to 10708b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * check for case conflict 10718b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States */ 10728b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (od->d_flags & SMB_ODIR_FLAG_IGNORE_CASE) { 10738b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States lookup_flags = SMB_IGNORE_CASE; 10748b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (od->d_flags & SMB_ODIR_FLAG_CATIA) 10758b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States lookup_flags |= SMB_CATIA; 10767f667e74Sjose borrego 10778b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States rc = smb_vop_lookup(od->d_dnode->vp, fnode->od_name, &vp, 10788b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States NULL, lookup_flags, &flags, od->d_tree->t_snode->vp, 1079*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States NULL, od->d_cred); 10808b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (rc != 0) 10818b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States return (rc); 10828b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States VN_RELE(vp); 10838b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 10848b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (flags & ED_CASE_CONFLICT) 10858b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States case_conflict = B_TRUE; 10868b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States } 10878b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 1088037cac00Sjoyce mcintosh if ((rc = smb_node_getattr(sr, fnode, &attr)) != 0) { 1089037cac00Sjoyce mcintosh smb_node_release(fnode); 1090037cac00Sjoyce mcintosh return (rc); 1091037cac00Sjoyce mcintosh } 1092037cac00Sjoyce mcintosh 10937f667e74Sjose borrego ino = attr.sa_vattr.va_nodeid; 10948b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States (void) smb_mangle_name(ino, fnode->od_name, 10958b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States fileinfo->fi_shortname, fileinfo->fi_name83, case_conflict); 10968b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States name = (case_conflict) ? fileinfo->fi_shortname : fnode->od_name; 10978b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States (void) strlcpy(fileinfo->fi_name, name, sizeof (fileinfo->fi_name)); 10987f667e74Sjose borrego 10997f667e74Sjose borrego /* follow link to get target node & attr */ 1100*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_node_is_symlink(fnode) && 1101*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_odir_lookup_link(sr, od, fnode->od_name, &tgt_node)) { 11027f667e74Sjose borrego smb_node_release(fnode); 11037f667e74Sjose borrego fnode = tgt_node; 1104037cac00Sjoyce mcintosh if ((rc = smb_node_getattr(sr, fnode, &attr)) != 0) { 1105037cac00Sjoyce mcintosh smb_node_release(fnode); 1106037cac00Sjoyce mcintosh return (rc); 1107037cac00Sjoyce mcintosh } 11087f667e74Sjose borrego } 11097f667e74Sjose borrego 11107f667e74Sjose borrego /* check search attributes */ 1111037cac00Sjoyce mcintosh if (!smb_sattr_check(attr.sa_dosattr, od->d_sattr)) { 11127f667e74Sjose borrego smb_node_release(fnode); 11137f667e74Sjose borrego return (ENOENT); 11147f667e74Sjose borrego } 11157f667e74Sjose borrego 1116037cac00Sjoyce mcintosh fileinfo->fi_dosattr = attr.sa_dosattr; 1117037cac00Sjoyce mcintosh fileinfo->fi_nodeid = attr.sa_vattr.va_nodeid; 1118037cac00Sjoyce mcintosh fileinfo->fi_size = attr.sa_vattr.va_size; 1119e3f2c991SKeyur Desai fileinfo->fi_alloc_size = attr.sa_allocsz; 1120037cac00Sjoyce mcintosh fileinfo->fi_atime = attr.sa_vattr.va_atime; 1121037cac00Sjoyce mcintosh fileinfo->fi_mtime = attr.sa_vattr.va_mtime; 1122037cac00Sjoyce mcintosh fileinfo->fi_ctime = attr.sa_vattr.va_ctime; 1123037cac00Sjoyce mcintosh if (attr.sa_crtime.tv_sec) 1124037cac00Sjoyce mcintosh fileinfo->fi_crtime = attr.sa_crtime; 11257f667e74Sjose borrego else 1126037cac00Sjoyce mcintosh fileinfo->fi_crtime = attr.sa_vattr.va_mtime; 11277f667e74Sjose borrego 11287f667e74Sjose borrego smb_node_release(fnode); 11297f667e74Sjose borrego return (0); 11307f667e74Sjose borrego } 11317f667e74Sjose borrego 11327f667e74Sjose borrego /* 11337f667e74Sjose borrego * smb_odir_wildcard_fileinfo 11347f667e74Sjose borrego * 11357f667e74Sjose borrego * odirent contains a directory entry, obtained from a vop_readdir. 11367f667e74Sjose borrego * If a case conflict is identified the filename is mangled and the 11377f667e74Sjose borrego * shortname is used as 'name', in place of odirent->od_name. This 11387f667e74Sjose borrego * name will be used in the smb_fsop_lookup because smb_fsop_lookup 11397f667e74Sjose borrego * performs a case insensitive lookup if the tree is case insesitive, 11407f667e74Sjose borrego * so the mangled name is required in the case conflict scenario to 11417f667e74Sjose borrego * ensure the correct match. 11427f667e74Sjose borrego * 11437f667e74Sjose borrego * If the looked up file is a link, we attempt to lookup the link target 11447f667e74Sjose borrego * to use its attributes in place of those of the files's. 11457f667e74Sjose borrego * If we fail to lookup the target of the link we use the original 11467f667e74Sjose borrego * file's attributes. 11477f667e74Sjose borrego * Check if the attributes match the search attributes. 11487f667e74Sjose borrego * 11497f667e74Sjose borrego * Although some file systems can have directories larger than 11507f667e74Sjose borrego * SMB_MAXDIRSIZE smb_odir_next_odirent ensures that no offset larger 11517f667e74Sjose borrego * than SMB_MAXDIRSIZE is returned. It is therefore safe to use the 11527f667e74Sjose borrego * offset as the cookie (uint32_t). 11537f667e74Sjose borrego * 11547f667e74Sjose borrego * Returns: 0 - success 11557f667e74Sjose borrego * ENOENT - no match, proceed to next entry 11567f667e74Sjose borrego * errno - error 11577f667e74Sjose borrego */ 11587f667e74Sjose borrego static int 11597f667e74Sjose borrego smb_odir_wildcard_fileinfo(smb_request_t *sr, smb_odir_t *od, 11607f667e74Sjose borrego smb_odirent_t *odirent, smb_fileinfo_t *fileinfo) 11617f667e74Sjose borrego { 11627f667e74Sjose borrego int rc; 11637f667e74Sjose borrego smb_node_t *fnode, *tgt_node; 1164037cac00Sjoyce mcintosh smb_attr_t attr; 11657f667e74Sjose borrego char *name; 11667f667e74Sjose borrego boolean_t case_conflict; 11677f667e74Sjose borrego 11687f667e74Sjose borrego ASSERT(sr); 11697f667e74Sjose borrego ASSERT(sr->sr_magic == SMB_REQ_MAGIC); 11707f667e74Sjose borrego ASSERT(od); 11717f667e74Sjose borrego ASSERT(od->d_magic == SMB_ODIR_MAGIC); 11727f667e74Sjose borrego 11737f667e74Sjose borrego ASSERT(MUTEX_HELD(&od->d_mutex)); 11747f667e74Sjose borrego bzero(fileinfo, sizeof (smb_fileinfo_t)); 11757f667e74Sjose borrego 11768b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States case_conflict = ((od->d_flags & SMB_ODIR_FLAG_IGNORE_CASE) && 11777f667e74Sjose borrego (odirent->od_eflags & ED_CASE_CONFLICT)); 11787f667e74Sjose borrego (void) smb_mangle_name(odirent->od_ino, odirent->od_name, 11797f667e74Sjose borrego fileinfo->fi_shortname, fileinfo->fi_name83, case_conflict); 11807f667e74Sjose borrego name = (case_conflict) ? fileinfo->fi_shortname : odirent->od_name; 11817f667e74Sjose borrego (void) strlcpy(fileinfo->fi_name, name, sizeof (fileinfo->fi_name)); 11827f667e74Sjose borrego 1183eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States rc = smb_fsop_lookup(sr, od->d_cred, 0, od->d_tree->t_snode, 1184037cac00Sjoyce mcintosh od->d_dnode, name, &fnode); 11857f667e74Sjose borrego if (rc != 0) 11867f667e74Sjose borrego return (rc); 11877f667e74Sjose borrego 11887f667e74Sjose borrego /* follow link to get target node & attr */ 1189*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_node_is_symlink(fnode) && 1190*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_odir_lookup_link(sr, od, name, &tgt_node)) { 11917f667e74Sjose borrego smb_node_release(fnode); 11927f667e74Sjose borrego fnode = tgt_node; 1193037cac00Sjoyce mcintosh } 1194037cac00Sjoyce mcintosh 1195*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /* skip system files */ 1196*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_node_is_system(fnode)) { 1197*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_node_release(fnode); 1198*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (ENOENT); 1199*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } 1200*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 1201037cac00Sjoyce mcintosh if ((rc = smb_node_getattr(sr, fnode, &attr)) != 0) { 1202037cac00Sjoyce mcintosh smb_node_release(fnode); 1203037cac00Sjoyce mcintosh return (rc); 12047f667e74Sjose borrego } 12057f667e74Sjose borrego 12067f667e74Sjose borrego /* check search attributes */ 1207037cac00Sjoyce mcintosh if (!smb_sattr_check(attr.sa_dosattr, od->d_sattr)) { 12087f667e74Sjose borrego smb_node_release(fnode); 12097f667e74Sjose borrego return (ENOENT); 12107f667e74Sjose borrego } 12117f667e74Sjose borrego 12127f667e74Sjose borrego fileinfo->fi_cookie = (uint32_t)od->d_offset; 1213037cac00Sjoyce mcintosh fileinfo->fi_dosattr = attr.sa_dosattr; 1214037cac00Sjoyce mcintosh fileinfo->fi_nodeid = attr.sa_vattr.va_nodeid; 1215037cac00Sjoyce mcintosh fileinfo->fi_size = attr.sa_vattr.va_size; 1216e3f2c991SKeyur Desai fileinfo->fi_alloc_size = attr.sa_allocsz; 1217037cac00Sjoyce mcintosh fileinfo->fi_atime = attr.sa_vattr.va_atime; 1218037cac00Sjoyce mcintosh fileinfo->fi_mtime = attr.sa_vattr.va_mtime; 1219037cac00Sjoyce mcintosh fileinfo->fi_ctime = attr.sa_vattr.va_ctime; 1220037cac00Sjoyce mcintosh if (attr.sa_crtime.tv_sec) 1221037cac00Sjoyce mcintosh fileinfo->fi_crtime = attr.sa_crtime; 12227f667e74Sjose borrego else 1223037cac00Sjoyce mcintosh fileinfo->fi_crtime = attr.sa_vattr.va_mtime; 12247f667e74Sjose borrego 12257f667e74Sjose borrego smb_node_release(fnode); 12267f667e74Sjose borrego return (0); 12277f667e74Sjose borrego } 12287f667e74Sjose borrego 12297f667e74Sjose borrego /* 12307f667e74Sjose borrego * smb_odir_lookup_link 12317f667e74Sjose borrego * 12327f667e74Sjose borrego * If the file is a symlink we lookup the object to which the 12337f667e74Sjose borrego * symlink refers so that we can return its attributes. 12347f667e74Sjose borrego * This can cause a problem if a symlink in a sub-directory 12357f667e74Sjose borrego * points to a parent directory (some UNIX GUI's create a symlink 12367f667e74Sjose borrego * in $HOME/.desktop that points to the user's home directory). 12377f667e74Sjose borrego * Some Windows applications (e.g. virus scanning) loop/hang 12387f667e74Sjose borrego * trying to follow this recursive path and there is little 12397f667e74Sjose borrego * we can do because the path is constructed on the client. 12407f667e74Sjose borrego * smb_dirsymlink_enable allows an end-user to disable 12417f667e74Sjose borrego * symlinks to directories. Symlinks to other object types 12427f667e74Sjose borrego * should be unaffected. 12437f667e74Sjose borrego * 12447f667e74Sjose borrego * Returns: B_TRUE - followed link. tgt_node and tgt_attr set 12457f667e74Sjose borrego * B_FALSE - link not followed 12467f667e74Sjose borrego */ 12477f667e74Sjose borrego static boolean_t 12487f667e74Sjose borrego smb_odir_lookup_link(smb_request_t *sr, smb_odir_t *od, 1249037cac00Sjoyce mcintosh char *fname, smb_node_t **tgt_node) 12507f667e74Sjose borrego { 12517f667e74Sjose borrego int rc; 12527f667e74Sjose borrego 1253eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States rc = smb_fsop_lookup(sr, od->d_cred, SMB_FOLLOW_LINKS, 1254037cac00Sjoyce mcintosh od->d_tree->t_snode, od->d_dnode, fname, tgt_node); 12557f667e74Sjose borrego if (rc != 0) { 12567f667e74Sjose borrego *tgt_node = NULL; 12577f667e74Sjose borrego return (B_FALSE); 12587f667e74Sjose borrego } 12597f667e74Sjose borrego 1260037cac00Sjoyce mcintosh if (smb_node_is_dir(*tgt_node) && (!smb_dirsymlink_enable)) { 12617f667e74Sjose borrego smb_node_release(*tgt_node); 12627f667e74Sjose borrego *tgt_node = NULL; 12637f667e74Sjose borrego return (B_FALSE); 12647f667e74Sjose borrego } 12657f667e74Sjose borrego 12667f667e74Sjose borrego return (B_TRUE); 12677f667e74Sjose borrego } 1268