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*dc20a302Sas200622 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23da6c28aaSamw * Use is subject to license terms. 24da6c28aaSamw */ 25da6c28aaSamw 26da6c28aaSamw #pragma ident "%Z%%M% %I% %E% SMI" 27da6c28aaSamw 28da6c28aaSamw /* 29da6c28aaSamw * This module provides functions for TRANS2_FIND_FIRST2 and 30da6c28aaSamw * TRANS2_FIND_NEXT2 requests. The requests allow the client to search 31da6c28aaSamw * for the file(s) which match the file specification. The search is 32da6c28aaSamw * started with TRANS2_FIND_FIRST2 and can be continued if necessary with 33da6c28aaSamw * TRANS2_FIND_NEXT2. There are numerous levels of information which may be 34da6c28aaSamw * obtained for the returned files, the desired level is specified in the 35da6c28aaSamw * InformationLevel field of the requests. 36da6c28aaSamw * 37da6c28aaSamw * InformationLevel Name Value 38da6c28aaSamw * ================================= ================ 39da6c28aaSamw * 40da6c28aaSamw * SMB_INFO_STANDARD 1 41da6c28aaSamw * SMB_INFO_QUERY_EA_SIZE 2 42da6c28aaSamw * SMB_INFO_QUERY_EAS_FROM_LIST 3 43da6c28aaSamw * SMB_FIND_FILE_DIRECTORY_INFO 0x101 44da6c28aaSamw * SMB_FIND_FILE_FULL_DIRECTORY_INFO 0x102 45da6c28aaSamw * SMB_FIND_FILE_NAMES_INFO 0x103 46da6c28aaSamw * SMB_FIND_FILE_BOTH_DIRECTORY_INFO 0x104 47da6c28aaSamw * 48da6c28aaSamw * The following sections detail the data returned for each 49da6c28aaSamw * InformationLevel. The requested information is placed in the Data 50da6c28aaSamw * portion of the transaction response. Note: a client which does not 51da6c28aaSamw * support long names can only request SMB_INFO_STANDARD. 52da6c28aaSamw * 53da6c28aaSamw * A four-byte resume key precedes each data item (described below) if bit 54da6c28aaSamw * 2 in the Flags field is set, i.e. if the request indicates the server 55da6c28aaSamw * should return resume keys. Note: it is not always the case. If the 56da6c28aaSamw * data item already includes the resume key, the resume key should not be 57da6c28aaSamw * added again. 58da6c28aaSamw * 59da6c28aaSamw * 4.3.4.1 SMB_INFO_STANDARD 60da6c28aaSamw * 61da6c28aaSamw * Response Field Description 62da6c28aaSamw * ================================ ================================== 63da6c28aaSamw * 64da6c28aaSamw * SMB_DATE CreationDate; Date when file was created 65da6c28aaSamw * SMB_TIME CreationTime; Time when file was created 66da6c28aaSamw * SMB_DATE LastAccessDate; Date of last file access 67da6c28aaSamw * SMB_TIME LastAccessTime; Time of last file access 68da6c28aaSamw * SMB_DATE LastWriteDate; Date of last write to the file 69da6c28aaSamw * SMB_TIME LastWriteTime; Time of last write to the file 70da6c28aaSamw * ULONG DataSize; File Size 71da6c28aaSamw * ULONG AllocationSize; Size of filesystem allocation unit 72da6c28aaSamw * USHORT Attributes; File Attributes 73da6c28aaSamw * UCHAR FileNameLength; Length of filename in bytes 74da6c28aaSamw * STRING FileName; Name of found file 75da6c28aaSamw * 76da6c28aaSamw * 4.3.4.2 SMB_INFO_QUERY_EA_SIZE 77da6c28aaSamw * 78da6c28aaSamw * Response Field Description 79da6c28aaSamw * ================================= ================================== 80da6c28aaSamw * 81da6c28aaSamw * SMB_DATE CreationDate; Date when file was created 82da6c28aaSamw * SMB_TIME CreationTime; Time when file was created 83da6c28aaSamw * SMB_DATE LastAccessDate; Date of last file access 84da6c28aaSamw * SMB_TIME LastAccessTime; Time of last file access 85da6c28aaSamw * SMB_DATE LastWriteDate; Date of last write to the file 86da6c28aaSamw * SMB_TIME LastWriteTime; Time of last write to the file 87da6c28aaSamw * ULONG DataSize; File Size 88da6c28aaSamw * ULONG AllocationSize; Size of filesystem allocation unit 89da6c28aaSamw * USHORT Attributes; File Attributes 90da6c28aaSamw * ULONG EaSize; Size of file's EA information 91da6c28aaSamw * UCHAR FileNameLength; Length of filename in bytes 92da6c28aaSamw * STRING FileName; Name of found file 93da6c28aaSamw * 94da6c28aaSamw * 4.3.4.3 SMB_INFO_QUERY_EAS_FROM_LIST 95da6c28aaSamw * 96da6c28aaSamw * This request returns the same information as SMB_INFO_QUERY_EA_SIZE, but 97da6c28aaSamw * only for files which have an EA list which match the EA information in 98da6c28aaSamw * the Data part of the request. 99da6c28aaSamw * 100da6c28aaSamw * 4.3.4.4 SMB_FIND_FILE_DIRECTORY_INFO 101da6c28aaSamw * 102da6c28aaSamw * Response Field Description 103da6c28aaSamw * ================================= ================================== 104da6c28aaSamw * 105da6c28aaSamw * ULONG NextEntryOffset; Offset from this structure to 106da6c28aaSamw * beginning of next one 107da6c28aaSamw * ULONG FileIndex; 108da6c28aaSamw * LARGE_INTEGER CreationTime; file creation time 109da6c28aaSamw * LARGE_INTEGER LastAccessTime; last access time 110da6c28aaSamw * LARGE_INTEGER LastWriteTime; last write time 111da6c28aaSamw * LARGE_INTEGER ChangeTime; last attribute change time 112da6c28aaSamw * LARGE_INTEGER EndOfFile; file size 113da6c28aaSamw * LARGE_INTEGER AllocationSize; size of filesystem allocation information 114da6c28aaSamw * ULONG ExtFileAttributes; Extended file attributes 115da6c28aaSamw * (see section 3.11) 116da6c28aaSamw * ULONG FileNameLength; Length of filename in bytes 117da6c28aaSamw * STRING FileName; Name of the file 118da6c28aaSamw * 119da6c28aaSamw * 4.3.4.5 SMB_FIND_FILE_FULL_DIRECTORY_INFO 120da6c28aaSamw * 121da6c28aaSamw * Response Field Description 122da6c28aaSamw * ================================= ================================== 123da6c28aaSamw * 124da6c28aaSamw * ULONG NextEntryOffset; Offset from this structure to 125da6c28aaSamw * beginning of next one 126da6c28aaSamw * ULONG FileIndex; 127da6c28aaSamw * LARGE_INTEGER CreationTime; file creation time 128da6c28aaSamw * LARGE_INTEGER LastAccessTime; last access time 129da6c28aaSamw * LARGE_INTEGER LastWriteTime; last write time 130da6c28aaSamw * LARGE_INTEGER ChangeTime; last attribute change time 131da6c28aaSamw * LARGE_INTEGER EndOfFile; file size 132da6c28aaSamw * LARGE_INTEGER AllocationSize; size of filesystem allocation information 133da6c28aaSamw * ULONG ExtFileAttributes; Extended file attributes 134da6c28aaSamw * (see section 3.11) 135da6c28aaSamw * ULONG FileNameLength; Length of filename in bytes 136da6c28aaSamw * ULONG EaSize; Size of file's extended attributes 137da6c28aaSamw * STRING FileName; Name of the file 138da6c28aaSamw * 139da6c28aaSamw * 4.3.4.6 SMB_FIND_FILE_BOTH_DIRECTORY_INFO 140da6c28aaSamw * 141da6c28aaSamw * Response Field Description 142da6c28aaSamw * ================================= ================================== 143da6c28aaSamw * 144da6c28aaSamw * ULONG NextEntryOffset; Offset from this structure to 145da6c28aaSamw * beginning of next one 146da6c28aaSamw * ULONG FileIndex; 147da6c28aaSamw * LARGE_INTEGER CreationTime; file creation time 148da6c28aaSamw * LARGE_INTEGER LastAccessTime; last access time 149da6c28aaSamw * LARGE_INTEGER LastWriteTime; last write time 150da6c28aaSamw * LARGE_INTEGER ChangeTime; last attribute change time 151da6c28aaSamw * LARGE_INTEGER EndOfFile; file size 152da6c28aaSamw * LARGE_INTEGER AllocationSize; size of filesystem allocation information 153da6c28aaSamw * ULONG ExtFileAttributes; Extended file attributes 154da6c28aaSamw * (see section 3.11) 155da6c28aaSamw * ULONG FileNameLength; Length of FileName in bytes 156da6c28aaSamw * ULONG EaSize; Size of file's extended attributes 157da6c28aaSamw * UCHAR ShortNameLength; Length of file's short name in bytes 158da6c28aaSamw * UCHAR Reserved 159da6c28aaSamw * WCHAR ShortName[12]; File's 8.3 conformant name in Unicode 160da6c28aaSamw * STRING FileName; Files full length name 161da6c28aaSamw * 162da6c28aaSamw * 4.3.4.7 SMB_FIND_FILE_NAMES_INFO 163da6c28aaSamw * 164da6c28aaSamw * Response Field Description 165da6c28aaSamw * ================================= ================================== 166da6c28aaSamw * 167da6c28aaSamw * ULONG NextEntryOffset; Offset from this structure to 168da6c28aaSamw * beginning of next one 169da6c28aaSamw * ULONG FileIndex; 170da6c28aaSamw * ULONG FileNameLength; Length of FileName in bytes 171da6c28aaSamw * STRING FileName; Files full length name 172da6c28aaSamw */ 173da6c28aaSamw 174da6c28aaSamw #include <smbsrv/smb_incl.h> 175da6c28aaSamw #include <smbsrv/msgbuf.h> 176da6c28aaSamw #include <smbsrv/smbtrans.h> 177da6c28aaSamw #include <smbsrv/smb_fsops.h> 178da6c28aaSamw 179*dc20a302Sas200622 static int smb_trans2_find_get_maxdata(smb_request_t *, uint16_t, uint16_t); 180da6c28aaSamw 181*dc20a302Sas200622 int smb_trans2_find_get_dents(smb_request_t *, smb_xa_t *, 182*dc20a302Sas200622 uint16_t, uint16_t, int, smb_node_t *, 183*dc20a302Sas200622 uint16_t, uint16_t, int, char *, uint32_t *, int *, int *); 184da6c28aaSamw 185da6c28aaSamw int smb_gather_dents_info(char *, ino_t, int, char *, uint32_t, int32_t *, 186*dc20a302Sas200622 smb_attr_t *, smb_node_t *, char *, char *); 187da6c28aaSamw 188*dc20a302Sas200622 int smb_trans2_find_process_ients(smb_request_t *, smb_xa_t *, 189*dc20a302Sas200622 smb_dent_info_hdr_t *, uint16_t, uint16_t, int, 190*dc20a302Sas200622 smb_node_t *, int *, uint32_t *); 191da6c28aaSamw 192*dc20a302Sas200622 int smb_trans2_find_mbc_encode(smb_request_t *, smb_xa_t *, 193*dc20a302Sas200622 smb_dent_info_t *, int, uint16_t, uint16_t, 194*dc20a302Sas200622 uint32_t, smb_node_t *, smb_node_t *); 195da6c28aaSamw 196da6c28aaSamw /* 197*dc20a302Sas200622 * The UNIX characters below are considered illegal in Windows file names. 198*dc20a302Sas200622 * The following character conversions are used to support sites in which 199*dc20a302Sas200622 * Catia v4 is in use on UNIX and Catia v5 is in use on Windows. 200*dc20a302Sas200622 * 201*dc20a302Sas200622 * --------------------------- 202*dc20a302Sas200622 * Unix-char | Windows-char 203*dc20a302Sas200622 * --------------------------- 204*dc20a302Sas200622 * " | (0x00a8) Diaeresis 205*dc20a302Sas200622 * * | (0x00a4) Currency Sign 206*dc20a302Sas200622 * : | (0x00f7) Division Sign 207*dc20a302Sas200622 * < | (0x00ab) Left-Pointing Double Angle Quotation Mark 208*dc20a302Sas200622 * > | (0x00bb) Right-Pointing Double Angle Quotation Mark 209*dc20a302Sas200622 * ? | (0x00bf) Inverted Question mark 210*dc20a302Sas200622 * \ | (0x00ff) Latin Small Letter Y with Diaeresis 211*dc20a302Sas200622 * | | (0x00a6) Broken Bar 212da6c28aaSamw */ 213*dc20a302Sas200622 static int (*catia_callback)(uint8_t *, uint8_t *, int) = NULL; 214da6c28aaSamw void smb_register_catia_callback( 215*dc20a302Sas200622 int (*catia_v4tov5)(uint8_t *, uint8_t *, int)); 216da6c28aaSamw void smb_unregister_catia_callback(); 217da6c28aaSamw 218da6c28aaSamw /* 219*dc20a302Sas200622 * Tunable parameter to limit the maximum 220*dc20a302Sas200622 * number of entries to be returned. 221da6c28aaSamw */ 222*dc20a302Sas200622 uint16_t smb_trans2_find_max = 128; 223da6c28aaSamw 224da6c28aaSamw /* 225da6c28aaSamw * smb_register_catia_callback 226da6c28aaSamw * 227da6c28aaSamw * This function will be invoked by the catia module to register its 228da6c28aaSamw * function that translates filename in version 4 to a format that is 229da6c28aaSamw * compatible to version 5. 230da6c28aaSamw */ 231da6c28aaSamw void 232da6c28aaSamw smb_register_catia_callback( 233*dc20a302Sas200622 int (*catia_v4tov5)(uint8_t *, uint8_t *, int)) 234da6c28aaSamw { 235da6c28aaSamw catia_callback = catia_v4tov5; 236da6c28aaSamw } 237da6c28aaSamw 238da6c28aaSamw /* 239da6c28aaSamw * smb_unregister_catia_callback 240da6c28aaSamw * 241da6c28aaSamw * This function will unregister the catia callback prior to the catia 242da6c28aaSamw * module gets unloaded. 243da6c28aaSamw */ 244da6c28aaSamw void 245da6c28aaSamw smb_unregister_catia_callback() 246da6c28aaSamw { 247da6c28aaSamw catia_callback = 0; 248da6c28aaSamw } 249da6c28aaSamw 250da6c28aaSamw /* 251da6c28aaSamw * smb_com_trans2_find_first2 252da6c28aaSamw * 253da6c28aaSamw * Client Request Value 254da6c28aaSamw * ============================ ================================== 255da6c28aaSamw * 256da6c28aaSamw * UCHAR WordCount 15 257da6c28aaSamw * UCHAR TotalDataCount Total size of extended attribute list 258da6c28aaSamw * UCHAR SetupCount 1 259da6c28aaSamw * UCHAR Setup[0] TRANS2_FIND_FIRST2 260da6c28aaSamw * 261da6c28aaSamw * Parameter Block Encoding Description 262da6c28aaSamw * ============================ ================================== 263da6c28aaSamw * USHORT SearchAttributes; 264da6c28aaSamw * USHORT SearchCount; Maximum number of entries to return 265da6c28aaSamw * USHORT Flags; Additional information: 266da6c28aaSamw * Bit 0 - close search after this request 267da6c28aaSamw * Bit 1 - close search if end of search 268da6c28aaSamw * reached 269da6c28aaSamw * Bit 2 - return resume keys for each 270da6c28aaSamw * entry found 271da6c28aaSamw * Bit 3 - continue search from previous 272da6c28aaSamw * ending place 273da6c28aaSamw * Bit 4 - find with backup intent 274da6c28aaSamw * USHORT InformationLevel; See below 275da6c28aaSamw * ULONG SearchStorageType; 276da6c28aaSamw * STRING FileName; Pattern for the search 277da6c28aaSamw * UCHAR Data[ TotalDataCount ] FEAList if InformationLevel is 278da6c28aaSamw * QUERY_EAS_FROM_LIST 279da6c28aaSamw * 280da6c28aaSamw * Response Parameter Block Description 281da6c28aaSamw * ============================ ================================== 282da6c28aaSamw * 283da6c28aaSamw * USHORT Sid; Search handle 284da6c28aaSamw * USHORT SearchCount; Number of entries returned 285da6c28aaSamw * USHORT EndOfSearch; Was last entry returned? 286da6c28aaSamw * USHORT EaErrorOffset; Offset into EA list if EA error 287da6c28aaSamw * USHORT LastNameOffset; Offset into data to file name of last 288da6c28aaSamw * entry, if server needs it to resume 289da6c28aaSamw * search; else 0 290da6c28aaSamw * UCHAR Data[ TotalDataCount ] Level dependent info about the matches 291da6c28aaSamw * found in the search 292da6c28aaSamw */ 293da6c28aaSamw int 294*dc20a302Sas200622 smb_com_trans2_find_first2(smb_request_t *sr, smb_xa_t *xa) 295da6c28aaSamw { 296da6c28aaSamw int more = 0, rc; 297*dc20a302Sas200622 uint16_t sattr, fflag, infolev; 298*dc20a302Sas200622 uint16_t maxcount = 0; 299da6c28aaSamw int maxdata; 300*dc20a302Sas200622 int count, wildcards; 301da6c28aaSamw uint32_t cookie; 302da6c28aaSamw char *path; 303*dc20a302Sas200622 smb_node_t *dir_snode; 304da6c28aaSamw char *pattern; 305*dc20a302Sas200622 uint16_t sid; 306da6c28aaSamw 307da6c28aaSamw if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) { 308*dc20a302Sas200622 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 309da6c28aaSamw ERRDOS, ERROR_ACCESS_DENIED); 310da6c28aaSamw /* NOTREACHED */ 311da6c28aaSamw } 312da6c28aaSamw 313da6c28aaSamw if (smb_decode_mbc(&xa->req_param_mb, "%wwww4.u", sr, 314da6c28aaSamw &sattr, &maxcount, &fflag, &infolev, &path) != 0) { 315da6c28aaSamw smbsr_decode_error(sr); 316da6c28aaSamw /* NOTREACHED */ 317da6c28aaSamw } 318da6c28aaSamw 319da6c28aaSamw maxdata = smb_trans2_find_get_maxdata(sr, infolev, fflag); 320da6c28aaSamw if (maxdata == 0) { 321*dc20a302Sas200622 smbsr_error(sr, NT_STATUS_INVALID_LEVEL, 322*dc20a302Sas200622 ERRDOS, ERROR_INVALID_LEVEL); 323da6c28aaSamw /* NOTREACHED */ 324da6c28aaSamw } 325da6c28aaSamw 326*dc20a302Sas200622 /* 327*dc20a302Sas200622 * When maxcount is zero Windows behaves as if it was 1. 328*dc20a302Sas200622 */ 329*dc20a302Sas200622 if (maxcount == 0) 330*dc20a302Sas200622 maxcount = 1; 331*dc20a302Sas200622 332*dc20a302Sas200622 if ((smb_trans2_find_max != 0) && (maxcount > smb_trans2_find_max)) 333*dc20a302Sas200622 maxcount = smb_trans2_find_max; 334*dc20a302Sas200622 335*dc20a302Sas200622 if (sr->smb_flg2 & SMB_FLAGS2_UNICODE) 336da6c28aaSamw (void) smb_convert_unicode_wildcards(path); 337*dc20a302Sas200622 338da6c28aaSamw (void) smb_rdir_open(sr, path, sattr); 339da6c28aaSamw 340da6c28aaSamw /* 341da6c28aaSamw * Get a copy of information 342da6c28aaSamw */ 343da6c28aaSamw dir_snode = sr->sid_odir->d_dir_snode; 344*dc20a302Sas200622 pattern = kmem_alloc(MAXNAMELEN, KM_SLEEP); 345da6c28aaSamw (void) strcpy(pattern, sr->sid_odir->d_pattern); 346*dc20a302Sas200622 347da6c28aaSamw if (strcmp(pattern, "*.*") == 0) 348da6c28aaSamw (void) strncpy(pattern, "*", sizeof (pattern)); 349*dc20a302Sas200622 350da6c28aaSamw wildcards = sr->sid_odir->d_wildcards; 351da6c28aaSamw sattr = sr->sid_odir->d_sattr; 352da6c28aaSamw cookie = 0; 353da6c28aaSamw 354da6c28aaSamw rc = smb_trans2_find_get_dents(sr, xa, fflag, infolev, maxdata, 355da6c28aaSamw dir_snode, sattr, maxcount, wildcards, 356da6c28aaSamw pattern, &cookie, &more, &count); 357da6c28aaSamw 358da6c28aaSamw if (!count) 359da6c28aaSamw rc = ENOENT; 360da6c28aaSamw 361da6c28aaSamw if (rc) { 362da6c28aaSamw smb_rdir_close(sr); 363da6c28aaSamw kmem_free(pattern, MAXNAMELEN); 364*dc20a302Sas200622 smbsr_errno(sr, rc); 365da6c28aaSamw /* NOTREACHED */ 366da6c28aaSamw } 367da6c28aaSamw 368da6c28aaSamw /* 369*dc20a302Sas200622 * Save the sid here in case the search is closed below, 370*dc20a302Sas200622 * which will invalidate sr->smb_sid. We return the 371*dc20a302Sas200622 * sid, even though the search has been closed, to be 372*dc20a302Sas200622 * compatible with Windows. 373da6c28aaSamw */ 374da6c28aaSamw sid = sr->smb_sid; 375da6c28aaSamw 376da6c28aaSamw if (fflag & SMB_FIND_CLOSE_AFTER_REQUEST || 377*dc20a302Sas200622 (!more && fflag & SMB_FIND_CLOSE_AT_EOS)) { 378da6c28aaSamw smb_rdir_close(sr); 379*dc20a302Sas200622 } else { 380da6c28aaSamw mutex_enter(&sr->sid_odir->d_mutex); 381da6c28aaSamw sr->sid_odir->d_cookie = cookie; 382da6c28aaSamw mutex_exit(&sr->sid_odir->d_mutex); 383da6c28aaSamw } 384da6c28aaSamw 385da6c28aaSamw (void) smb_encode_mbc(&xa->rep_param_mb, "wwwww", 386da6c28aaSamw sid, count, (more ? 0 : 1), 0, 0); 387da6c28aaSamw 388da6c28aaSamw kmem_free(pattern, MAXNAMELEN); 389da6c28aaSamw return (SDRC_NORMAL_REPLY); 390da6c28aaSamw } 391da6c28aaSamw 392da6c28aaSamw /* 393da6c28aaSamw * smb_com_trans2_find_next2 394da6c28aaSamw * 395da6c28aaSamw * Client Request Value 396da6c28aaSamw * ================================== ================================= 397da6c28aaSamw * 398da6c28aaSamw * WordCount 15 399da6c28aaSamw * SetupCount 1 400da6c28aaSamw * Setup[0] TRANS2_FIND_NEXT2 401da6c28aaSamw * 402da6c28aaSamw * Parameter Block Encoding Description 403da6c28aaSamw * ================================== ================================= 404da6c28aaSamw * 405da6c28aaSamw * USHORT Sid; Search handle 406da6c28aaSamw * USHORT SearchCount; Maximum number of entries to 407da6c28aaSamw * return 408da6c28aaSamw * USHORT InformationLevel; Levels described in 409da6c28aaSamw * TRANS2_FIND_FIRST2 request 410da6c28aaSamw * ULONG ResumeKey; Value returned by previous find2 411da6c28aaSamw * call 412da6c28aaSamw * USHORT Flags; Additional information: bit set- 413da6c28aaSamw * 0 - close search after this 414da6c28aaSamw * request 415da6c28aaSamw * 1 - close search if end of search 416da6c28aaSamw * reached 417da6c28aaSamw * 2 - return resume keys for each 418da6c28aaSamw * entry found 419da6c28aaSamw * 3 - resume/continue from previous 420da6c28aaSamw * ending place 421da6c28aaSamw * 4 - find with backup intent 422da6c28aaSamw * STRING FileName; Resume file name 423da6c28aaSamw * 424da6c28aaSamw * Sid is the value returned by a previous successful TRANS2_FIND_FIRST2 425da6c28aaSamw * call. If Bit3 of Flags is set, then FileName may be the NULL string, 426da6c28aaSamw * since the search is continued from the previous TRANS2_FIND request. 427da6c28aaSamw * Otherwise, FileName must not be more than 256 characters long. 428da6c28aaSamw * 429da6c28aaSamw * Response Field Description 430da6c28aaSamw * ================================== ================================= 431da6c28aaSamw * 432da6c28aaSamw * USHORT SearchCount; Number of entries returned 433da6c28aaSamw * USHORT EndOfSearch; Was last entry returned? 434da6c28aaSamw * USHORT EaErrorOffset; Offset into EA list if EA error 435da6c28aaSamw * USHORT LastNameOffset; Offset into data to file name of 436da6c28aaSamw * last entry, if server needs it to 437da6c28aaSamw * resume search; else 0 438da6c28aaSamw * UCHAR Data[TotalDataCount] Level dependent info about the 439da6c28aaSamw * matches found in the search 440da6c28aaSamw */ 441da6c28aaSamw int 442*dc20a302Sas200622 smb_com_trans2_find_next2(smb_request_t *sr, smb_xa_t *xa) 443da6c28aaSamw { 444*dc20a302Sas200622 uint16_t fflag, infolev; 445da6c28aaSamw int maxdata, count, wildcards, more = 0, rc; 446da6c28aaSamw uint32_t cookie; 447*dc20a302Sas200622 uint16_t maxcount = 0; 448*dc20a302Sas200622 smb_node_t *dir_snode; 449da6c28aaSamw char *pattern; 450*dc20a302Sas200622 uint16_t sattr; 451da6c28aaSamw 452da6c28aaSamw /* 453*dc20a302Sas200622 * The last parameter in the request is a path, which is a 454*dc20a302Sas200622 * null-terminated unicode string. 455da6c28aaSamw * 456da6c28aaSamw * smb_decode_mbc(&xa->req_param_mb, "%www lwu", sr, 457da6c28aaSamw * &sr->smb_sid, &maxcount, &infolev, &cookie, &fflag, &path) 458da6c28aaSamw * 459*dc20a302Sas200622 * We don't reference this parameter and it is not currently 460*dc20a302Sas200622 * decoded because we a expect 2-byte null but Mac OS 10 461*dc20a302Sas200622 * clients send a 1-byte null, which leads to a decode error. 462da6c28aaSamw */ 463da6c28aaSamw if (smb_decode_mbc(&xa->req_param_mb, "%www lw", sr, 464da6c28aaSamw &sr->smb_sid, &maxcount, &infolev, &cookie, &fflag) != 0) { 465da6c28aaSamw smbsr_decode_error(sr); 466da6c28aaSamw /* NOTREACHED */ 467da6c28aaSamw } 468da6c28aaSamw 469da6c28aaSamw sr->sid_odir = smb_odir_lookup_by_sid(sr->tid_tree, sr->smb_sid); 470da6c28aaSamw if (sr->sid_odir == NULL) { 471*dc20a302Sas200622 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 472da6c28aaSamw /* NOTREACHED */ 473da6c28aaSamw } 474da6c28aaSamw 475*dc20a302Sas200622 maxdata = smb_trans2_find_get_maxdata(sr, infolev, fflag); 476da6c28aaSamw if (maxdata == 0) { 477da6c28aaSamw smb_rdir_close(sr); 478*dc20a302Sas200622 smbsr_error(sr, NT_STATUS_INVALID_LEVEL, 479*dc20a302Sas200622 ERRDOS, ERROR_INVALID_LEVEL); 480da6c28aaSamw /* NOTREACHED */ 481da6c28aaSamw } 482da6c28aaSamw 483da6c28aaSamw /* 484*dc20a302Sas200622 * When maxcount is zero Windows behaves as if it was 1. 485*dc20a302Sas200622 */ 486*dc20a302Sas200622 if (maxcount == 0) 487*dc20a302Sas200622 maxcount = 1; 488*dc20a302Sas200622 489*dc20a302Sas200622 if ((smb_trans2_find_max != 0) && (maxcount > smb_trans2_find_max)) 490*dc20a302Sas200622 maxcount = smb_trans2_find_max; 491*dc20a302Sas200622 492*dc20a302Sas200622 /* 493da6c28aaSamw * Get a copy of information 494da6c28aaSamw */ 495da6c28aaSamw dir_snode = sr->sid_odir->d_dir_snode; 496*dc20a302Sas200622 pattern = kmem_alloc(MAXNAMELEN, KM_SLEEP); 497da6c28aaSamw (void) strcpy(pattern, sr->sid_odir->d_pattern); 498da6c28aaSamw wildcards = sr->sid_odir->d_wildcards; 499da6c28aaSamw sattr = sr->sid_odir->d_sattr; 500da6c28aaSamw if (fflag & SMB_FIND_CONTINUE_FROM_LAST) { 501da6c28aaSamw mutex_enter(&sr->sid_odir->d_mutex); 502da6c28aaSamw cookie = sr->sid_odir->d_cookie; 503da6c28aaSamw mutex_exit(&sr->sid_odir->d_mutex); 504da6c28aaSamw } 505da6c28aaSamw 506da6c28aaSamw rc = smb_trans2_find_get_dents(sr, xa, fflag, infolev, maxdata, 507da6c28aaSamw dir_snode, sattr, maxcount, wildcards, pattern, &cookie, 508da6c28aaSamw &more, &count); 509da6c28aaSamw 510da6c28aaSamw if (rc) { 511da6c28aaSamw smb_rdir_close(sr); 512da6c28aaSamw kmem_free(pattern, MAXNAMELEN); 513*dc20a302Sas200622 smbsr_errno(sr, rc); 514da6c28aaSamw /* NOTREACHED */ 515da6c28aaSamw } 516da6c28aaSamw 517da6c28aaSamw if (fflag & SMB_FIND_CLOSE_AFTER_REQUEST || 518da6c28aaSamw (!more && fflag & SMB_FIND_CLOSE_AT_EOS)) 519da6c28aaSamw smb_rdir_close(sr); 520da6c28aaSamw else { 521da6c28aaSamw mutex_enter(&sr->sid_odir->d_mutex); 522da6c28aaSamw sr->sid_odir->d_cookie = cookie; 523da6c28aaSamw mutex_exit(&sr->sid_odir->d_mutex); 524da6c28aaSamw } 525da6c28aaSamw 526da6c28aaSamw (void) smb_encode_mbc(&xa->rep_param_mb, "wwww", 527da6c28aaSamw count, (more ? 0 : 1), 0, 0); 528da6c28aaSamw 529da6c28aaSamw kmem_free(pattern, MAXNAMELEN); 530da6c28aaSamw return (SDRC_NORMAL_REPLY); 531da6c28aaSamw } 532da6c28aaSamw 533da6c28aaSamw /* 534da6c28aaSamw * smb_trans2_find_get_maxdata 535da6c28aaSamw * 536*dc20a302Sas200622 * Calculate the minimum response space required for the specified 537*dc20a302Sas200622 * information level. 538da6c28aaSamw * 539*dc20a302Sas200622 * A non-zero return value provides the minimum space required. 540*dc20a302Sas200622 * A return value of zero indicates an unknown information level. 541da6c28aaSamw */ 542*dc20a302Sas200622 static int 543*dc20a302Sas200622 smb_trans2_find_get_maxdata(smb_request_t *sr, uint16_t infolev, uint16_t fflag) 544da6c28aaSamw { 545da6c28aaSamw int maxdata; 546da6c28aaSamw 547da6c28aaSamw maxdata = smb_ascii_or_unicode_null_len(sr); 548da6c28aaSamw 549da6c28aaSamw switch (infolev) { 550da6c28aaSamw case SMB_INFO_STANDARD : 551da6c28aaSamw if (fflag & SMB_FIND_RETURN_RESUME_KEYS) 552da6c28aaSamw maxdata += sizeof (int32_t); 553da6c28aaSamw maxdata += 2 + 2 + 2 + 4 + 4 + 2 + 1; 554da6c28aaSamw break; 555da6c28aaSamw 556da6c28aaSamw case SMB_INFO_QUERY_EA_SIZE: 557da6c28aaSamw if (fflag & SMB_FIND_RETURN_RESUME_KEYS) 558da6c28aaSamw maxdata += sizeof (int32_t); 559da6c28aaSamw maxdata += 2 + 2 + 2 + 4 + 4 + 2 + 4 + 1; 560da6c28aaSamw break; 561da6c28aaSamw 562da6c28aaSamw case SMB_FIND_FILE_DIRECTORY_INFO: 563da6c28aaSamw maxdata += 4 + 4 + 8 + 8 + 8 + 8 + 8 + 8 + 4 + 4; 564da6c28aaSamw break; 565da6c28aaSamw 566da6c28aaSamw case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: 567da6c28aaSamw maxdata += 4 + 4 + 8 + 8 + 8 + 8 + 8 + 8 + 4 + 4 + 4 + 2 + 24; 568da6c28aaSamw break; 569da6c28aaSamw 570da6c28aaSamw case SMB_FIND_FILE_NAMES_INFO: 571da6c28aaSamw maxdata += 4 + 4 + 4; 572da6c28aaSamw break; 573da6c28aaSamw 574da6c28aaSamw case SMB_MAC_FIND_BOTH_HFS_INFO: 575da6c28aaSamw maxdata += 4 + 4 + 8 + 8 + 8 + 8 + 8 + 8 + 8 + 4 + 1 + 1 + 2 + 576da6c28aaSamw 4 + 32 + 4 + 1 + 1 + 24 + 4; 577da6c28aaSamw break; 578da6c28aaSamw 579da6c28aaSamw default: 580da6c28aaSamw maxdata = 0; 581da6c28aaSamw } 582da6c28aaSamw 583da6c28aaSamw return (maxdata); 584da6c28aaSamw } 585da6c28aaSamw 586da6c28aaSamw /* 587da6c28aaSamw * smb_trans2_find_get_dents 588da6c28aaSamw * 589da6c28aaSamw * This function will get all the directory entry information and mbc 590da6c28aaSamw * encode it in the xa. If there is an error, it will be returned; 591da6c28aaSamw * otherwise, 0 is returned. 592da6c28aaSamw * 593da6c28aaSamw * The more field will be updated. If the value returned is one, it means 594da6c28aaSamw * there are more entries; otherwise, the returned value will be zero. The 595da6c28aaSamw * cookie will also be updated to indicate the next start point for the 596da6c28aaSamw * search. The count value will also be updated to stores the total entries 597da6c28aaSamw * encoded. 598da6c28aaSamw */ 599da6c28aaSamw int smb_trans2_find_get_dents( 600da6c28aaSamw smb_request_t *sr, 601da6c28aaSamw smb_xa_t *xa, 602*dc20a302Sas200622 uint16_t fflag, 603*dc20a302Sas200622 uint16_t infolev, 604da6c28aaSamw int maxdata, 605da6c28aaSamw smb_node_t *dir_snode, 606*dc20a302Sas200622 uint16_t sattr, 607*dc20a302Sas200622 uint16_t maxcount, 608da6c28aaSamw int wildcards, 609da6c28aaSamw char *pattern, 610da6c28aaSamw uint32_t *cookie, 611da6c28aaSamw int *more, 612da6c28aaSamw int *count) 613da6c28aaSamw { 614da6c28aaSamw smb_dent_info_hdr_t *ihdr; 615da6c28aaSamw smb_dent_info_t *ient; 616da6c28aaSamw int dent_buf_size; 617da6c28aaSamw int i; 618da6c28aaSamw int total; 619da6c28aaSamw int maxentries; 620da6c28aaSamw int rc; 621da6c28aaSamw 622da6c28aaSamw ihdr = kmem_zalloc(sizeof (smb_dent_info_hdr_t), KM_SLEEP); 623da6c28aaSamw *count = 0; 624da6c28aaSamw 625da6c28aaSamw if (!wildcards) 626da6c28aaSamw maxentries = maxcount = 1; 627da6c28aaSamw else { 628da6c28aaSamw maxentries = (xa->rep_data_mb.max_bytes - 629da6c28aaSamw xa->rep_data_mb.chain_offset) / maxdata; 630da6c28aaSamw if (maxcount > SMB_MAX_DENTS_IOVEC) 631da6c28aaSamw maxcount = SMB_MAX_DENTS_IOVEC; 632da6c28aaSamw if (maxentries > maxcount) 633da6c28aaSamw maxentries = maxcount; 634da6c28aaSamw } 635da6c28aaSamw 636da6c28aaSamw /* Each entry will need to be aligned so add _POINTER_ALIGNMENT */ 637da6c28aaSamw dent_buf_size = 638da6c28aaSamw maxentries * (SMB_MAX_DENT_INFO_SIZE + _POINTER_ALIGNMENT); 639da6c28aaSamw ihdr->iov->iov_base = kmem_alloc(dent_buf_size, KM_SLEEP); 640da6c28aaSamw 641da6c28aaSamw ihdr->sattr = sattr; 642da6c28aaSamw ihdr->pattern = pattern; 643da6c28aaSamw ihdr->sr = sr; 644da6c28aaSamw 645da6c28aaSamw ihdr->uio.uio_iovcnt = maxcount; 646da6c28aaSamw ihdr->uio.uio_resid = dent_buf_size; 647da6c28aaSamw ihdr->uio.uio_iov = ihdr->iov; 64855bf511dSas200622 ihdr->uio.uio_loffset = 0; 649da6c28aaSamw 650da6c28aaSamw rc = smb_get_dents(sr, cookie, dir_snode, wildcards, ihdr, more); 651da6c28aaSamw if (rc != 0) { 652da6c28aaSamw goto out; 653da6c28aaSamw } 654da6c28aaSamw 655da6c28aaSamw if (ihdr->iov->iov_len == 0) 656da6c28aaSamw *count = 0; 657da6c28aaSamw else 658da6c28aaSamw *count = smb_trans2_find_process_ients(sr, xa, ihdr, fflag, 659da6c28aaSamw infolev, maxdata, dir_snode, more, cookie); 660da6c28aaSamw rc = 0; 661da6c28aaSamw 662da6c28aaSamw out: 663da6c28aaSamw 664da6c28aaSamw total = maxcount - ihdr->uio.uio_iovcnt; 665da6c28aaSamw ASSERT((total >= 0) && (total <= SMB_MAX_DENTS_IOVEC)); 666da6c28aaSamw for (i = 0; i < total; i++) { 667da6c28aaSamw /*LINTED E_BAD_PTR_CAST_ALIGN*/ 668da6c28aaSamw ient = (smb_dent_info_t *)ihdr->iov[i].iov_base; 669da6c28aaSamw ASSERT(ient); 670da6c28aaSamw smb_node_release(ient->snode); 671da6c28aaSamw } 672da6c28aaSamw 673da6c28aaSamw kmem_free(ihdr->iov->iov_base, dent_buf_size); 674da6c28aaSamw kmem_free(ihdr, sizeof (smb_dent_info_hdr_t)); 675da6c28aaSamw return (0); 676da6c28aaSamw } 677da6c28aaSamw 678da6c28aaSamw 679da6c28aaSamw 680da6c28aaSamw /* 681da6c28aaSamw * smb_get_dents 682da6c28aaSamw * 683da6c28aaSamw * This function utilizes "smb_fsop_getdents()" to get dir entries. 684da6c28aaSamw * The "smb_gather_dents_info()" is the call back function called 685da6c28aaSamw * inside the file system. It is very important that the function 686da6c28aaSamw * does not sleep or yield since it is processed inside a file 687da6c28aaSamw * system transaction. 688da6c28aaSamw * 689da6c28aaSamw * The function returns 0 when successful and error code when failed. 690da6c28aaSamw * If more is provided, the return value of 1 is returned indicating 691da6c28aaSamw * more entries; otherwise, 0 is returned. 692da6c28aaSamw */ 693da6c28aaSamw int smb_get_dents( 694da6c28aaSamw smb_request_t *sr, 695da6c28aaSamw uint32_t *cookie, 696da6c28aaSamw smb_node_t *dir_snode, 697*dc20a302Sas200622 uint32_t wildcards, 698da6c28aaSamw smb_dent_info_hdr_t *ihdr, 699da6c28aaSamw int *more) 700da6c28aaSamw { 701da6c28aaSamw int rc; 702da6c28aaSamw char *namebuf; 703da6c28aaSamw smb_node_t *snode; 704da6c28aaSamw smb_attr_t file_attr; 705da6c28aaSamw uint32_t maxcnt = ihdr->uio.uio_iovcnt; 706da6c28aaSamw char shortname[MANGLE_NAMELEN], name83[MANGLE_NAMELEN]; 707da6c28aaSamw fsvol_attr_t vol_attr; 708da6c28aaSamw 709da6c28aaSamw namebuf = kmem_zalloc(MAXNAMELEN, KM_SLEEP); 710da6c28aaSamw if (more) 711da6c28aaSamw *more = 0; 712da6c28aaSamw 713da6c28aaSamw if ((rc = fsd_getattr(&sr->tid_tree->t_fsd, &vol_attr)) != 0) { 714da6c28aaSamw kmem_free(namebuf, MAXNAMELEN); 715da6c28aaSamw return (rc); 716da6c28aaSamw } 717da6c28aaSamw 718da6c28aaSamw if (!wildcards) { 719da6c28aaSamw /* Already found entry? */ 720da6c28aaSamw if (*cookie != 0) 721da6c28aaSamw return (0); 722da6c28aaSamw shortname[0] = '\0'; 723da6c28aaSamw 724da6c28aaSamw rc = smb_fsop_lookup(sr, sr->user_cr, 0, sr->tid_tree->t_snode, 725da6c28aaSamw dir_snode, ihdr->pattern, &snode, &file_attr, shortname, 726da6c28aaSamw name83); 727da6c28aaSamw 728da6c28aaSamw if (rc) { 729da6c28aaSamw kmem_free(namebuf, MAXNAMELEN); 730da6c28aaSamw return (rc); 731da6c28aaSamw } 732da6c28aaSamw 733da6c28aaSamw (void) strlcpy(namebuf, ihdr->pattern, MAXNAMELEN); 734da6c28aaSamw 735da6c28aaSamw /* 736da6c28aaSamw * It is not necessary to set the "force" flag (i.e. to 737da6c28aaSamw * take into account mangling for case-insensitive collisions) 738da6c28aaSamw */ 739da6c28aaSamw 740da6c28aaSamw if (shortname[0] == '\0') 741da6c28aaSamw (void) smb_mangle_name(snode->attr.sa_vattr.va_nodeid, 742da6c28aaSamw namebuf, shortname, name83, 0); 743da6c28aaSamw (void) smb_gather_dents_info((char *)ihdr, 744da6c28aaSamw snode->attr.sa_vattr.va_nodeid, 745da6c28aaSamw strlen(namebuf), namebuf, -1, (int *)&maxcnt, 746da6c28aaSamw &snode->attr, snode, shortname, name83); 747da6c28aaSamw kmem_free(namebuf, MAXNAMELEN); 748da6c28aaSamw return (0); 749da6c28aaSamw } 750da6c28aaSamw 751da6c28aaSamw if ((rc = smb_fsop_getdents(sr, sr->user_cr, dir_snode, cookie, 752da6c28aaSamw 0, (int *)&maxcnt, (char *)ihdr, ihdr->pattern)) != 0) { 753da6c28aaSamw if (rc == ENOENT) { 754da6c28aaSamw kmem_free(namebuf, MAXNAMELEN); 755da6c28aaSamw return (0); 756da6c28aaSamw } 757da6c28aaSamw kmem_free(namebuf, MAXNAMELEN); 758da6c28aaSamw return (rc); 759da6c28aaSamw } 760da6c28aaSamw 761da6c28aaSamw if (*cookie != 0x7FFFFFFF && more) 762da6c28aaSamw *more = 1; 763da6c28aaSamw 764da6c28aaSamw kmem_free(namebuf, MAXNAMELEN); 765da6c28aaSamw return (0); 766da6c28aaSamw } 767da6c28aaSamw 768da6c28aaSamw 769da6c28aaSamw 770da6c28aaSamw 771da6c28aaSamw /* 772da6c28aaSamw * smb_gather_dents_info 773da6c28aaSamw * 774da6c28aaSamw * The function will accept information of each directory entry and put 775da6c28aaSamw * the needed information in the buffer. It is passed as the call back 776da6c28aaSamw * function for smb_fsop_getdents() to gather trans2 find info. 777da6c28aaSamw * 778da6c28aaSamw * If the buffer space is not enough, -1 will be returned. Regardless 779da6c28aaSamw * of valid entry or not, 0 will be returned; however, only valid entry 780da6c28aaSamw * will be stored in the buffer. 781da6c28aaSamw */ 782da6c28aaSamw int /*ARGSUSED*/ 783da6c28aaSamw smb_gather_dents_info( 784da6c28aaSamw char *args, 785da6c28aaSamw ino_t fileid, 786da6c28aaSamw int namelen, 787da6c28aaSamw char *name, 788da6c28aaSamw uint32_t cookie, 789da6c28aaSamw int32_t *countp, 790da6c28aaSamw smb_attr_t *attr, 791da6c28aaSamw smb_node_t *snode, 792da6c28aaSamw char *shortname, 793da6c28aaSamw char *name83) 794da6c28aaSamw { 795da6c28aaSamw /*LINTED E_BAD_PTR_CAST_ALIGN*/ 796da6c28aaSamw smb_dent_info_hdr_t *ihdr = (smb_dent_info_hdr_t *)args; 797da6c28aaSamw smb_dent_info_t *ient; 798*dc20a302Sas200622 uint8_t *v5_name = NULL; 799*dc20a302Sas200622 uint8_t *np = (uint8_t *)name; 800da6c28aaSamw int reclen = sizeof (smb_dent_info_t) + namelen; 801da6c28aaSamw 802da6c28aaSamw v5_name = kmem_alloc(MAXNAMELEN-1, KM_SLEEP); 803da6c28aaSamw 804da6c28aaSamw if (!ihdr->uio.uio_iovcnt || ihdr->uio.uio_resid < reclen) { 805da6c28aaSamw kmem_free(v5_name, MAXNAMELEN-1); 806da6c28aaSamw smb_node_release(snode); 807da6c28aaSamw return (-1); 808da6c28aaSamw } 809da6c28aaSamw 810da6c28aaSamw if (!smb_sattr_check(attr, name, ihdr->sattr)) { 811da6c28aaSamw kmem_free(v5_name, MAXNAMELEN-1); 812da6c28aaSamw smb_node_release(snode); 813da6c28aaSamw return (0); 814da6c28aaSamw } 815da6c28aaSamw 816da6c28aaSamw if (catia_callback) { 817*dc20a302Sas200622 catia_callback(v5_name, (uint8_t *)name, MAXNAMELEN-1); 818da6c28aaSamw np = v5_name; 819da6c28aaSamw reclen = sizeof (smb_dent_info_t) + strlen((char *)v5_name); 820da6c28aaSamw } 821da6c28aaSamw 822da6c28aaSamw ASSERT(snode); 823da6c28aaSamw ASSERT(snode->n_magic == SMB_NODE_MAGIC); 824da6c28aaSamw ASSERT(snode->n_state != SMB_NODE_STATE_DESTROYING); 825da6c28aaSamw 826da6c28aaSamw /* 827da6c28aaSamw * Each entry needs to be properly aligned or we may get an alignment 828da6c28aaSamw * fault on sparc. 829da6c28aaSamw */ 83055bf511dSas200622 ihdr->uio.uio_loffset = (offset_t)PTRALIGN(ihdr->uio.uio_loffset); 831da6c28aaSamw /*LINTED E_BAD_PTR_CAST_ALIGN*/ 83255bf511dSas200622 ient = (smb_dent_info_t *)&ihdr->iov->iov_base[ihdr->uio.uio_loffset]; 833da6c28aaSamw 834da6c28aaSamw ient->cookie = cookie; 835da6c28aaSamw ient->attr = *attr; 836da6c28aaSamw ient->snode = snode; 837da6c28aaSamw 838da6c28aaSamw (void) strcpy(ient->name, (char *)np); 839da6c28aaSamw (void) strcpy(ient->shortname, shortname); 840da6c28aaSamw (void) strcpy(ient->name83, name83); 841da6c28aaSamw ihdr->uio.uio_iov->iov_base = (char *)ient; 842da6c28aaSamw ihdr->uio.uio_iov->iov_len = reclen; 843da6c28aaSamw 844da6c28aaSamw ihdr->uio.uio_iov++; 845da6c28aaSamw ihdr->uio.uio_iovcnt--; 846da6c28aaSamw ihdr->uio.uio_resid -= reclen; 84755bf511dSas200622 ihdr->uio.uio_loffset += reclen; 848da6c28aaSamw 849da6c28aaSamw kmem_free(v5_name, MAXNAMELEN-1); 850da6c28aaSamw return (0); 851da6c28aaSamw } 852da6c28aaSamw 853da6c28aaSamw 854da6c28aaSamw 855da6c28aaSamw /* 856da6c28aaSamw * smb_trans2_find_process_ients 857da6c28aaSamw * 858da6c28aaSamw * This function encodes the directory entry information store in 859da6c28aaSamw * the iov structure of the ihdr structure. 860da6c28aaSamw * 861da6c28aaSamw * The total entries encoded will be returned. If the entries encoded 862da6c28aaSamw * is less than the total entries in the iov, the more field will 863da6c28aaSamw * be updated to 1. Also, the next cookie wil be updated as well. 864da6c28aaSamw */ 865da6c28aaSamw int 866da6c28aaSamw smb_trans2_find_process_ients( 867*dc20a302Sas200622 smb_request_t *sr, 868*dc20a302Sas200622 smb_xa_t *xa, 869da6c28aaSamw smb_dent_info_hdr_t *ihdr, 870*dc20a302Sas200622 uint16_t fflag, 871*dc20a302Sas200622 uint16_t infolev, 872da6c28aaSamw int maxdata, 873*dc20a302Sas200622 smb_node_t *dir_snode, 874da6c28aaSamw int *more, 875da6c28aaSamw uint32_t *cookie) 876da6c28aaSamw { 877da6c28aaSamw int i, err = 0; 878da6c28aaSamw smb_dent_info_t *ient; 879da6c28aaSamw uint32_t mb_flags = (sr->smb_flg2 & SMB_FLAGS2_UNICODE) 880da6c28aaSamw ? SMB_MSGBUF_UNICODE : 0; 881da6c28aaSamw 882da6c28aaSamw for (i = 0; i < SMB_MAX_DENTS_IOVEC; i++) { 883da6c28aaSamw /*LINTED E_BAD_PTR_CAST_ALIGN*/ 884da6c28aaSamw if ((ient = (smb_dent_info_t *)ihdr->iov[i].iov_base) == 0) 885da6c28aaSamw break; 886da6c28aaSamw 887da6c28aaSamw /* 888*dc20a302Sas200622 * Observed differences between our response and Windows 889*dc20a302Sas200622 * response, which hasn't caused a problem yet! 890da6c28aaSamw * 891*dc20a302Sas200622 * 1. The NextEntryOffset field for the last entry should 892*dc20a302Sas200622 * be 0. This code always calculate the record length 893*dc20a302Sas200622 * and puts the result in the NextEntryOffset field. 894da6c28aaSamw * 895*dc20a302Sas200622 * 2. The FileIndex field is always 0. This code puts 896*dc20a302Sas200622 * the cookie in the FileIndex field. 897da6c28aaSamw */ 898da6c28aaSamw err = smb_trans2_find_mbc_encode(sr, xa, ient, maxdata, infolev, 899da6c28aaSamw fflag, mb_flags, dir_snode, NULL); 900da6c28aaSamw 901da6c28aaSamw if (err) 902da6c28aaSamw break; 903da6c28aaSamw } 904da6c28aaSamw 905da6c28aaSamw /* 906*dc20a302Sas200622 * Not enough space to store all the entries returned, 907*dc20a302Sas200622 * which is indicated by setting more. 908da6c28aaSamw */ 909da6c28aaSamw if (more && err < 0) { 910da6c28aaSamw *more = 1; 911da6c28aaSamw 912da6c28aaSamw /* 913da6c28aaSamw * Assume the space will be at least enough for 1 entry. 914da6c28aaSamw */ 915da6c28aaSamw /*LINTED E_BAD_PTR_CAST_ALIGN*/ 916da6c28aaSamw ient = (smb_dent_info_t *)ihdr->iov[i-1].iov_base; 917da6c28aaSamw *cookie = ient->cookie; 918da6c28aaSamw } 919da6c28aaSamw return (i); 920da6c28aaSamw } 921da6c28aaSamw 922da6c28aaSamw /* 923da6c28aaSamw * smb_trans2_find_mbc_encode 924da6c28aaSamw * 925da6c28aaSamw * This function encodes the mbc for one directory entry. 926da6c28aaSamw * 927da6c28aaSamw * The function returns -1 when the max data requested by client 928da6c28aaSamw * is reached. If the entry is valid and successful encoded, 0 929da6c28aaSamw * will be returned; otherwise, 1 will be returned. 930da6c28aaSamw */ 931*dc20a302Sas200622 int /*ARGSUSED*/ 932*dc20a302Sas200622 smb_trans2_find_mbc_encode( 933*dc20a302Sas200622 smb_request_t *sr, 934*dc20a302Sas200622 smb_xa_t *xa, 935da6c28aaSamw smb_dent_info_t *ient, 936da6c28aaSamw int maxdata, 937*dc20a302Sas200622 uint16_t infolev, 938*dc20a302Sas200622 uint16_t fflag, 939*dc20a302Sas200622 uint32_t mb_flags, 940*dc20a302Sas200622 smb_node_t *dir_snode, 941*dc20a302Sas200622 smb_node_t *sd_snode) 942da6c28aaSamw { 943da6c28aaSamw int uni_namelen; 944*dc20a302Sas200622 int shortlen; 945*dc20a302Sas200622 uint32_t next_entry_offset; 946da6c28aaSamw char buf83[26]; 947da6c28aaSamw smb_msgbuf_t mb; 948da6c28aaSamw uint32_t dattr = 0; 949da6c28aaSamw uint32_t size32 = 0; 950da6c28aaSamw uint64_t size64 = 0; 951*dc20a302Sas200622 smb_node_t *lnk_snode; 952da6c28aaSamw smb_attr_t lnkattr; 953da6c28aaSamw int rc; 954da6c28aaSamw 955da6c28aaSamw uni_namelen = smb_ascii_or_unicode_strlen(sr, ient->name); 956da6c28aaSamw if (uni_namelen == -1) 957da6c28aaSamw return (1); 958da6c28aaSamw 959*dc20a302Sas200622 next_entry_offset = maxdata + uni_namelen; 960*dc20a302Sas200622 961da6c28aaSamw if (MBC_ROOM_FOR(&xa->rep_data_mb, (maxdata + uni_namelen)) == 0) 962da6c28aaSamw return (-1); 963da6c28aaSamw 964da6c28aaSamw if (ient->attr.sa_vattr.va_type == VLNK) { 965da6c28aaSamw rc = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS, 966da6c28aaSamw sr->tid_tree->t_snode, dir_snode, ient->name, &lnk_snode, 967da6c28aaSamw &lnkattr, 0, 0); 968da6c28aaSamw 969da6c28aaSamw /* 970da6c28aaSamw * We normally want to resolve the object to which a symlink 971da6c28aaSamw * refers so that CIFS clients can access sub-directories and 972da6c28aaSamw * find the correct association for files. This causes a 973da6c28aaSamw * problem, however, if a symlink in a sub-directory points 974da6c28aaSamw * to a parent directory (some UNIX GUI's create a symlink in 975da6c28aaSamw * $HOME/.desktop that points to the user's home directory). 976da6c28aaSamw * Some Windows applications (i.e. virus scanning) loop/hang 977da6c28aaSamw * trying to follow this recursive path and there is little 978da6c28aaSamw * we can do because the path is constructed on the client. 979*dc20a302Sas200622 * skc_dirsymlink_enable allows an end-user to disable 980da6c28aaSamw * symlinks to directories. Symlinks to other object types 981da6c28aaSamw * should be unaffected. 982da6c28aaSamw */ 983da6c28aaSamw if (rc == 0) { 984da6c28aaSamw if (smb_info.si.skc_dirsymlink_enable || 985da6c28aaSamw (lnkattr.sa_vattr.va_type != VDIR)) { 986da6c28aaSamw smb_node_release(ient->snode); 987da6c28aaSamw ient->snode = lnk_snode; 988da6c28aaSamw ient->attr = lnkattr; 989da6c28aaSamw } else { 990da6c28aaSamw smb_node_release(lnk_snode); 991da6c28aaSamw } 992da6c28aaSamw } 993da6c28aaSamw } 994da6c28aaSamw 995da6c28aaSamw if (infolev != SMB_FIND_FILE_NAMES_INFO) { 996da6c28aaSamw size64 = smb_node_get_size(ient->snode, &ient->attr); 997da6c28aaSamw size32 = (size64 > 0xFFFFFFFF) ? 0xFFFFFFFF : (uint32_t)size64; 998da6c28aaSamw dattr = smb_mode_to_dos_attributes(&ient->attr); 999da6c28aaSamw } 1000da6c28aaSamw 1001da6c28aaSamw switch (infolev) { 1002da6c28aaSamw case SMB_INFO_STANDARD: 1003da6c28aaSamw if (fflag & SMB_FIND_RETURN_RESUME_KEYS) 1004da6c28aaSamw (void) smb_encode_mbc(&xa->rep_data_mb, "l", 1005da6c28aaSamw ient->cookie); 1006da6c28aaSamw 1007da6c28aaSamw (void) smb_encode_mbc(&xa->rep_data_mb, "%yyyllwbu", sr, 1008da6c28aaSamw ient->attr.sa_crtime.tv_sec ? ient->attr.sa_crtime.tv_sec : 1009da6c28aaSamw ient->attr.sa_vattr.va_mtime.tv_sec, 1010da6c28aaSamw ient->attr.sa_vattr.va_atime.tv_sec, 1011da6c28aaSamw ient->attr.sa_vattr.va_mtime.tv_sec, 1012da6c28aaSamw size32, 1013da6c28aaSamw size32, 1014da6c28aaSamw dattr, 1015da6c28aaSamw uni_namelen, 1016da6c28aaSamw ient->name); 1017da6c28aaSamw break; 1018da6c28aaSamw 1019da6c28aaSamw case SMB_INFO_QUERY_EA_SIZE: 1020da6c28aaSamw if (fflag & SMB_FIND_RETURN_RESUME_KEYS) 1021*dc20a302Sas200622 (void) smb_encode_mbc(&xa->rep_data_mb, "l", 1022*dc20a302Sas200622 ient->cookie); 1023da6c28aaSamw 1024da6c28aaSamw (void) smb_encode_mbc(&xa->rep_data_mb, "%yyyllwlbu", sr, 1025da6c28aaSamw ient->attr.sa_crtime.tv_sec ? ient->attr.sa_crtime.tv_sec : 1026da6c28aaSamw ient->attr.sa_vattr.va_mtime.tv_sec, 1027da6c28aaSamw ient->attr.sa_vattr.va_atime.tv_sec, 1028da6c28aaSamw ient->attr.sa_vattr.va_mtime.tv_sec, 1029da6c28aaSamw size32, 1030da6c28aaSamw size32, 1031da6c28aaSamw dattr, 1032da6c28aaSamw 0L, /* EA Size */ 1033da6c28aaSamw uni_namelen, 1034da6c28aaSamw ient->name); 1035da6c28aaSamw break; 1036da6c28aaSamw 1037da6c28aaSamw case SMB_FIND_FILE_DIRECTORY_INFO: 1038da6c28aaSamw (void) smb_encode_mbc(&xa->rep_data_mb, "%llTTTTqqllu", sr, 1039*dc20a302Sas200622 next_entry_offset, 1040da6c28aaSamw ient->cookie, 1041da6c28aaSamw ient->attr.sa_crtime.tv_sec ? &ient->attr.sa_crtime : 1042da6c28aaSamw &ient->attr.sa_vattr.va_mtime, 1043da6c28aaSamw &ient->attr.sa_vattr.va_atime, 1044da6c28aaSamw &ient->attr.sa_vattr.va_mtime, 1045da6c28aaSamw &ient->attr.sa_vattr.va_ctime, 1046da6c28aaSamw size64, 1047da6c28aaSamw size64, 1048da6c28aaSamw dattr, 1049da6c28aaSamw uni_namelen, 1050da6c28aaSamw ient->name); 1051da6c28aaSamw break; 1052da6c28aaSamw 1053da6c28aaSamw case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: 1054da6c28aaSamw bzero(buf83, sizeof (buf83)); 1055*dc20a302Sas200622 smb_msgbuf_init(&mb, (uint8_t *)buf83, sizeof (buf83), 1056da6c28aaSamw mb_flags); 1057da6c28aaSamw if (smb_msgbuf_encode(&mb, "u", ient->shortname) < 0) { 1058da6c28aaSamw smb_msgbuf_term(&mb); 1059da6c28aaSamw return (-1); 1060da6c28aaSamw } 1061*dc20a302Sas200622 shortlen = smb_ascii_or_unicode_strlen(sr, ient->shortname); 1062da6c28aaSamw 1063*dc20a302Sas200622 (void) smb_encode_mbc(&xa->rep_data_mb, "%llTTTTqqlllb.24cu", 1064*dc20a302Sas200622 sr, 1065*dc20a302Sas200622 next_entry_offset, 1066da6c28aaSamw ient->cookie, 1067da6c28aaSamw ient->attr.sa_crtime.tv_sec ? &ient->attr.sa_crtime : 1068da6c28aaSamw &ient->attr.sa_vattr.va_mtime, 1069da6c28aaSamw &ient->attr.sa_vattr.va_atime, 1070da6c28aaSamw &ient->attr.sa_vattr.va_mtime, 1071da6c28aaSamw &ient->attr.sa_vattr.va_ctime, 1072da6c28aaSamw size64, 1073da6c28aaSamw size64, 1074da6c28aaSamw dattr, 1075da6c28aaSamw uni_namelen, 1076da6c28aaSamw 0L, 1077*dc20a302Sas200622 shortlen, 1078da6c28aaSamw buf83, 1079da6c28aaSamw ient->name); 1080da6c28aaSamw 1081da6c28aaSamw smb_msgbuf_term(&mb); 1082da6c28aaSamw break; 1083da6c28aaSamw 1084da6c28aaSamw case SMB_FIND_FILE_NAMES_INFO: 1085da6c28aaSamw (void) smb_encode_mbc(&xa->rep_data_mb, "%lllu", sr, 1086*dc20a302Sas200622 next_entry_offset, 1087da6c28aaSamw ient->cookie, 1088da6c28aaSamw uni_namelen, 1089da6c28aaSamw ient->name); 1090da6c28aaSamw break; 1091da6c28aaSamw } 1092da6c28aaSamw 1093da6c28aaSamw return (0); 1094da6c28aaSamw } 1095da6c28aaSamw 1096da6c28aaSamw /* 1097da6c28aaSamw * Close a search started by a Trans2FindFirst2 request. 1098da6c28aaSamw */ 1099da6c28aaSamw int 1100*dc20a302Sas200622 smb_com_find_close2(smb_request_t *sr) 1101da6c28aaSamw { 1102da6c28aaSamw if (smbsr_decode_vwv(sr, "w", &sr->smb_sid) != 0) { 1103da6c28aaSamw smbsr_decode_error(sr); 1104da6c28aaSamw /* NOTREACHED */ 1105da6c28aaSamw } 1106da6c28aaSamw 1107da6c28aaSamw sr->sid_odir = smb_odir_lookup_by_sid(sr->tid_tree, sr->smb_sid); 1108da6c28aaSamw if (sr->sid_odir == NULL) { 1109*dc20a302Sas200622 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 1110da6c28aaSamw /* NOTREACHED */ 1111da6c28aaSamw } 1112da6c28aaSamw 1113da6c28aaSamw smb_rdir_close(sr); 1114da6c28aaSamw smbsr_encode_empty_result(sr); 1115da6c28aaSamw return (SDRC_NORMAL_REPLY); 1116da6c28aaSamw } 1117