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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  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
 
 
 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 #define SMB_NAME83_BUFLEN       12
 199 static void smb_name83(const char *, char *, size_t);
 200 
 201 /* *** smb_com_search *** */
 202 
 203 smb_sdrc_t
 204 smb_pre_search(smb_request_t *sr)
 205 {
 206         DTRACE_SMB_1(op__Search__start, smb_request_t *, sr);
 207         return (SDRC_SUCCESS);
 208 }
 209 
 210 void
 211 smb_post_search(smb_request_t *sr)
 212 {
 213         DTRACE_SMB_1(op__Search__done, smb_request_t *, sr);
 214 }
 215 
 216 smb_sdrc_t
 217 smb_com_search(smb_request_t *sr)
 218 {
 219         int                     rc;
 220         uint16_t                count, maxcount, index;
 221         uint16_t                sattr, odid;
 222         uint16_t                key_len;
 223         uint32_t                client_key;
 224         char                    name[SMB_SHORTNAMELEN];
 225         char                    name83[SMB_SHORTNAMELEN];
 226         smb_pathname_t          *pn;
 227         unsigned char           resume_char;
 228         unsigned char           type;
 229         boolean_t               find_first, to_upper;
 230         smb_tree_t              *tree;
 231         smb_odir_t              *od;
 232         smb_fileinfo_t          fileinfo;
 233         smb_odir_resume_t       odir_resume;
 
 283                     1, 1, rc+3, 5, rc);
 284 
 285                 return (SDRC_SUCCESS);
 286         }
 287 
 288         if ((key_len != 0) && (key_len != 21))
 289                 return (SDRC_ERROR);
 290 
 291         find_first = (key_len == 0);
 292         resume_char = 0;
 293         client_key = 0;
 294 
 295         if (find_first) {
 296                 status = smb_odir_openpath(sr, pn->pn_path, sattr, 0, &od);
 297                 if (status != 0) {
 298                         if (status == NT_STATUS_ACCESS_DENIED)
 299                                 smbsr_warn(sr, NT_STATUS_NO_MORE_FILES,
 300                                     ERRDOS, ERROR_NO_MORE_FILES);
 301                         return (SDRC_ERROR);
 302                 }
 303         } else {
 304                 if (smb_mbc_decodef(&sr->smb_data, "b12.wwl",
 305                     &resume_char, &index, &odid, &client_key) != 0) {
 306                         return (SDRC_ERROR);
 307                 }
 308                 od = smb_tree_lookup_odir(sr, odid);
 309         }
 310 
 311         if (od == NULL) {
 312                 smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
 313                     ERRDOS, ERROR_INVALID_HANDLE);
 314                 return (SDRC_ERROR);
 315         }
 316 
 317         if (!find_first) {
 318                 if ((od->d_flags & SMB_ODIR_FLAG_WILDCARDS) == 0) {
 319                         od->d_eof = B_TRUE;
 320                 } else {
 321                         odir_resume.or_type = SMB_ODIR_RESUME_IDX;
 322                         odir_resume.or_idx = index;
 
 377         }
 378 
 379         rc = (sr->reply.chain_offset - sr->cur_reply_offset) - 8;
 380         if (smb_mbc_poke(&sr->reply, sr->cur_reply_offset, "bwwbw",
 381             1, count, rc+3, 5, rc) < 0) {
 382                 smb_odir_close(od);
 383                 smb_odir_release(od);
 384                 return (SDRC_ERROR);
 385         }
 386 
 387         smb_odir_release(od);
 388         return (SDRC_SUCCESS);
 389 }
 390 
 391 
 392 /* *** smb_com_find *** */
 393 
 394 smb_sdrc_t
 395 smb_pre_find(smb_request_t *sr)
 396 {
 397         DTRACE_SMB_1(op__Find__start, smb_request_t *, sr);
 398         return (SDRC_SUCCESS);
 399 }
 400 
 401 void
 402 smb_post_find(smb_request_t *sr)
 403 {
 404         DTRACE_SMB_1(op__Find__done, smb_request_t *, sr);
 405 }
 406 
 407 smb_sdrc_t
 408 smb_com_find(smb_request_t *sr)
 409 {
 410         int                     rc;
 411         uint16_t                count, maxcount, index;
 412         uint16_t                sattr, odid;
 413         uint16_t                key_len;
 414         uint32_t                client_key;
 415         char                    name83[SMB_SHORTNAMELEN];
 416         smb_odir_t              *od;
 417         smb_fileinfo_t          fileinfo;
 418         uint32_t                status;
 419         uint16_t                eos;
 420 
 421         smb_pathname_t          *pn;
 422         unsigned char           resume_char;
 423         unsigned char           type;
 424         boolean_t               find_first = B_TRUE;
 
 438         smb_pathname_init(sr, pn, pn->pn_path);
 439         if (!smb_pathname_validate(sr, pn))
 440                 return (SDRC_ERROR);
 441 
 442         if (smb_is_stream_name(pn->pn_path)) {
 443                 smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID,
 444                     ERRDOS, ERROR_INVALID_NAME);
 445                 return (SDRC_ERROR);
 446         }
 447 
 448         find_first = (key_len == 0);
 449         resume_char = 0;
 450         client_key = 0;
 451 
 452         if (find_first) {
 453                 status = smb_odir_openpath(sr, pn->pn_path, sattr, 0, &od);
 454                 if (status != 0) {
 455                         smbsr_error(sr, status, 0, 0);
 456                         return (SDRC_ERROR);
 457                 }
 458         } else {
 459                 if (smb_mbc_decodef(&sr->smb_data, "b12.wwl",
 460                     &resume_char, &index, &odid, &client_key) != 0) {
 461                         return (SDRC_ERROR);
 462                 }
 463                 od = smb_tree_lookup_odir(sr, odid);
 464         }
 465 
 466         if (od == NULL) {
 467                 smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
 468                     ERRDOS, ERROR_INVALID_HANDLE);
 469                 return (SDRC_ERROR);
 470         }
 471 
 472         if (!find_first) {
 473                 if ((od->d_flags & SMB_ODIR_FLAG_WILDCARDS) == 0) {
 474                         od->d_eof = B_TRUE;
 475                 } else {
 476                         odir_resume.or_type = SMB_ODIR_RESUME_IDX;
 477                         odir_resume.or_idx = index;
 
 530         }
 531 
 532         rc = (MBC_LENGTH(&sr->reply) - sr->cur_reply_offset) - 8;
 533         if (smb_mbc_poke(&sr->reply, sr->cur_reply_offset, "bwwbw",
 534             1, count, rc+3, 5, rc) < 0) {
 535                 smb_odir_close(od);
 536                 smb_odir_release(od);
 537                 return (SDRC_ERROR);
 538         }
 539 
 540         smb_odir_release(od);
 541         return (SDRC_SUCCESS);
 542 }
 543 
 544 
 545 /* *** smb_com_find_close *** */
 546 
 547 smb_sdrc_t
 548 smb_pre_find_close(smb_request_t *sr)
 549 {
 550         DTRACE_SMB_1(op__FindClose__start, smb_request_t *, sr);
 551         return (SDRC_SUCCESS);
 552 }
 553 
 554 void
 555 smb_post_find_close(smb_request_t *sr)
 556 {
 557         DTRACE_SMB_1(op__FindClose__done, smb_request_t *, sr);
 558 }
 559 
 560 smb_sdrc_t
 561 smb_com_find_close(smb_request_t *sr)
 562 {
 563         int             rc;
 564         uint16_t        maxcount, index;
 565         uint16_t        sattr, odid;
 566         uint16_t        key_len;
 567         uint32_t        client_key;
 568         char            *path;
 569         unsigned char   resume_char;
 570         unsigned char   type;
 571         smb_odir_t      *od;
 572 
 573         if (smbsr_decode_vwv(sr, "ww", &maxcount, &sattr) != 0)
 574                 return (SDRC_ERROR);
 575 
 576         rc = smbsr_decode_data(sr, "%Abw", sr, &path, &type, &key_len);
 577         if ((rc != 0) || (type != 0x05))
 
 596                 smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
 597                     ERRDOS, ERROR_INVALID_HANDLE);
 598                 return (SDRC_ERROR);
 599         }
 600 
 601         smb_odir_close(od);
 602         smb_odir_release(od);
 603 
 604         if (smbsr_encode_result(sr, 1, 3, "bwwbw", 1, 0, 3, 5, 0))
 605                 return (SDRC_ERROR);
 606 
 607         return (SDRC_SUCCESS);
 608 }
 609 
 610 
 611 /* *** smb_com_find_unique *** */
 612 
 613 smb_sdrc_t
 614 smb_pre_find_unique(smb_request_t *sr)
 615 {
 616         DTRACE_SMB_1(op__FindUnique__start, smb_request_t *, sr);
 617         return (SDRC_SUCCESS);
 618 }
 619 
 620 void
 621 smb_post_find_unique(smb_request_t *sr)
 622 {
 623         DTRACE_SMB_1(op__FindUnique__done, smb_request_t *, sr);
 624 }
 625 
 626 smb_sdrc_t
 627 smb_com_find_unique(struct smb_request *sr)
 628 {
 629         int                     rc;
 630         uint16_t                count, maxcount, index;
 631         uint16_t                sattr;
 632         smb_pathname_t          *pn;
 633         unsigned char           resume_char = '\0';
 634         uint32_t                client_key = 0;
 635         char                    name83[SMB_SHORTNAMELEN];
 636         smb_odir_t              *od;
 637         smb_fileinfo_t          fileinfo;
 638         uint32_t                status;
 639         uint16_t                eos;
 640         smb_vdb_t               *vdb;
 641 
 642         if (smbsr_decode_vwv(sr, "ww", &maxcount, &sattr) != 0)
 643                 return (SDRC_ERROR);
 
 674         rc = 0;
 675         count = 0;
 676         index = 0;
 677         if (maxcount > SMB_MAX_SEARCH)
 678                 maxcount = SMB_MAX_SEARCH;
 679 
 680         while (count < maxcount) {
 681                 rc = smb_odir_read_fileinfo(sr, od, &fileinfo, &eos);
 682                 if (rc != 0 || eos != 0)
 683                         break;
 684 
 685                 if (*fileinfo.fi_shortname == '\0') {
 686                         if (smb_needs_mangled(fileinfo.fi_name))
 687                                 continue;
 688                         (void) strlcpy(fileinfo.fi_shortname, fileinfo.fi_name,
 689                             SMB_SHORTNAMELEN - 1);
 690                 }
 691                 smb_name83(fileinfo.fi_shortname, name83, SMB_SHORTNAMELEN);
 692 
 693                 (void) smb_mbc_encodef(&sr->reply, "b11c.wwlbYl13c",
 694                     resume_char, name83, index, od->d_odid,
 695                     client_key, fileinfo.fi_dosattr & 0xff,
 696                     smb_time_gmt_to_local(sr, fileinfo.fi_mtime.tv_sec),
 697                     (int32_t)fileinfo.fi_size,
 698                     fileinfo.fi_shortname);
 699 
 700                 count++;
 701                 index++;
 702         }
 703         if (eos && rc == ENOENT)
 704                 rc = 0;
 705 
 706         smb_odir_close(od);
 707         smb_odir_release(od);
 708 
 709         if (rc != 0)
 710                 return (SDRC_ERROR);
 711 
 712         if (count == 0) {
 713                 smbsr_warn(sr, NT_STATUS_NO_MORE_FILES,
 714                     ERRDOS, ERROR_NO_MORE_FILES);
 715                 return (SDRC_ERROR);
 
 | 
 
 
   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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  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
 
 
 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 #define SMB_NAME83_BUFLEN       12
 199 static void smb_name83(const char *, char *, size_t);
 200 
 201 /* *** smb_com_search *** */
 202 
 203 smb_sdrc_t
 204 smb_pre_search(smb_request_t *sr)
 205 {
 206         DTRACE_SMB_START(op__Search, smb_request_t *, sr);
 207         return (SDRC_SUCCESS);
 208 }
 209 
 210 void
 211 smb_post_search(smb_request_t *sr)
 212 {
 213         DTRACE_SMB_DONE(op__Search, smb_request_t *, sr);
 214 }
 215 
 216 smb_sdrc_t
 217 smb_com_search(smb_request_t *sr)
 218 {
 219         int                     rc;
 220         uint16_t                count, maxcount, index;
 221         uint16_t                sattr, odid;
 222         uint16_t                key_len;
 223         uint32_t                client_key;
 224         char                    name[SMB_SHORTNAMELEN];
 225         char                    name83[SMB_SHORTNAMELEN];
 226         smb_pathname_t          *pn;
 227         unsigned char           resume_char;
 228         unsigned char           type;
 229         boolean_t               find_first, to_upper;
 230         smb_tree_t              *tree;
 231         smb_odir_t              *od;
 232         smb_fileinfo_t          fileinfo;
 233         smb_odir_resume_t       odir_resume;
 
 283                     1, 1, rc+3, 5, rc);
 284 
 285                 return (SDRC_SUCCESS);
 286         }
 287 
 288         if ((key_len != 0) && (key_len != 21))
 289                 return (SDRC_ERROR);
 290 
 291         find_first = (key_len == 0);
 292         resume_char = 0;
 293         client_key = 0;
 294 
 295         if (find_first) {
 296                 status = smb_odir_openpath(sr, pn->pn_path, sattr, 0, &od);
 297                 if (status != 0) {
 298                         if (status == NT_STATUS_ACCESS_DENIED)
 299                                 smbsr_warn(sr, NT_STATUS_NO_MORE_FILES,
 300                                     ERRDOS, ERROR_NO_MORE_FILES);
 301                         return (SDRC_ERROR);
 302                 }
 303                 odid = od->d_odid;
 304         } else {
 305                 if (smb_mbc_decodef(&sr->smb_data, "b12.wwl",
 306                     &resume_char, &index, &odid, &client_key) != 0) {
 307                         return (SDRC_ERROR);
 308                 }
 309                 od = smb_tree_lookup_odir(sr, odid);
 310         }
 311 
 312         if (od == NULL) {
 313                 smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
 314                     ERRDOS, ERROR_INVALID_HANDLE);
 315                 return (SDRC_ERROR);
 316         }
 317 
 318         if (!find_first) {
 319                 if ((od->d_flags & SMB_ODIR_FLAG_WILDCARDS) == 0) {
 320                         od->d_eof = B_TRUE;
 321                 } else {
 322                         odir_resume.or_type = SMB_ODIR_RESUME_IDX;
 323                         odir_resume.or_idx = index;
 
 378         }
 379 
 380         rc = (sr->reply.chain_offset - sr->cur_reply_offset) - 8;
 381         if (smb_mbc_poke(&sr->reply, sr->cur_reply_offset, "bwwbw",
 382             1, count, rc+3, 5, rc) < 0) {
 383                 smb_odir_close(od);
 384                 smb_odir_release(od);
 385                 return (SDRC_ERROR);
 386         }
 387 
 388         smb_odir_release(od);
 389         return (SDRC_SUCCESS);
 390 }
 391 
 392 
 393 /* *** smb_com_find *** */
 394 
 395 smb_sdrc_t
 396 smb_pre_find(smb_request_t *sr)
 397 {
 398         DTRACE_SMB_START(op__Find, smb_request_t *, sr);
 399         return (SDRC_SUCCESS);
 400 }
 401 
 402 void
 403 smb_post_find(smb_request_t *sr)
 404 {
 405         DTRACE_SMB_DONE(op__Find, smb_request_t *, sr);
 406 }
 407 
 408 smb_sdrc_t
 409 smb_com_find(smb_request_t *sr)
 410 {
 411         int                     rc;
 412         uint16_t                count, maxcount, index;
 413         uint16_t                sattr, odid;
 414         uint16_t                key_len;
 415         uint32_t                client_key;
 416         char                    name83[SMB_SHORTNAMELEN];
 417         smb_odir_t              *od;
 418         smb_fileinfo_t          fileinfo;
 419         uint32_t                status;
 420         uint16_t                eos;
 421 
 422         smb_pathname_t          *pn;
 423         unsigned char           resume_char;
 424         unsigned char           type;
 425         boolean_t               find_first = B_TRUE;
 
 439         smb_pathname_init(sr, pn, pn->pn_path);
 440         if (!smb_pathname_validate(sr, pn))
 441                 return (SDRC_ERROR);
 442 
 443         if (smb_is_stream_name(pn->pn_path)) {
 444                 smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID,
 445                     ERRDOS, ERROR_INVALID_NAME);
 446                 return (SDRC_ERROR);
 447         }
 448 
 449         find_first = (key_len == 0);
 450         resume_char = 0;
 451         client_key = 0;
 452 
 453         if (find_first) {
 454                 status = smb_odir_openpath(sr, pn->pn_path, sattr, 0, &od);
 455                 if (status != 0) {
 456                         smbsr_error(sr, status, 0, 0);
 457                         return (SDRC_ERROR);
 458                 }
 459                 odid = od->d_odid;
 460         } else {
 461                 if (smb_mbc_decodef(&sr->smb_data, "b12.wwl",
 462                     &resume_char, &index, &odid, &client_key) != 0) {
 463                         return (SDRC_ERROR);
 464                 }
 465                 od = smb_tree_lookup_odir(sr, odid);
 466         }
 467 
 468         if (od == NULL) {
 469                 smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
 470                     ERRDOS, ERROR_INVALID_HANDLE);
 471                 return (SDRC_ERROR);
 472         }
 473 
 474         if (!find_first) {
 475                 if ((od->d_flags & SMB_ODIR_FLAG_WILDCARDS) == 0) {
 476                         od->d_eof = B_TRUE;
 477                 } else {
 478                         odir_resume.or_type = SMB_ODIR_RESUME_IDX;
 479                         odir_resume.or_idx = index;
 
 532         }
 533 
 534         rc = (MBC_LENGTH(&sr->reply) - sr->cur_reply_offset) - 8;
 535         if (smb_mbc_poke(&sr->reply, sr->cur_reply_offset, "bwwbw",
 536             1, count, rc+3, 5, rc) < 0) {
 537                 smb_odir_close(od);
 538                 smb_odir_release(od);
 539                 return (SDRC_ERROR);
 540         }
 541 
 542         smb_odir_release(od);
 543         return (SDRC_SUCCESS);
 544 }
 545 
 546 
 547 /* *** smb_com_find_close *** */
 548 
 549 smb_sdrc_t
 550 smb_pre_find_close(smb_request_t *sr)
 551 {
 552         DTRACE_SMB_START(op__FindClose, smb_request_t *, sr);
 553         return (SDRC_SUCCESS);
 554 }
 555 
 556 void
 557 smb_post_find_close(smb_request_t *sr)
 558 {
 559         DTRACE_SMB_DONE(op__FindClose, smb_request_t *, sr);
 560 }
 561 
 562 smb_sdrc_t
 563 smb_com_find_close(smb_request_t *sr)
 564 {
 565         int             rc;
 566         uint16_t        maxcount, index;
 567         uint16_t        sattr, odid;
 568         uint16_t        key_len;
 569         uint32_t        client_key;
 570         char            *path;
 571         unsigned char   resume_char;
 572         unsigned char   type;
 573         smb_odir_t      *od;
 574 
 575         if (smbsr_decode_vwv(sr, "ww", &maxcount, &sattr) != 0)
 576                 return (SDRC_ERROR);
 577 
 578         rc = smbsr_decode_data(sr, "%Abw", sr, &path, &type, &key_len);
 579         if ((rc != 0) || (type != 0x05))
 
 598                 smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
 599                     ERRDOS, ERROR_INVALID_HANDLE);
 600                 return (SDRC_ERROR);
 601         }
 602 
 603         smb_odir_close(od);
 604         smb_odir_release(od);
 605 
 606         if (smbsr_encode_result(sr, 1, 3, "bwwbw", 1, 0, 3, 5, 0))
 607                 return (SDRC_ERROR);
 608 
 609         return (SDRC_SUCCESS);
 610 }
 611 
 612 
 613 /* *** smb_com_find_unique *** */
 614 
 615 smb_sdrc_t
 616 smb_pre_find_unique(smb_request_t *sr)
 617 {
 618         DTRACE_SMB_START(op__FindUnique, smb_request_t *, sr);
 619         return (SDRC_SUCCESS);
 620 }
 621 
 622 void
 623 smb_post_find_unique(smb_request_t *sr)
 624 {
 625         DTRACE_SMB_DONE(op__FindUnique, smb_request_t *, sr);
 626 }
 627 
 628 smb_sdrc_t
 629 smb_com_find_unique(struct smb_request *sr)
 630 {
 631         int                     rc;
 632         uint16_t                count, maxcount, index;
 633         uint16_t                sattr;
 634         smb_pathname_t          *pn;
 635         unsigned char           resume_char = '\0';
 636         uint32_t                client_key = 0;
 637         char                    name83[SMB_SHORTNAMELEN];
 638         smb_odir_t              *od;
 639         smb_fileinfo_t          fileinfo;
 640         uint32_t                status;
 641         uint16_t                eos;
 642         smb_vdb_t               *vdb;
 643 
 644         if (smbsr_decode_vwv(sr, "ww", &maxcount, &sattr) != 0)
 645                 return (SDRC_ERROR);
 
 676         rc = 0;
 677         count = 0;
 678         index = 0;
 679         if (maxcount > SMB_MAX_SEARCH)
 680                 maxcount = SMB_MAX_SEARCH;
 681 
 682         while (count < maxcount) {
 683                 rc = smb_odir_read_fileinfo(sr, od, &fileinfo, &eos);
 684                 if (rc != 0 || eos != 0)
 685                         break;
 686 
 687                 if (*fileinfo.fi_shortname == '\0') {
 688                         if (smb_needs_mangled(fileinfo.fi_name))
 689                                 continue;
 690                         (void) strlcpy(fileinfo.fi_shortname, fileinfo.fi_name,
 691                             SMB_SHORTNAMELEN - 1);
 692                 }
 693                 smb_name83(fileinfo.fi_shortname, name83, SMB_SHORTNAMELEN);
 694 
 695                 (void) smb_mbc_encodef(&sr->reply, "b11c.wwlbYl13c",
 696                     resume_char, name83, index, od->d_odid, client_key,
 697                     fileinfo.fi_dosattr & 0xff,
 698                     smb_time_gmt_to_local(sr, fileinfo.fi_mtime.tv_sec),
 699                     (int32_t)fileinfo.fi_size,
 700                     fileinfo.fi_shortname);
 701 
 702                 count++;
 703                 index++;
 704         }
 705         if (eos && rc == ENOENT)
 706                 rc = 0;
 707 
 708         smb_odir_close(od);
 709         smb_odir_release(od);
 710 
 711         if (rc != 0)
 712                 return (SDRC_ERROR);
 713 
 714         if (count == 0) {
 715                 smbsr_warn(sr, NT_STATUS_NO_MORE_FILES,
 716                     ERRDOS, ERROR_NO_MORE_FILES);
 717                 return (SDRC_ERROR);
 
 |