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