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