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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  24  * Copyright 2016 Syneto S.R.L. All rights reserved.
  25  * Copyright (c) 2016 by Delphix. All rights reserved.
  26  */
  27 
  28 /*
  29  * General Structures Layout
  30  * -------------------------
  31  *
  32  * This is a simplified diagram showing the relationship between most of the
  33  * main structures.
  34  *
  35  * +-------------------+
  36  * |     SMB_INFO      |
  37  * +-------------------+
  38  *          |
  39  *          |
  40  *          v
  41  * +-------------------+       +-------------------+      +-------------------+
  42  * |     SESSION       |<----->|     SESSION       |......|      SESSION      |
  43  * +-------------------+       +-------------------+      +-------------------+
  44  *   |          |
  45  *   |          |
  46  *   |          v
  47  *   |  +-------------------+     +-------------------+   +-------------------+
  48  *   |  |       USER        |<--->|       USER        |...|       USER        |
  49  *   |  +-------------------+     +-------------------+   +-------------------+
  50  *   |
  51  *   |
  52  *   v
  53  * +-------------------+       +-------------------+      +-------------------+
  54  * |       TREE        |<----->|       TREE        |......|       TREE        |
  55  * +-------------------+       +-------------------+      +-------------------+
  56  *      |         |
  57  *      |         |
  58  *      |         v
  59  *      |     +-------+       +-------+      +-------+
  60  *      |     | OFILE |<----->| OFILE |......| OFILE |
  61  *      |     +-------+       +-------+      +-------+
  62  *      |
  63  *      |
  64  *      v
  65  *  +-------+       +------+      +------+
  66  *  | ODIR  |<----->| ODIR |......| ODIR |
  67  *  +-------+       +------+      +------+
  68  *
  69  *
  70  * Ofile State Machine
  71  * ------------------
  72  *
  73  *    +-------------------------+        T0
  74  *    |  SMB_OFILE_STATE_OPEN   |<----------- Creation/Allocation
  75  *    +-------------------------+
  76  *                  |
  77  *                  | T1
  78  *                  |
  79  *                  v
  80  *    +-------------------------+
  81  *    | SMB_OFILE_STATE_CLOSING |
  82  *    +-------------------------+
  83  *                  |
  84  *                  | T2
  85  *                  |
  86  *                  v
  87  *    +-------------------------+    T3
  88  *    | SMB_OFILE_STATE_CLOSED  |----------> Deletion/Free
  89  *    +-------------------------+
  90  *
  91  * SMB_OFILE_STATE_OPEN
  92  *
  93  *    While in this state:
  94  *      - The ofile is queued in the list of ofiles of its tree.
  95  *      - References will be given out if the ofile is looked up.
  96  *
  97  * SMB_OFILE_STATE_CLOSING
  98  *
  99  *    While in this state:
 100  *      - The ofile is queued in the list of ofiles of its tree.
 101  *      - References will not be given out if the ofile is looked up.
 102  *      - The file is closed and the locks held are being released.
 103  *      - The resources associated with the ofile remain.
 104  *
 105  * SMB_OFILE_STATE_CLOSED
 106  *
 107  *    While in this state:
 108  *      - The ofile is queued in the list of ofiles of its tree.
 109  *      - References will not be given out if the ofile is looked up.
 110  *      - The resources associated with the ofile remain.
 111  *
 112  * Transition T0
 113  *
 114  *    This transition occurs in smb_ofile_open(). A new ofile is created and
 115  *    added to the list of ofiles of a tree.
 116  *
 117  * Transition T1
 118  *
 119  *    This transition occurs in smb_ofile_close().
 120  *
 121  * Transition T2
 122  *
 123  *    This transition occurs in smb_ofile_release(). The resources associated
 124  *    with the ofile are freed as well as the ofile structure. For the
 125  *    transition to occur, the ofile must be in the SMB_OFILE_STATE_CLOSED
 126  *    state and the reference count be zero.
 127  *
 128  * Comments
 129  * --------
 130  *
 131  *    The state machine of the ofile structures is controlled by 3 elements:
 132  *      - The list of ofiles of the tree it belongs to.
 133  *      - The mutex embedded in the structure itself.
 134  *      - The reference count.
 135  *
 136  *    There's a mutex embedded in the ofile structure used to protect its fields
 137  *    and there's a lock embedded in the list of ofiles of a tree. To
 138  *    increment or to decrement the reference count the mutex must be entered.
 139  *    To insert the ofile into the list of ofiles of the tree and to remove
 140  *    the ofile from it, the lock must be entered in RW_WRITER mode.
 141  *
 142  *    Rules of access to a ofile structure:
 143  *
 144  *    1) In order to avoid deadlocks, when both (mutex and lock of the ofile
 145  *       list) have to be entered, the lock must be entered first.
 146  *
 147  *    2) All actions applied to an ofile require a reference count.
 148  *
 149  *    3) There are 2 ways of getting a reference count. One is when the ofile
 150  *       is opened. The other one when the ofile is looked up. This translates
 151  *       into 2 functions: smb_ofile_open() and smb_ofile_lookup_by_fid().
 152  *
 153  *    It should be noted that the reference count of an ofile registers the
 154  *    number of references to the ofile in other structures (such as an smb
 155  *    request). The reference count is not incremented in these 2 instances:
 156  *
 157  *    1) The ofile is open. An ofile is anchored by its state. If there's
 158  *       no activity involving an ofile currently open, the reference count
 159  *       of that ofile is zero.
 160  *
 161  *    2) The ofile is queued in the list of ofiles of its tree. The fact of
 162  *       being queued in that list is NOT registered by incrementing the
 163  *       reference count.
 164  */
 165 #include <smbsrv/smb_kproto.h>
 166 #include <smbsrv/smb_fsops.h>
 167 
 168 static boolean_t smb_ofile_is_open_locked(smb_ofile_t *);
 169 static smb_ofile_t *smb_ofile_close_and_next(smb_ofile_t *);
 170 static int smb_ofile_netinfo_encode(smb_ofile_t *, uint8_t *, size_t,
 171     uint32_t *);
 172 static int smb_ofile_netinfo_init(smb_ofile_t *, smb_netfileinfo_t *);
 173 static void smb_ofile_netinfo_fini(smb_netfileinfo_t *);
 174 
 175 /*
 176  * smb_ofile_open
 177  */
 178 smb_ofile_t *
 179 smb_ofile_open(
 180     smb_request_t       *sr,
 181     smb_node_t          *node,
 182     struct open_param   *op,
 183     uint16_t            ftype,
 184     uint32_t            uniqid,
 185     smb_error_t         *err)
 186 {
 187         smb_tree_t      *tree = sr->tid_tree;
 188         smb_ofile_t     *of;
 189         uint16_t        fid;
 190         smb_attr_t      attr;
 191         int             rc;
 192         enum errstates { EMPTY, FIDALLOC, CRHELD, MUTEXINIT };
 193         enum errstates  state = EMPTY;
 194 
 195         if (smb_idpool_alloc(&tree->t_fid_pool, &fid)) {
 196                 err->status = NT_STATUS_TOO_MANY_OPENED_FILES;
 197                 err->errcls = ERRDOS;
 198                 err->errcode = ERROR_TOO_MANY_OPEN_FILES;
 199                 return (NULL);
 200         }
 201         state = FIDALLOC;
 202 
 203         of = kmem_cache_alloc(smb_cache_ofile, KM_SLEEP);
 204         bzero(of, sizeof (smb_ofile_t));
 205         of->f_magic = SMB_OFILE_MAGIC;
 206         of->f_refcnt = 1;
 207         of->f_fid = fid;
 208         of->f_uniqid = uniqid;
 209         of->f_opened_by_pid = sr->smb_pid;
 210         of->f_granted_access = op->desired_access;
 211         of->f_share_access = op->share_access;
 212         of->f_create_options = op->create_options;
 213         of->f_cr = (op->create_options & FILE_OPEN_FOR_BACKUP_INTENT) ?
 214             smb_user_getprivcred(sr->uid_user) : sr->uid_user->u_cred;
 215         crhold(of->f_cr);
 216         state = CRHELD;
 217         of->f_ftype = ftype;
 218         of->f_server = tree->t_server;
 219         of->f_session = tree->t_session;
 220         /*
 221          * grab a ref for of->f_user
 222          * released in smb_ofile_delete()
 223          */
 224         smb_user_hold_internal(sr->uid_user);
 225         of->f_user = sr->uid_user;
 226         of->f_tree = tree;
 227         of->f_node = node;
 228 
 229         mutex_init(&of->f_mutex, NULL, MUTEX_DEFAULT, NULL);
 230         state = MUTEXINIT;
 231         of->f_state = SMB_OFILE_STATE_OPEN;
 232 
 233         if (ftype == SMB_FTYPE_MESG_PIPE) {
 234                 /* See smb_opipe_open. */
 235                 of->f_pipe = op->pipe;
 236                 smb_server_inc_pipes(of->f_server);
 237         } else {
 238                 ASSERT(ftype == SMB_FTYPE_DISK); /* Regular file, not a pipe */
 239                 ASSERT(node);
 240 
 241                 /*
 242                  * Note that the common open path often adds bits like
 243                  * READ_CONTROL, so the logic "is this open exec-only"
 244                  * needs to look at only the FILE_DATA_ALL bits.
 245                  */
 246                 if ((of->f_granted_access & FILE_DATA_ALL) == FILE_EXECUTE)
 247                         of->f_flags |= SMB_OFLAGS_EXECONLY;
 248 
 249                 bzero(&attr, sizeof (smb_attr_t));
 250                 attr.sa_mask = SMB_AT_UID | SMB_AT_DOSATTR;
 251                 rc = smb_node_getattr(NULL, node, of->f_cr, NULL, &attr);
 252                 if (rc != 0) {
 253                         err->status = NT_STATUS_INTERNAL_ERROR;
 254                         err->errcls = ERRDOS;
 255                         err->errcode = ERROR_INTERNAL_ERROR;
 256                         goto errout;
 257                 }
 258                 if (crgetuid(of->f_cr) == attr.sa_vattr.va_uid) {
 259                         /*
 260                          * Add this bit for the file's owner even if it's not
 261                          * specified in the request (Windows behavior).
 262                          */
 263                         of->f_granted_access |= FILE_READ_ATTRIBUTES;
 264                 }
 265 
 266                 if (smb_node_is_file(node)) {
 267                         of->f_mode =
 268                             smb_fsop_amask_to_omode(of->f_granted_access);
 269                         if (smb_fsop_open(node, of->f_mode, of->f_cr) != 0) {
 270                                 err->status = NT_STATUS_ACCESS_DENIED;
 271                                 err->errcls = ERRDOS;
 272                                 err->errcode = ERROR_ACCESS_DENIED;
 273                                 goto errout;
 274                         }
 275                 }
 276 
 277                 if (tree->t_flags & SMB_TREE_READONLY)
 278                         of->f_flags |= SMB_OFLAGS_READONLY;
 279 
 280                 /*
 281                  * Note that if we created_readonly, that
 282                  * will _not_ yet show in attr.sa_dosattr
 283                  * so creating a readonly file gives the
 284                  * caller a writable handle as it should.
 285                  */
 286                 if (attr.sa_dosattr & FILE_ATTRIBUTE_READONLY)
 287                         of->f_flags |= SMB_OFLAGS_READONLY;
 288 
 289                 smb_node_inc_open_ofiles(node);
 290                 smb_node_add_ofile(node, of);
 291                 smb_node_ref(node);
 292                 smb_server_inc_files(of->f_server);
 293         }
 294         smb_llist_enter(&tree->t_ofile_list, RW_WRITER);
 295         smb_llist_insert_tail(&tree->t_ofile_list, of);
 296         smb_llist_exit(&tree->t_ofile_list);
 297         atomic_inc_32(&tree->t_open_files);
 298         atomic_inc_32(&of->f_session->s_file_cnt);
 299         return (of);
 300 
 301 errout:
 302         switch (state) {
 303         case MUTEXINIT:
 304                 mutex_destroy(&of->f_mutex);
 305                 smb_user_release(of->f_user);
 306                 /*FALLTHROUGH*/
 307         case CRHELD:
 308                 crfree(of->f_cr);
 309                 of->f_magic = 0;
 310                 kmem_cache_free(smb_cache_ofile, of);
 311                 /*FALLTHROUGH*/
 312         case FIDALLOC:
 313                 smb_idpool_free(&tree->t_fid_pool, fid);
 314                 /*FALLTHROUGH*/
 315         case EMPTY:
 316                 break;
 317         }
 318         return (NULL);
 319 }
 320 
 321 /*
 322  * smb_ofile_close
 323  */
 324 void
 325 smb_ofile_close(smb_ofile_t *of, int32_t mtime_sec)
 326 {
 327         smb_attr_t *pa;
 328         timestruc_t now;
 329         uint32_t flags = 0;
 330 
 331         SMB_OFILE_VALID(of);
 332 
 333         mutex_enter(&of->f_mutex);
 334         ASSERT(of->f_refcnt);
 335         if (of->f_state != SMB_OFILE_STATE_OPEN) {
 336                 mutex_exit(&of->f_mutex);
 337                 return;
 338         }
 339         of->f_state = SMB_OFILE_STATE_CLOSING;
 340         mutex_exit(&of->f_mutex);
 341 
 342         switch (of->f_ftype) {
 343         case SMB_FTYPE_BYTE_PIPE:
 344         case SMB_FTYPE_MESG_PIPE:
 345                 smb_opipe_close(of);
 346                 smb_server_dec_pipes(of->f_server);
 347                 break;
 348 
 349         case SMB_FTYPE_DISK:
 350         case SMB_FTYPE_PRINTER:
 351                 /*
 352                  * In here we make changes to of->f_pending_attr
 353                  * while not holding of->f_mutex.  This is OK
 354                  * because we've changed f_state to CLOSING,
 355                  * so no more threads will take this path.
 356                  */
 357                 pa = &of->f_pending_attr;
 358                 if (mtime_sec != 0) {
 359                         pa->sa_vattr.va_mtime.tv_sec = mtime_sec;
 360                         pa->sa_mask |= SMB_AT_MTIME;
 361                 }
 362 
 363                 /*
 364                  * If we have ever modified data via this handle
 365                  * (write or truncate) and if the mtime was not
 366                  * set via this handle, update the mtime again
 367                  * during the close.  Windows expects this.
 368                  * [ MS-FSA 2.1.5.4 "Update Timestamps" ]
 369                  */
 370                 if (of->f_written &&
 371                     (pa->sa_mask & SMB_AT_MTIME) == 0) {
 372                         pa->sa_mask |= SMB_AT_MTIME;
 373                         gethrestime(&now);
 374                         pa->sa_vattr.va_mtime = now;
 375                 }
 376 
 377                 if (of->f_flags & SMB_OFLAGS_SET_DELETE_ON_CLOSE) {
 378                         if (smb_tree_has_feature(of->f_tree,
 379                             SMB_TREE_CATIA)) {
 380                                 flags |= SMB_CATIA;
 381                         }
 382                         (void) smb_node_set_delete_on_close(of->f_node,
 383                             of->f_cr, flags);
 384                 }
 385                 smb_fsop_unshrlock(of->f_cr, of->f_node, of->f_uniqid);
 386                 smb_node_destroy_lock_by_ofile(of->f_node, of);
 387 
 388                 if (smb_node_is_file(of->f_node)) {
 389                         (void) smb_fsop_close(of->f_node, of->f_mode,
 390                             of->f_cr);
 391                         smb_oplock_release(of->f_node, of);
 392                 } else {
 393                         /*
 394                          * If there was an odir, close it.
 395                          */
 396                         if (of->f_odir != NULL)
 397                                 smb_odir_close(of->f_odir);
 398                 }
 399                 if (smb_node_dec_open_ofiles(of->f_node) == 0) {
 400                         /*
 401                          * Last close. The f_pending_attr has
 402                          * only times (atime,ctime,mtime) so
 403                          * we can borrow it to commit the
 404                          * n_pending_dosattr from the node.
 405                          */
 406                         pa->sa_dosattr =
 407                             of->f_node->n_pending_dosattr;
 408                         if (pa->sa_dosattr != 0)
 409                                 pa->sa_mask |= SMB_AT_DOSATTR;
 410                         /* Let's leave this zero when not in use. */
 411                         of->f_node->n_allocsz = 0;
 412                 }
 413                 if (pa->sa_mask != 0) {
 414                         /*
 415                          * Commit any pending attributes from
 416                          * the ofile we're closing.  Note that
 417                          * we pass NULL as the ofile to setattr
 418                          * so it will write to the file system
 419                          * and not keep anything on the ofile.
 420                          * This clears n_pending_dosattr if
 421                          * there are no opens, otherwise the
 422                          * dosattr will be pending again.
 423                          */
 424                         (void) smb_node_setattr(NULL, of->f_node,
 425                             of->f_cr, NULL, pa);
 426                 }
 427 
 428                 /*
 429                  * Cancel any notify change requests that
 430                  * may be using this open instance.
 431                  */
 432                 if (of->f_node->n_fcn.fcn_count)
 433                         smb_notify_file_closed(of);
 434 
 435                 smb_server_dec_files(of->f_server);
 436                 break;
 437         }
 438         atomic_dec_32(&of->f_tree->t_open_files);
 439 
 440         mutex_enter(&of->f_mutex);
 441         ASSERT(of->f_refcnt);
 442         ASSERT(of->f_state == SMB_OFILE_STATE_CLOSING);
 443         of->f_state = SMB_OFILE_STATE_CLOSED;
 444         mutex_exit(&of->f_mutex);
 445 }
 446 
 447 /*
 448  * smb_ofile_close_all
 449  *
 450  *
 451  */
 452 void
 453 smb_ofile_close_all(
 454     smb_tree_t          *tree)
 455 {
 456         smb_ofile_t     *of;
 457 
 458         ASSERT(tree);
 459         ASSERT(tree->t_magic == SMB_TREE_MAGIC);
 460 
 461         smb_llist_enter(&tree->t_ofile_list, RW_READER);
 462         of = smb_llist_head(&tree->t_ofile_list);
 463         while (of) {
 464                 ASSERT(of->f_magic == SMB_OFILE_MAGIC);
 465                 ASSERT(of->f_tree == tree);
 466                 of = smb_ofile_close_and_next(of);
 467         }
 468         smb_llist_exit(&tree->t_ofile_list);
 469 }
 470 
 471 /*
 472  * smb_ofiles_close_by_pid
 473  *
 474  *
 475  */
 476 void
 477 smb_ofile_close_all_by_pid(
 478     smb_tree_t          *tree,
 479     uint16_t            pid)
 480 {
 481         smb_ofile_t     *of;
 482 
 483         ASSERT(tree);
 484         ASSERT(tree->t_magic == SMB_TREE_MAGIC);
 485 
 486         smb_llist_enter(&tree->t_ofile_list, RW_READER);
 487         of = smb_llist_head(&tree->t_ofile_list);
 488         while (of) {
 489                 ASSERT(of->f_magic == SMB_OFILE_MAGIC);
 490                 ASSERT(of->f_tree == tree);
 491                 if (of->f_opened_by_pid == pid) {
 492                         of = smb_ofile_close_and_next(of);
 493                 } else {
 494                         of = smb_llist_next(&tree->t_ofile_list, of);
 495                 }
 496         }
 497         smb_llist_exit(&tree->t_ofile_list);
 498 }
 499 
 500 /*
 501  * If the enumeration request is for ofile data, handle it here.
 502  * Otherwise, return.
 503  *
 504  * This function should be called with a hold on the ofile.
 505  */
 506 int
 507 smb_ofile_enum(smb_ofile_t *of, smb_svcenum_t *svcenum)
 508 {
 509         uint8_t *pb;
 510         uint_t nbytes;
 511         int rc;
 512 
 513         ASSERT(of);
 514         ASSERT(of->f_magic == SMB_OFILE_MAGIC);
 515         ASSERT(of->f_refcnt);
 516 
 517         if (svcenum->se_type != SMB_SVCENUM_TYPE_FILE)
 518                 return (0);
 519 
 520         if (svcenum->se_nskip > 0) {
 521                 svcenum->se_nskip--;
 522                 return (0);
 523         }
 524 
 525         if (svcenum->se_nitems >= svcenum->se_nlimit) {
 526                 svcenum->se_nitems = svcenum->se_nlimit;
 527                 return (0);
 528         }
 529 
 530         pb = &svcenum->se_buf[svcenum->se_bused];
 531 
 532         rc = smb_ofile_netinfo_encode(of, pb, svcenum->se_bavail,
 533             &nbytes);
 534         if (rc == 0) {
 535                 svcenum->se_bavail -= nbytes;
 536                 svcenum->se_bused += nbytes;
 537                 svcenum->se_nitems++;
 538         }
 539 
 540         return (rc);
 541 }
 542 
 543 /*
 544  * Take a reference on an open file.
 545  */
 546 boolean_t
 547 smb_ofile_hold(smb_ofile_t *of)
 548 {
 549         ASSERT(of);
 550         ASSERT(of->f_magic == SMB_OFILE_MAGIC);
 551 
 552         mutex_enter(&of->f_mutex);
 553 
 554         if (of->f_state != SMB_OFILE_STATE_OPEN) {
 555                 mutex_exit(&of->f_mutex);
 556                 return (B_FALSE);
 557         }
 558         of->f_refcnt++;
 559 
 560         mutex_exit(&of->f_mutex);
 561         return (B_TRUE);
 562 }
 563 
 564 /*
 565  * Release a reference on a file.  If the reference count falls to
 566  * zero and the file has been closed, post the object for deletion.
 567  * Object deletion is deferred to avoid modifying a list while an
 568  * iteration may be in progress.
 569  */
 570 void
 571 smb_ofile_release(smb_ofile_t *of)
 572 {
 573         SMB_OFILE_VALID(of);
 574 
 575         mutex_enter(&of->f_mutex);
 576         ASSERT(of->f_refcnt);
 577         of->f_refcnt--;
 578         switch (of->f_state) {
 579         case SMB_OFILE_STATE_OPEN:
 580         case SMB_OFILE_STATE_CLOSING:
 581                 break;
 582 
 583         case SMB_OFILE_STATE_CLOSED:
 584                 if (of->f_refcnt == 0)
 585                         smb_tree_post_ofile(of->f_tree, of);
 586                 break;
 587 
 588         default:
 589                 ASSERT(0);
 590                 break;
 591         }
 592         mutex_exit(&of->f_mutex);
 593 }
 594 
 595 /*
 596  * smb_ofile_request_complete
 597  *
 598  * During oplock acquisition, all other oplock requests on the node
 599  * are blocked until the acquire request completes and the response
 600  * is on the wire.
 601  * Call smb_oplock_broadcast to notify the node that the request
 602  * has completed.
 603  *
 604  * THIS MECHANISM RELIES ON THE FACT THAT THE OFILE IS NOT REMOVED
 605  * FROM THE SR UNTIL REQUEST COMPLETION (when the sr is destroyed)
 606  */
 607 void
 608 smb_ofile_request_complete(smb_ofile_t *of)
 609 {
 610         SMB_OFILE_VALID(of);
 611 
 612         switch (of->f_ftype) {
 613         case SMB_FTYPE_DISK:
 614                 ASSERT(of->f_node);
 615                 smb_oplock_broadcast(of->f_node);
 616                 break;
 617         case SMB_FTYPE_MESG_PIPE:
 618                 break;
 619         default:
 620                 break;
 621         }
 622 }
 623 
 624 /*
 625  * smb_ofile_lookup_by_fid
 626  *
 627  * Find the open file whose fid matches the one specified in the request.
 628  * If we can't find the fid or the shares (trees) don't match, we have a
 629  * bad fid.
 630  */
 631 smb_ofile_t *
 632 smb_ofile_lookup_by_fid(
 633     smb_request_t       *sr,
 634     uint16_t            fid)
 635 {
 636         smb_tree_t      *tree = sr->tid_tree;
 637         smb_llist_t     *of_list;
 638         smb_ofile_t     *of;
 639 
 640         ASSERT(tree->t_magic == SMB_TREE_MAGIC);
 641 
 642         of_list = &tree->t_ofile_list;
 643 
 644         smb_llist_enter(of_list, RW_READER);
 645         of = smb_llist_head(of_list);
 646         while (of) {
 647                 ASSERT(of->f_magic == SMB_OFILE_MAGIC);
 648                 ASSERT(of->f_tree == tree);
 649                 if (of->f_fid == fid)
 650                         break;
 651                 of = smb_llist_next(of_list, of);
 652         }
 653         if (of == NULL)
 654                 goto out;
 655 
 656         /*
 657          * Only allow use of a given FID with the same UID that
 658          * was used to open it.  MS-CIFS 3.3.5.14
 659          */
 660         if (of->f_user != sr->uid_user) {
 661                 of = NULL;
 662                 goto out;
 663         }
 664 
 665         mutex_enter(&of->f_mutex);
 666         if (of->f_state != SMB_OFILE_STATE_OPEN) {
 667                 mutex_exit(&of->f_mutex);
 668                 of = NULL;
 669                 goto out;
 670         }
 671         of->f_refcnt++;
 672         mutex_exit(&of->f_mutex);
 673 
 674 out:
 675         smb_llist_exit(of_list);
 676         return (of);
 677 }
 678 
 679 /*
 680  * smb_ofile_lookup_by_uniqid
 681  *
 682  * Find the open file whose uniqid matches the one specified in the request.
 683  */
 684 smb_ofile_t *
 685 smb_ofile_lookup_by_uniqid(smb_tree_t *tree, uint32_t uniqid)
 686 {
 687         smb_llist_t     *of_list;
 688         smb_ofile_t     *of;
 689 
 690         ASSERT(tree->t_magic == SMB_TREE_MAGIC);
 691 
 692         of_list = &tree->t_ofile_list;
 693         smb_llist_enter(of_list, RW_READER);
 694         of = smb_llist_head(of_list);
 695 
 696         while (of) {
 697                 ASSERT(of->f_magic == SMB_OFILE_MAGIC);
 698                 ASSERT(of->f_tree == tree);
 699 
 700                 if (of->f_uniqid == uniqid) {
 701                         if (smb_ofile_hold(of)) {
 702                                 smb_llist_exit(of_list);
 703                                 return (of);
 704                         }
 705                 }
 706 
 707                 of = smb_llist_next(of_list, of);
 708         }
 709 
 710         smb_llist_exit(of_list);
 711         return (NULL);
 712 }
 713 
 714 /*
 715  * Disallow NetFileClose on certain ofiles to avoid side-effects.
 716  * Closing a tree root is not allowed: use NetSessionDel or NetShareDel.
 717  * Closing SRVSVC connections is not allowed because this NetFileClose
 718  * request may depend on this ofile.
 719  */
 720 boolean_t
 721 smb_ofile_disallow_fclose(smb_ofile_t *of)
 722 {
 723         ASSERT(of);
 724         ASSERT(of->f_magic == SMB_OFILE_MAGIC);
 725         ASSERT(of->f_refcnt);
 726 
 727         switch (of->f_ftype) {
 728         case SMB_FTYPE_DISK:
 729                 ASSERT(of->f_tree);
 730                 return (of->f_node == of->f_tree->t_snode);
 731 
 732         case SMB_FTYPE_MESG_PIPE:
 733                 ASSERT(of->f_pipe);
 734                 if (smb_strcasecmp(of->f_pipe->p_name, "SRVSVC", 0) == 0)
 735                         return (B_TRUE);
 736                 break;
 737         default:
 738                 break;
 739         }
 740 
 741         return (B_FALSE);
 742 }
 743 
 744 /*
 745  * smb_ofile_set_flags
 746  *
 747  * Return value:
 748  *
 749  *      Current flags value
 750  *
 751  */
 752 void
 753 smb_ofile_set_flags(
 754     smb_ofile_t         *of,
 755     uint32_t            flags)
 756 {
 757         ASSERT(of);
 758         ASSERT(of->f_magic == SMB_OFILE_MAGIC);
 759         ASSERT(of->f_refcnt);
 760 
 761         mutex_enter(&of->f_mutex);
 762         of->f_flags |= flags;
 763         mutex_exit(&of->f_mutex);
 764 }
 765 
 766 /*
 767  * smb_ofile_seek
 768  *
 769  * Return value:
 770  *
 771  *      0               Success
 772  *      EINVAL          Unknown mode
 773  *      EOVERFLOW       offset too big
 774  *
 775  */
 776 int
 777 smb_ofile_seek(
 778     smb_ofile_t         *of,
 779     ushort_t            mode,
 780     int32_t             off,
 781     uint32_t            *retoff)
 782 {
 783         u_offset_t      newoff = 0;
 784         int             rc = 0;
 785         smb_attr_t      attr;
 786 
 787         ASSERT(of);
 788         ASSERT(of->f_magic == SMB_OFILE_MAGIC);
 789         ASSERT(of->f_refcnt);
 790 
 791         mutex_enter(&of->f_mutex);
 792         switch (mode) {
 793         case SMB_SEEK_SET:
 794                 if (off < 0)
 795                         newoff = 0;
 796                 else
 797                         newoff = (u_offset_t)off;
 798                 break;
 799 
 800         case SMB_SEEK_CUR:
 801                 if (off < 0 && (-off) > of->f_seek_pos)
 802                         newoff = 0;
 803                 else
 804                         newoff = of->f_seek_pos + (u_offset_t)off;
 805                 break;
 806 
 807         case SMB_SEEK_END:
 808                 bzero(&attr, sizeof (smb_attr_t));
 809                 attr.sa_mask |= SMB_AT_SIZE;
 810                 rc = smb_fsop_getattr(NULL, zone_kcred(), of->f_node, &attr);
 811                 if (rc != 0) {
 812                         mutex_exit(&of->f_mutex);
 813                         return (rc);
 814                 }
 815                 if (off < 0 && (-off) > attr.sa_vattr.va_size)
 816                         newoff = 0;
 817                 else
 818                         newoff = attr.sa_vattr.va_size + (u_offset_t)off;
 819                 break;
 820 
 821         default:
 822                 mutex_exit(&of->f_mutex);
 823                 return (EINVAL);
 824         }
 825 
 826         /*
 827          * See comments at the beginning of smb_seek.c.
 828          * If the offset is greater than UINT_MAX, we will return an error.
 829          */
 830 
 831         if (newoff > UINT_MAX) {
 832                 rc = EOVERFLOW;
 833         } else {
 834                 of->f_seek_pos = newoff;
 835                 *retoff = (uint32_t)newoff;
 836         }
 837         mutex_exit(&of->f_mutex);
 838         return (rc);
 839 }
 840 
 841 /*
 842  * smb_ofile_flush
 843  *
 844  * If writes on this file are not synchronous, flush it using the NFSv3
 845  * commit interface.
 846  *
 847  * XXX - todo: Flush named pipe should drain writes.
 848  */
 849 void
 850 smb_ofile_flush(struct smb_request *sr, struct smb_ofile *of)
 851 {
 852         switch (of->f_ftype) {
 853         case SMB_FTYPE_DISK:
 854                 if ((of->f_node->flags & NODE_FLAGS_WRITE_THROUGH) == 0)
 855                         (void) smb_fsop_commit(sr, of->f_cr, of->f_node);
 856                 break;
 857         default:
 858                 break;
 859         }
 860 }
 861 
 862 /*
 863  * smb_ofile_is_open
 864  */
 865 boolean_t
 866 smb_ofile_is_open(smb_ofile_t *of)
 867 {
 868         boolean_t       rc;
 869 
 870         SMB_OFILE_VALID(of);
 871 
 872         mutex_enter(&of->f_mutex);
 873         rc = smb_ofile_is_open_locked(of);
 874         mutex_exit(&of->f_mutex);
 875         return (rc);
 876 }
 877 
 878 /* *************************** Static Functions ***************************** */
 879 
 880 /*
 881  * Determine whether or not an ofile is open.
 882  * This function must be called with the mutex held.
 883  */
 884 static boolean_t
 885 smb_ofile_is_open_locked(smb_ofile_t *of)
 886 {
 887         switch (of->f_state) {
 888         case SMB_OFILE_STATE_OPEN:
 889                 return (B_TRUE);
 890 
 891         case SMB_OFILE_STATE_CLOSING:
 892         case SMB_OFILE_STATE_CLOSED:
 893                 return (B_FALSE);
 894 
 895         default:
 896                 ASSERT(0);
 897                 return (B_FALSE);
 898         }
 899 }
 900 
 901 /*
 902  * This function closes the file passed in (if appropriate) and returns the
 903  * next open file in the list of open files of the tree of the open file passed
 904  * in. It requires that the list of open files of the tree be entered in
 905  * RW_READER mode before being called.
 906  */
 907 static smb_ofile_t *
 908 smb_ofile_close_and_next(smb_ofile_t *of)
 909 {
 910         smb_ofile_t     *next_of;
 911         smb_tree_t      *tree;
 912 
 913         ASSERT(of);
 914         ASSERT(of->f_magic == SMB_OFILE_MAGIC);
 915 
 916         mutex_enter(&of->f_mutex);
 917         switch (of->f_state) {
 918         case SMB_OFILE_STATE_OPEN:
 919                 /* The file is still open. */
 920                 of->f_refcnt++;
 921                 ASSERT(of->f_refcnt);
 922                 tree = of->f_tree;
 923                 mutex_exit(&of->f_mutex);
 924                 smb_llist_exit(&of->f_tree->t_ofile_list);
 925                 smb_ofile_close(of, 0);
 926                 smb_ofile_release(of);
 927                 smb_llist_enter(&tree->t_ofile_list, RW_READER);
 928                 next_of = smb_llist_head(&tree->t_ofile_list);
 929                 break;
 930         case SMB_OFILE_STATE_CLOSING:
 931         case SMB_OFILE_STATE_CLOSED:
 932                 /*
 933                  * The ofile exists but is closed or
 934                  * in the process being closed.
 935                  */
 936                 mutex_exit(&of->f_mutex);
 937                 next_of = smb_llist_next(&of->f_tree->t_ofile_list, of);
 938                 break;
 939         default:
 940                 ASSERT(0);
 941                 mutex_exit(&of->f_mutex);
 942                 next_of = smb_llist_next(&of->f_tree->t_ofile_list, of);
 943                 break;
 944         }
 945         return (next_of);
 946 }
 947 
 948 /*
 949  * Delete an ofile.
 950  *
 951  * Remove the ofile from the tree list before freeing resources
 952  * associated with the ofile.
 953  */
 954 void
 955 smb_ofile_delete(void *arg)
 956 {
 957         smb_tree_t      *tree;
 958         smb_ofile_t     *of = (smb_ofile_t *)arg;
 959 
 960         SMB_OFILE_VALID(of);
 961         ASSERT(of->f_refcnt == 0);
 962         ASSERT(of->f_state == SMB_OFILE_STATE_CLOSED);
 963         ASSERT(!SMB_OFILE_OPLOCK_GRANTED(of));
 964 
 965         tree = of->f_tree;
 966         smb_llist_enter(&tree->t_ofile_list, RW_WRITER);
 967         smb_llist_remove(&tree->t_ofile_list, of);
 968         smb_idpool_free(&tree->t_fid_pool, of->f_fid);
 969         atomic_dec_32(&tree->t_session->s_file_cnt);
 970         smb_llist_exit(&tree->t_ofile_list);
 971 
 972         mutex_enter(&of->f_mutex);
 973         mutex_exit(&of->f_mutex);
 974 
 975         switch (of->f_ftype) {
 976         case SMB_FTYPE_BYTE_PIPE:
 977         case SMB_FTYPE_MESG_PIPE:
 978                 smb_opipe_dealloc(of->f_pipe);
 979                 of->f_pipe = NULL;
 980                 break;
 981         case SMB_FTYPE_DISK:
 982                 if (of->f_odir != NULL)
 983                         smb_odir_release(of->f_odir);
 984                 smb_node_rem_ofile(of->f_node, of);
 985                 smb_node_release(of->f_node);
 986                 break;
 987         default:
 988                 ASSERT(!"f_ftype");
 989                 break;
 990         }
 991 
 992         of->f_magic = (uint32_t)~SMB_OFILE_MAGIC;
 993         mutex_destroy(&of->f_mutex);
 994         crfree(of->f_cr);
 995         smb_user_release(of->f_user);
 996         kmem_cache_free(smb_cache_ofile, of);
 997 }
 998 
 999 /*
1000  * smb_ofile_access
1001  *
1002  * This function will check to see if the access requested is granted.
1003  * Returns NT status codes.
1004  */
1005 uint32_t
1006 smb_ofile_access(smb_ofile_t *of, cred_t *cr, uint32_t access)
1007 {
1008 
1009         if ((of == NULL) || (cr == zone_kcred()))
1010                 return (NT_STATUS_SUCCESS);
1011 
1012         /*
1013          * If the request is for something
1014          * I don't grant it is an error
1015          */
1016         if (~(of->f_granted_access) & access) {
1017                 if (!(of->f_granted_access & ACCESS_SYSTEM_SECURITY) &&
1018                     (access & ACCESS_SYSTEM_SECURITY)) {
1019                         return (NT_STATUS_PRIVILEGE_NOT_HELD);
1020                 }
1021                 return (NT_STATUS_ACCESS_DENIED);
1022         }
1023 
1024         return (NT_STATUS_SUCCESS);
1025 }
1026 
1027 /*
1028  * smb_ofile_share_check
1029  *
1030  * Check if ofile was opened with share access NONE (0).
1031  * Returns: B_TRUE  - share access non-zero
1032  *          B_FALSE - share access NONE
1033  */
1034 boolean_t
1035 smb_ofile_share_check(smb_ofile_t *of)
1036 {
1037         return (!SMB_DENY_ALL(of->f_share_access));
1038 }
1039 
1040 /*
1041  * check file sharing rules for current open request
1042  * against existing open instances of the same file
1043  *
1044  * Returns NT_STATUS_SHARING_VIOLATION if there is any
1045  * sharing conflict, otherwise returns NT_STATUS_SUCCESS.
1046  */
1047 uint32_t
1048 smb_ofile_open_check(smb_ofile_t *of, uint32_t desired_access,
1049     uint32_t share_access)
1050 {
1051         ASSERT(of->f_magic == SMB_OFILE_MAGIC);
1052 
1053         mutex_enter(&of->f_mutex);
1054 
1055         if (of->f_state != SMB_OFILE_STATE_OPEN) {
1056                 mutex_exit(&of->f_mutex);
1057                 return (NT_STATUS_INVALID_HANDLE);
1058         }
1059 
1060         /* if it's just meta data */
1061         if ((of->f_granted_access & FILE_DATA_ALL) == 0) {
1062                 mutex_exit(&of->f_mutex);
1063                 return (NT_STATUS_SUCCESS);
1064         }
1065 
1066         /*
1067          * Check requested share access against the
1068          * open granted (desired) access
1069          */
1070         if (SMB_DENY_DELETE(share_access) && (of->f_granted_access & DELETE)) {
1071                 mutex_exit(&of->f_mutex);
1072                 return (NT_STATUS_SHARING_VIOLATION);
1073         }
1074 
1075         if (SMB_DENY_READ(share_access) &&
1076             (of->f_granted_access & (FILE_READ_DATA | FILE_EXECUTE))) {
1077                 mutex_exit(&of->f_mutex);
1078                 return (NT_STATUS_SHARING_VIOLATION);
1079         }
1080 
1081         if (SMB_DENY_WRITE(share_access) &&
1082             (of->f_granted_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) {
1083                 mutex_exit(&of->f_mutex);
1084                 return (NT_STATUS_SHARING_VIOLATION);
1085         }
1086 
1087         /* check requested desired access against the open share access */
1088         if (SMB_DENY_DELETE(of->f_share_access) && (desired_access & DELETE)) {
1089                 mutex_exit(&of->f_mutex);
1090                 return (NT_STATUS_SHARING_VIOLATION);
1091         }
1092 
1093         if (SMB_DENY_READ(of->f_share_access) &&
1094             (desired_access & (FILE_READ_DATA | FILE_EXECUTE))) {
1095                 mutex_exit(&of->f_mutex);
1096                 return (NT_STATUS_SHARING_VIOLATION);
1097         }
1098 
1099         if (SMB_DENY_WRITE(of->f_share_access) &&
1100             (desired_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) {
1101                 mutex_exit(&of->f_mutex);
1102                 return (NT_STATUS_SHARING_VIOLATION);
1103         }
1104 
1105         mutex_exit(&of->f_mutex);
1106         return (NT_STATUS_SUCCESS);
1107 }
1108 
1109 /*
1110  * smb_ofile_rename_check
1111  *
1112  * An open file can be renamed if
1113  *
1114  *  1. isn't opened for data writing or deleting
1115  *
1116  *  2. Opened with "Deny Delete" share mode
1117  *         But not opened for data reading or executing
1118  *         (opened for accessing meta data)
1119  */
1120 
1121 uint32_t
1122 smb_ofile_rename_check(smb_ofile_t *of)
1123 {
1124         ASSERT(of->f_magic == SMB_OFILE_MAGIC);
1125 
1126         mutex_enter(&of->f_mutex);
1127 
1128         if (of->f_state != SMB_OFILE_STATE_OPEN) {
1129                 mutex_exit(&of->f_mutex);
1130                 return (NT_STATUS_INVALID_HANDLE);
1131         }
1132 
1133         if (of->f_granted_access &
1134             (FILE_WRITE_DATA | FILE_APPEND_DATA | DELETE)) {
1135                 mutex_exit(&of->f_mutex);
1136                 return (NT_STATUS_SHARING_VIOLATION);
1137         }
1138 
1139         if ((of->f_share_access & FILE_SHARE_DELETE) == 0) {
1140                 if (of->f_granted_access &
1141                     (FILE_READ_DATA | FILE_EXECUTE)) {
1142                         mutex_exit(&of->f_mutex);
1143                         return (NT_STATUS_SHARING_VIOLATION);
1144                 }
1145         }
1146 
1147         mutex_exit(&of->f_mutex);
1148         return (NT_STATUS_SUCCESS);
1149 }
1150 
1151 /*
1152  * smb_ofile_delete_check
1153  *
1154  * An open file can be deleted only if opened for
1155  * accessing meta data. Share modes aren't important
1156  * in this case.
1157  *
1158  * NOTE: there is another mechanism for deleting an
1159  * open file that NT clients usually use.
1160  * That's setting "Delete on close" flag for an open
1161  * file.  In this way the file will be deleted after
1162  * last close. This flag can be set by SmbTrans2SetFileInfo
1163  * with FILE_DISPOSITION_INFO information level.
1164  * For setting this flag, the file should be opened by
1165  * DELETE access in the FID that is passed in the Trans2
1166  * request.
1167  */
1168 
1169 uint32_t
1170 smb_ofile_delete_check(smb_ofile_t *of)
1171 {
1172         ASSERT(of->f_magic == SMB_OFILE_MAGIC);
1173 
1174         mutex_enter(&of->f_mutex);
1175 
1176         if (of->f_state != SMB_OFILE_STATE_OPEN) {
1177                 mutex_exit(&of->f_mutex);
1178                 return (NT_STATUS_INVALID_HANDLE);
1179         }
1180 
1181         if (of->f_granted_access &
1182             (FILE_READ_DATA | FILE_WRITE_DATA |
1183             FILE_APPEND_DATA | FILE_EXECUTE | DELETE)) {
1184                 mutex_exit(&of->f_mutex);
1185                 return (NT_STATUS_SHARING_VIOLATION);
1186         }
1187 
1188         mutex_exit(&of->f_mutex);
1189         return (NT_STATUS_SUCCESS);
1190 }
1191 
1192 cred_t *
1193 smb_ofile_getcred(smb_ofile_t *of)
1194 {
1195         return (of->f_cr);
1196 }
1197 
1198 /*
1199  * smb_ofile_set_delete_on_close
1200  *
1201  * Set the DeleteOnClose flag on the smb file. When the file is closed,
1202  * the flag will be transferred to the smb node, which will commit the
1203  * delete operation and inhibit subsequent open requests.
1204  *
1205  * When DeleteOnClose is set on an smb_node, the common open code will
1206  * reject subsequent open requests for the file. Observation of Windows
1207  * 2000 indicates that subsequent opens should be allowed (assuming
1208  * there would be no sharing violation) until the file is closed using
1209  * the fid on which the DeleteOnClose was requested.
1210  */
1211 void
1212 smb_ofile_set_delete_on_close(smb_ofile_t *of)
1213 {
1214         mutex_enter(&of->f_mutex);
1215         of->f_flags |= SMB_OFLAGS_SET_DELETE_ON_CLOSE;
1216         mutex_exit(&of->f_mutex);
1217 }
1218 
1219 /*
1220  * Encode open file information into a buffer; needed in user space to
1221  * support RPC requests.
1222  */
1223 static int
1224 smb_ofile_netinfo_encode(smb_ofile_t *of, uint8_t *buf, size_t buflen,
1225     uint32_t *nbytes)
1226 {
1227         smb_netfileinfo_t       fi;
1228         int                     rc;
1229 
1230         rc = smb_ofile_netinfo_init(of, &fi);
1231         if (rc == 0) {
1232                 rc = smb_netfileinfo_encode(&fi, buf, buflen, nbytes);
1233                 smb_ofile_netinfo_fini(&fi);
1234         }
1235 
1236         return (rc);
1237 }
1238 
1239 static int
1240 smb_ofile_netinfo_init(smb_ofile_t *of, smb_netfileinfo_t *fi)
1241 {
1242         smb_user_t      *user;
1243         smb_tree_t      *tree;
1244         smb_node_t      *node;
1245         char            *path;
1246         char            *buf;
1247         int             rc;
1248 
1249         ASSERT(of);
1250         user = of->f_user;
1251         tree = of->f_tree;
1252         ASSERT(user);
1253         ASSERT(tree);
1254 
1255         buf = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
1256 
1257         switch (of->f_ftype) {
1258         case SMB_FTYPE_DISK:
1259                 node = of->f_node;
1260                 ASSERT(node);
1261 
1262                 fi->fi_permissions = of->f_granted_access;
1263                 fi->fi_numlocks = smb_lock_get_lock_count(node, of);
1264 
1265                 path = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
1266 
1267                 if (node != tree->t_snode) {
1268                         rc = smb_node_getshrpath(node, tree, path, MAXPATHLEN);
1269                         if (rc != 0)
1270                                 (void) strlcpy(path, node->od_name, MAXPATHLEN);
1271                 }
1272 
1273                 (void) snprintf(buf, MAXPATHLEN, "%s:%s", tree->t_sharename,
1274                     path);
1275                 kmem_free(path, MAXPATHLEN);
1276                 break;
1277 
1278         case SMB_FTYPE_MESG_PIPE:
1279                 ASSERT(of->f_pipe);
1280 
1281                 fi->fi_permissions = FILE_READ_DATA | FILE_WRITE_DATA |
1282                     FILE_EXECUTE;
1283                 fi->fi_numlocks = 0;
1284                 (void) snprintf(buf, MAXPATHLEN, "\\PIPE\\%s",
1285                     of->f_pipe->p_name);
1286                 break;
1287 
1288         default:
1289                 kmem_free(buf, MAXPATHLEN);
1290                 return (-1);
1291         }
1292 
1293         fi->fi_fid = of->f_fid;
1294         fi->fi_uniqid = of->f_uniqid;
1295         fi->fi_pathlen = strlen(buf) + 1;
1296         fi->fi_path = smb_mem_strdup(buf);
1297         kmem_free(buf, MAXPATHLEN);
1298 
1299         fi->fi_namelen = user->u_domain_len + user->u_name_len + 2;
1300         fi->fi_username = kmem_alloc(fi->fi_namelen, KM_SLEEP);
1301         (void) snprintf(fi->fi_username, fi->fi_namelen, "%s\\%s",
1302             user->u_domain, user->u_name);
1303         return (0);
1304 }
1305 
1306 static void
1307 smb_ofile_netinfo_fini(smb_netfileinfo_t *fi)
1308 {
1309         if (fi == NULL)
1310                 return;
1311 
1312         if (fi->fi_path)
1313                 smb_mem_free(fi->fi_path);
1314         if (fi->fi_username)
1315                 kmem_free(fi->fi_username, fi->fi_namelen);
1316 
1317         bzero(fi, sizeof (smb_netfileinfo_t));
1318 }
1319 
1320 /*
1321  * A query of user and group quotas may span multiple requests.
1322  * f_quota_resume is used to determine where the query should
1323  * be resumed, in a subsequent request. f_quota_resume contains
1324  * the SID of the last quota entry returned to the client.
1325  */
1326 void
1327 smb_ofile_set_quota_resume(smb_ofile_t *ofile, char *resume)
1328 {
1329         ASSERT(ofile);
1330         mutex_enter(&ofile->f_mutex);
1331         if (resume == NULL)
1332                 bzero(ofile->f_quota_resume, SMB_SID_STRSZ);
1333         else
1334                 (void) strlcpy(ofile->f_quota_resume, resume, SMB_SID_STRSZ);
1335         mutex_exit(&ofile->f_mutex);
1336 }
1337 
1338 void
1339 smb_ofile_get_quota_resume(smb_ofile_t *ofile, char *buf, int bufsize)
1340 {
1341         ASSERT(ofile);
1342         mutex_enter(&ofile->f_mutex);
1343         (void) strlcpy(buf, ofile->f_quota_resume, bufsize);
1344         mutex_exit(&ofile->f_mutex);
1345 }