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 2010 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <smbsrv/smb_kproto.h> 27 28 /* 29 * smb_com_search 30 * smb_com_find, smb_com_find_close 31 * smb_find_unique 32 * 33 * These commands are used for directory searching. They share the same 34 * message formats, defined below: 35 * 36 * Client Request Description 37 * ---------------------------------- --------------------------------- 38 * 39 * UCHAR WordCount; Count of parameter words = 2 40 * USHORT MaxCount; Number of dir. entries to return 41 * USHORT SearchAttributes; 42 * USHORT ByteCount; Count of data bytes; min = 5 43 * UCHAR BufferFormat1; 0x04 -- ASCII 44 * UCHAR FileName[]; File name, may be null 45 * UCHAR BufferFormat2; 0x05 -- Variable block 46 * USHORT ResumeKeyLength; Length of resume key, may be 0 47 * UCHAR ResumeKey[]; Resume key 48 * 49 * FileName specifies the file to be sought. SearchAttributes indicates 50 * the attributes that the file must have. If SearchAttributes is 51 * zero then only normal files are returned. If the system file, hidden or 52 * directory attributes are specified then the search is inclusive - both the 53 * specified type(s) of files and normal files are returned. If the volume 54 * label attribute is specified then the search is exclusive, and only the 55 * volume label entry is returned. 56 * 57 * MaxCount specifies the number of directory entries to be returned. 58 * 59 * Server Response Description 60 * ---------------------------------- --------------------------------- 61 * 62 * UCHAR WordCount; Count of parameter words = 1 63 * USHORT Count; Number of entries returned 64 * USHORT ByteCount; Count of data bytes; min = 3 65 * UCHAR BufferFormat; 0x05 -- Variable block 66 * USHORT DataLength; Length of data 67 * UCHAR DirectoryInformationData[]; Data 68 * 69 * The response will contain one or more directory entries as determined by 70 * the Count field. No more than MaxCount entries will be returned. Only 71 * entries that match the sought FileName and SearchAttributes combination 72 * will be returned. 73 * 74 * ResumeKey must be null (length = 0) on the initial search request. 75 * Subsequent search requests intended to continue a search must contain 76 * the ResumeKey field extracted from the last directory entry of the 77 * previous response. ResumeKey is self-contained, for calls containing 78 * a non-zero ResumeKey neither the SearchAttributes or FileName fields 79 * will be valid in the request. ResumeKey has the following format: 80 * 81 * Resume Key Field Description 82 * ---------------------------------- --------------------------------- 83 * 84 * UCHAR Reserved; bit 7 - consumer use 85 * bits 5,6 - system use (must preserve) 86 * bits 0-4 - server use (must preserve) 87 * UCHAR FileName[11]; Name of the returned file 88 * UCHAR ReservedForServer[5]; Client must not modify 89 * byte 0 - uniquely identifies find 90 * through find_close 91 * bytes 1-4 - available for server use 92 * (must be non-zero) 93 * UCHAR ReservedForConsumer[4]; Server must not modify 94 * 95 * FileName is 8.3 format, with the three character extension left 96 * justified into FileName[9-11]. 97 * 98 * There may be multiple matching entries in response to a single request 99 * as wildcards are supported in the last component of FileName of the 100 * initial request. 101 * 102 * Returned directory entries in the DirectoryInformationData field of the 103 * response each have the following format: 104 * 105 * Directory Information Field Description 106 * ---------------------------------- --------------------------------- 107 * 108 * SMB_RESUME_KEY ResumeKey; Described above 109 * UCHAR FileAttributes; Attributes of the found file 110 * SMB_TIME LastWriteTime; Time file was last written 111 * SMB_DATE LastWriteDate; Date file was last written 112 * ULONG FileSize; Size of the file 113 * UCHAR FileName[13]; ASCII, space-filled null terminated 114 * 115 * FileName must conform to 8.3 rules, and is padded after the extension 116 * with 0x20 characters if necessary. 117 * 118 * As can be seen from the above structure, these commands cannot return 119 * long filenames, and cannot return UNICODE filenames. 120 * 121 * Files which have a size greater than 2^32 bytes should have the least 122 * significant 32 bits of their size returned in FileSize. 123 * 124 * smb_com_search 125 * -------------- 126 * 127 * If the client is prior to the LANMAN1.0 dialect, the returned FileName 128 * should be uppercased. 129 * If the client has negotiated a dialect prior to the LANMAN1.0 dialect, 130 * or if bit0 of the Flags2 SMB header field of the request is clear, 131 * the returned FileName should be uppercased. 132 * 133 * SMB_COM_SEARCH terminates when either the requested maximum number of 134 * entries that match the named file are found, or the end of directory is 135 * reached without the maximum number of matches being found. A response 136 * containing no entries indicates that no matching entries were found 137 * between the starting point of the search and the end of directory. 138 * 139 * 140 * The find, find_close and find_unique protocols may be used in place of 141 * the core "search" protocol when LANMAN 1.0 dialect has been negotiated. 142 * 143 * smb_com_find 144 * ------------ 145 * 146 * The find protocol is used to match the find OS/2 system call. 147 * 148 * The format of the find protocol is the same as the core "search" protocol. 149 * The difference is that the directory is logically Opened with a find protocol 150 * and logically closed with the find close protocol. 151 * As is true of a failing open, if a find request (find "first" request where 152 * resume_key is null) fails (no entries are found), no find close protocol is 153 * expected. 154 * 155 * If no global characters are present, a "find unique" protocol should be used 156 * (only one entry is expected and find close need not be sent). 157 * 158 * A find request will terminate when either the requested maximum number of 159 * entries that match the named file are found, or the end of directory is 160 * reached without the maximum number of matches being found. A response 161 * containing no entries indicates that no matching entries were found between 162 * the starting point of the search and the end of directory. 163 * 164 * If a find requests more data than can be placed in a message of the 165 * max-xmit-size for the TID specified, the server will return only the number 166 * of entries which will fit. 167 * 168 * 169 * smb_com_find_close 170 * ------------------ 171 * 172 * The find close protocol is used to match the find close OS/2 system call. 173 * 174 * Whereas the first find protocol logically opens the directory, subsequent 175 * find protocols presenting a resume_key further "read" the directory, the 176 * find close protocol "closes" the directory allowing the server to free any 177 * resources held in support of the directory search. 178 * 179 * In our implementation this translates to closing the odir. 180 * 181 * 182 * smb_com_find_unique 183 * ------------------- 184 * 185 * The format of the find unique protocol is the same as the core "search" 186 * protocol. The difference is that the directory is logically opened, any 187 * matching entries returned, and then the directory is logically closed. 188 * 189 * The resume search key key will be returned as in the find protocol and 190 * search protocol however it may NOT be returned to continue the search. 191 * Only one buffer of entries is expected and find close need not be sent. 192 * 193 * If a find unique requests more data than can be placed in a message of the 194 * max-xmit-size for the TID specified, the server will abort the virtual 195 * circuit to the consumer. 196 */ 197 198 /* *** smb_com_search *** */ 199 200 smb_sdrc_t 201 smb_pre_search(smb_request_t *sr) 202 { 203 DTRACE_SMB_1(op__Search__start, smb_request_t *, sr); 204 return (SDRC_SUCCESS); 205 } 206 207 void 208 smb_post_search(smb_request_t *sr) 209 { 210 DTRACE_SMB_1(op__Search__done, smb_request_t *, sr); 211 } 212 213 smb_sdrc_t 214 smb_com_search(smb_request_t *sr) 215 { 216 int rc; 217 uint16_t count, maxcount, index; 218 uint16_t sattr, odid; 219 uint16_t key_len; 220 uint32_t client_key; 221 char name[SMB_SHORTNAMELEN]; 222 smb_pathname_t *pn; 223 unsigned char resume_char; 224 unsigned char type; 225 boolean_t find_first, to_upper; 226 smb_tree_t *tree; 227 smb_odir_t *od; 228 smb_fileinfo_t fileinfo; 229 smb_odir_resume_t odir_resume; 230 boolean_t eos; 231 232 to_upper = B_FALSE; 233 if ((sr->session->dialect <= LANMAN1_0) || 234 ((sr->smb_flg2 & SMB_FLAGS2_KNOWS_LONG_NAMES) == 0)) { 235 to_upper = B_TRUE; 236 } 237 238 /* We only handle 8.3 name here */ 239 sr->smb_flg2 &= ~SMB_FLAGS2_KNOWS_LONG_NAMES; 240 sr->smb_flg &= ~SMB_FLAGS_CASE_INSENSITIVE; 241 242 if (smbsr_decode_vwv(sr, "ww", &maxcount, &sattr) != 0) 243 return (SDRC_ERROR); 244 245 pn = &sr->arg.dirop.fqi.fq_path; 246 rc = smbsr_decode_data(sr, "%Abw", sr, &pn->pn_path, &type, &key_len); 247 if ((rc != 0) || (type != 0x05)) 248 return (SDRC_ERROR); 249 250 smb_pathname_init(sr, pn, pn->pn_path); 251 if (!smb_pathname_validate(sr, pn) || 252 smb_is_stream_name(pn->pn_path)) { 253 smbsr_warn(sr, NT_STATUS_NO_MORE_FILES, 254 ERRDOS, ERROR_NO_MORE_FILES); 255 return (SDRC_ERROR); 256 } 257 258 tree = sr->tid_tree; 259 260 /* Volume information only */ 261 if ((sattr == FILE_ATTRIBUTE_VOLUME) && (key_len != 21)) { 262 (void) memset(name, ' ', sizeof (name)); 263 (void) strncpy(name, tree->t_volume, sizeof (name)); 264 265 if (key_len >= 21) { 266 (void) smb_mbc_decodef(&sr->smb_data, "17.l", 267 &client_key); 268 } else { 269 client_key = 0; 270 } 271 272 (void) smb_mbc_encodef(&sr->reply, "bwwbwb11c5.lb8.13c", 273 1, 0, VAR_BCC, 5, 0, 0, pn->pn_path+1, 274 client_key, sattr, name); 275 276 rc = (sr->reply.chain_offset - sr->cur_reply_offset) - 8; 277 (void) smb_mbc_poke(&sr->reply, sr->cur_reply_offset, "bwwbw", 278 1, 1, rc+3, 5, rc); 279 280 return (SDRC_SUCCESS); 281 } 282 283 if ((key_len != 0) && (key_len != 21)) 284 return (SDRC_ERROR); 285 286 find_first = (key_len == 0); 287 resume_char = 0; 288 client_key = 0; 289 290 if (find_first) { 291 odid = smb_odir_open(sr, pn->pn_path, sattr, 0); 292 if (odid == 0) { 293 if (sr->smb_error.status == NT_STATUS_ACCESS_DENIED) 294 smbsr_warn(sr, NT_STATUS_NO_MORE_FILES, 295 ERRDOS, ERROR_NO_MORE_FILES); 296 return (SDRC_ERROR); 297 } 298 } else { 299 if (smb_mbc_decodef(&sr->smb_data, "b12.wwl", 300 &resume_char, &index, &odid, &client_key) != 0) { 301 return (SDRC_ERROR); 302 } 303 } 304 305 od = smb_tree_lookup_odir(sr->tid_tree, odid); 306 if (od == NULL) { 307 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, 308 ERRDOS, ERROR_INVALID_HANDLE); 309 return (SDRC_ERROR); 310 } 311 312 if (!find_first) { 313 odir_resume.or_type = SMB_ODIR_RESUME_IDX; 314 odir_resume.or_idx = index; 315 smb_odir_resume_at(od, &odir_resume); 316 } 317 318 (void) smb_mbc_encodef(&sr->reply, "bwwbw", 1, 0, VAR_BCC, 5, 0); 319 320 rc = 0; 321 index = 0; 322 count = 0; 323 if (maxcount > SMB_MAX_SEARCH) 324 maxcount = SMB_MAX_SEARCH; 325 326 while (count < maxcount) { 327 rc = smb_odir_read_fileinfo(sr, od, &fileinfo, &eos); 328 if ((rc != 0 || (eos == B_TRUE))) 329 break; 330 331 (void) memset(name, ' ', sizeof (name)); 332 if (*fileinfo.fi_shortname == '\0') { 333 (void) strlcpy(name, fileinfo.fi_name, 334 SMB_SHORTNAMELEN - 1); 335 if (to_upper) 336 (void) smb_strupr(name); 337 } else { 338 (void) strlcpy(name, fileinfo.fi_shortname, 339 SMB_SHORTNAMELEN - 1); 340 } 341 342 (void) smb_mbc_encodef(&sr->reply, "b8c3c.wwlbYl13c", 343 resume_char, 344 fileinfo.fi_name83, fileinfo.fi_name83+9, 345 index, odid, client_key, 346 fileinfo.fi_dosattr & 0xff, 347 smb_time_gmt_to_local(sr, fileinfo.fi_mtime.tv_sec), 348 (int32_t)fileinfo.fi_size, 349 name); 350 351 smb_odir_save_cookie(od, index, fileinfo.fi_cookie); 352 353 count++; 354 index++; 355 } 356 357 if (rc != 0) { 358 smb_odir_close(od); 359 smb_odir_release(od); 360 return (SDRC_ERROR); 361 } 362 363 if (count == 0 && find_first) { 364 smb_odir_close(od); 365 smb_odir_release(od); 366 smbsr_warn(sr, NT_STATUS_NO_MORE_FILES, 367 ERRDOS, ERROR_NO_MORE_FILES); 368 return (SDRC_ERROR); 369 } 370 371 rc = (sr->reply.chain_offset - sr->cur_reply_offset) - 8; 372 if (smb_mbc_poke(&sr->reply, sr->cur_reply_offset, "bwwbw", 373 1, count, rc+3, 5, rc) < 0) { 374 smb_odir_close(od); 375 smb_odir_release(od); 376 return (SDRC_ERROR); 377 } 378 379 smb_odir_release(od); 380 return (SDRC_SUCCESS); 381 } 382 383 384 /* *** smb_com_find *** */ 385 386 smb_sdrc_t 387 smb_pre_find(smb_request_t *sr) 388 { 389 DTRACE_SMB_1(op__Find__start, smb_request_t *, sr); 390 return (SDRC_SUCCESS); 391 } 392 393 void 394 smb_post_find(smb_request_t *sr) 395 { 396 DTRACE_SMB_1(op__Find__done, smb_request_t *, sr); 397 } 398 399 smb_sdrc_t 400 smb_com_find(smb_request_t *sr) 401 { 402 int rc; 403 uint16_t count, maxcount, index; 404 uint16_t sattr, odid; 405 uint16_t key_len; 406 uint32_t client_key; 407 char name[SMB_SHORTNAMELEN]; 408 smb_odir_t *od; 409 smb_fileinfo_t fileinfo; 410 boolean_t eos; 411 412 smb_pathname_t *pn; 413 unsigned char resume_char; 414 unsigned char type; 415 boolean_t find_first = B_TRUE; 416 smb_odir_resume_t odir_resume; 417 418 if (smbsr_decode_vwv(sr, "ww", &maxcount, &sattr) != 0) 419 return (SDRC_ERROR); 420 421 pn = &sr->arg.dirop.fqi.fq_path; 422 rc = smbsr_decode_data(sr, "%Abw", sr, &pn->pn_path, &type, &key_len); 423 if ((rc != 0) || (type != 0x05)) 424 return (SDRC_ERROR); 425 426 if ((key_len != 0) && (key_len != 21)) 427 return (SDRC_ERROR); 428 429 smb_pathname_init(sr, pn, pn->pn_path); 430 if (!smb_pathname_validate(sr, pn)) 431 return (SDRC_ERROR); 432 433 if (smb_is_stream_name(pn->pn_path)) { 434 smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID, 435 ERRDOS, ERROR_INVALID_NAME); 436 return (SDRC_ERROR); 437 } 438 439 find_first = (key_len == 0); 440 resume_char = 0; 441 client_key = 0; 442 443 if (find_first) { 444 odid = smb_odir_open(sr, pn->pn_path, sattr, 0); 445 if (odid == 0) 446 return (SDRC_ERROR); 447 } else { 448 if (smb_mbc_decodef(&sr->smb_data, "b12.wwl", 449 &resume_char, &index, &odid, &client_key) != 0) { 450 return (SDRC_ERROR); 451 } 452 } 453 454 od = smb_tree_lookup_odir(sr->tid_tree, odid); 455 if (od == NULL) { 456 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, 457 ERRDOS, ERROR_INVALID_HANDLE); 458 return (SDRC_ERROR); 459 } 460 461 if (!find_first) { 462 odir_resume.or_type = SMB_ODIR_RESUME_IDX; 463 odir_resume.or_idx = index; 464 smb_odir_resume_at(od, &odir_resume); 465 } 466 467 (void) smb_mbc_encodef(&sr->reply, "bwwbw", 1, 0, VAR_BCC, 5, 0); 468 469 rc = 0; 470 index = 0; 471 count = 0; 472 if (maxcount > SMB_MAX_SEARCH) 473 maxcount = SMB_MAX_SEARCH; 474 475 while (count < maxcount) { 476 rc = smb_odir_read_fileinfo(sr, od, &fileinfo, &eos); 477 if ((rc != 0 || (eos == B_TRUE))) 478 break; 479 480 (void) memset(name, ' ', sizeof (name)); 481 if (*fileinfo.fi_shortname == '\0') { 482 (void) strlcpy(name, fileinfo.fi_name, 483 SMB_SHORTNAMELEN - 1); 484 } else { 485 (void) strlcpy(name, fileinfo.fi_shortname, 486 SMB_SHORTNAMELEN - 1); 487 } 488 489 (void) smb_mbc_encodef(&sr->reply, "b8c3c.wwlbYl13c", 490 resume_char, 491 fileinfo.fi_name83, fileinfo.fi_name83+9, 492 index, odid, client_key, 493 fileinfo.fi_dosattr & 0xff, 494 smb_time_gmt_to_local(sr, fileinfo.fi_mtime.tv_sec), 495 (int32_t)fileinfo.fi_size, 496 name); 497 498 smb_odir_save_cookie(od, index, fileinfo.fi_cookie); 499 500 count++; 501 index++; 502 } 503 504 if (rc != 0) { 505 smb_odir_close(od); 506 smb_odir_release(od); 507 return (SDRC_ERROR); 508 } 509 510 if (count == 0 && find_first) { 511 smb_odir_close(od); 512 smb_odir_release(od); 513 smbsr_warn(sr, NT_STATUS_NO_MORE_FILES, 514 ERRDOS, ERROR_NO_MORE_FILES); 515 return (SDRC_ERROR); 516 } 517 518 rc = (MBC_LENGTH(&sr->reply) - sr->cur_reply_offset) - 8; 519 if (smb_mbc_poke(&sr->reply, sr->cur_reply_offset, "bwwbw", 520 1, count, rc+3, 5, rc) < 0) { 521 smb_odir_close(od); 522 smb_odir_release(od); 523 return (SDRC_ERROR); 524 } 525 526 smb_odir_release(od); 527 return (SDRC_SUCCESS); 528 } 529 530 531 /* *** smb_com_find_close *** */ 532 533 smb_sdrc_t 534 smb_pre_find_close(smb_request_t *sr) 535 { 536 DTRACE_SMB_1(op__FindClose__start, smb_request_t *, sr); 537 return (SDRC_SUCCESS); 538 } 539 540 void 541 smb_post_find_close(smb_request_t *sr) 542 { 543 DTRACE_SMB_1(op__FindClose__done, smb_request_t *, sr); 544 } 545 546 smb_sdrc_t 547 smb_com_find_close(smb_request_t *sr) 548 { 549 int rc; 550 uint16_t maxcount, index; 551 uint16_t sattr, odid; 552 uint16_t key_len; 553 uint32_t client_key; 554 char *path; 555 unsigned char resume_char; 556 unsigned char type; 557 smb_odir_t *od; 558 559 if (smbsr_decode_vwv(sr, "ww", &maxcount, &sattr) != 0) 560 return (SDRC_ERROR); 561 562 rc = smbsr_decode_data(sr, "%Abw", sr, &path, &type, &key_len); 563 if ((rc != 0) || (type != 0x05)) 564 return (SDRC_ERROR); 565 566 if (key_len == 0) { 567 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, 568 ERRDOS, ERROR_INVALID_HANDLE); 569 return (SDRC_ERROR); 570 } else if (key_len != 21) { 571 return (SDRC_ERROR); 572 } 573 574 odid = 0; 575 if (smb_mbc_decodef(&sr->smb_data, "b12.wwl", 576 &resume_char, &index, &odid, &client_key) != 0) { 577 return (SDRC_ERROR); 578 } 579 580 od = smb_tree_lookup_odir(sr->tid_tree, odid); 581 if (od == NULL) { 582 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, 583 ERRDOS, ERROR_INVALID_HANDLE); 584 return (SDRC_ERROR); 585 } 586 587 smb_odir_close(od); 588 smb_odir_release(od); 589 590 if (smbsr_encode_result(sr, 1, 3, "bwwbw", 1, 0, 3, 5, 0)) 591 return (SDRC_ERROR); 592 593 return (SDRC_SUCCESS); 594 } 595 596 597 /* *** smb_com_find_unique *** */ 598 599 smb_sdrc_t 600 smb_pre_find_unique(smb_request_t *sr) 601 { 602 DTRACE_SMB_1(op__FindUnique__start, smb_request_t *, sr); 603 return (SDRC_SUCCESS); 604 } 605 606 void 607 smb_post_find_unique(smb_request_t *sr) 608 { 609 DTRACE_SMB_1(op__FindUnique__done, smb_request_t *, sr); 610 } 611 612 smb_sdrc_t 613 smb_com_find_unique(struct smb_request *sr) 614 { 615 int rc; 616 uint16_t count, maxcount, index; 617 uint16_t sattr, odid; 618 smb_pathname_t *pn; 619 unsigned char resume_char = '\0'; 620 uint32_t client_key = 0; 621 char name[SMB_SHORTNAMELEN]; 622 smb_odir_t *od; 623 smb_fileinfo_t fileinfo; 624 boolean_t eos; 625 smb_vdb_t *vdb; 626 627 if (smbsr_decode_vwv(sr, "ww", &maxcount, &sattr) != 0) 628 return (SDRC_ERROR); 629 630 pn = &sr->arg.dirop.fqi.fq_path; 631 vdb = kmem_alloc(sizeof (smb_vdb_t), KM_SLEEP); 632 if ((smbsr_decode_data(sr, "%AV", sr, &pn->pn_path, vdb) != 0) || 633 (vdb->vdb_len != 0)) { 634 kmem_free(vdb, sizeof (smb_vdb_t)); 635 return (SDRC_ERROR); 636 } 637 kmem_free(vdb, sizeof (smb_vdb_t)); 638 639 smb_pathname_init(sr, pn, pn->pn_path); 640 if (!smb_pathname_validate(sr, pn)) 641 return (SDRC_ERROR); 642 643 if (smb_is_stream_name(pn->pn_path)) { 644 smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID, 645 ERRDOS, ERROR_INVALID_NAME); 646 return (SDRC_ERROR); 647 } 648 649 (void) smb_mbc_encodef(&sr->reply, "bwwbw", 1, 0, VAR_BCC, 5, 0); 650 651 odid = smb_odir_open(sr, pn->pn_path, sattr, 0); 652 if (odid == 0) 653 return (SDRC_ERROR); 654 od = smb_tree_lookup_odir(sr->tid_tree, odid); 655 if (od == NULL) 656 return (SDRC_ERROR); 657 658 rc = 0; 659 count = 0; 660 index = 0; 661 if (maxcount > SMB_MAX_SEARCH) 662 maxcount = SMB_MAX_SEARCH; 663 664 while (count < maxcount) { 665 rc = smb_odir_read_fileinfo(sr, od, &fileinfo, &eos); 666 if ((rc != 0 || (eos == B_TRUE))) 667 break; 668 669 (void) memset(name, ' ', sizeof (name)); 670 if (*fileinfo.fi_shortname == '\0') { 671 (void) strlcpy(name, fileinfo.fi_name, 672 SMB_SHORTNAMELEN - 1); 673 } else { 674 (void) strlcpy(name, fileinfo.fi_shortname, 675 SMB_SHORTNAMELEN - 1); 676 } 677 678 (void) smb_mbc_encodef(&sr->reply, "b8c3c.wwlbYl13c", 679 resume_char, 680 fileinfo.fi_name83, fileinfo.fi_name83+9, 681 index, odid, client_key, 682 fileinfo.fi_dosattr & 0xff, 683 smb_time_gmt_to_local(sr, fileinfo.fi_mtime.tv_sec), 684 (int32_t)fileinfo.fi_size, 685 name); 686 687 count++; 688 index++; 689 } 690 691 smb_odir_close(od); 692 smb_odir_release(od); 693 694 if (rc != 0) 695 return (SDRC_ERROR); 696 697 if (count == 0) { 698 smbsr_warn(sr, NT_STATUS_NO_MORE_FILES, 699 ERRDOS, ERROR_NO_MORE_FILES); 700 return (SDRC_ERROR); 701 } 702 703 rc = (MBC_LENGTH(&sr->reply) - sr->cur_reply_offset) - 8; 704 if (smb_mbc_poke(&sr->reply, sr->cur_reply_offset, 705 "bwwbw", 1, count, rc+3, 5, rc) < 0) { 706 return (SDRC_ERROR); 707 } 708 709 return (SDRC_SUCCESS); 710 } 711