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 2009 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  * smb_ofile_seek
    651  *
    652  * Return value:
    653  *
    654  *	0		Success
    655  *	EINVAL		Unknown mode
    656  *	EOVERFLOW	offset too big
    657  *
    658  */
    659 int
    660 smb_ofile_seek(
    661     smb_ofile_t		*of,
    662     ushort_t		mode,
    663     int32_t		off,
    664     uint32_t		*retoff)
    665 {
    666 	u_offset_t	newoff = 0;
    667 	int		rc = 0;
    668 	smb_attr_t	attr;
    669 
    670 	ASSERT(of);
    671 	ASSERT(of->f_magic == SMB_OFILE_MAGIC);
    672 	ASSERT(of->f_refcnt);
    673 
    674 	mutex_enter(&of->f_mutex);
    675 	switch (mode) {
    676 	case SMB_SEEK_SET:
    677 		if (off < 0)
    678 			newoff = 0;
    679 		else
    680 			newoff = (u_offset_t)off;
    681 		break;
    682 
    683 	case SMB_SEEK_CUR:
    684 		if (off < 0 && (-off) > of->f_seek_pos)
    685 			newoff = 0;
    686 		else
    687 			newoff = of->f_seek_pos + (u_offset_t)off;
    688 		break;
    689 
    690 	case SMB_SEEK_END:
    691 		bzero(&attr, sizeof (smb_attr_t));
    692 		attr.sa_mask |= SMB_AT_SIZE;
    693 		rc = smb_fsop_getattr(NULL, kcred, of->f_node, &attr);
    694 		if (rc != 0) {
    695 			mutex_exit(&of->f_mutex);
    696 			return (rc);
    697 		}
    698 		if (off < 0 && (-off) > attr.sa_vattr.va_size)
    699 			newoff = 0;
    700 		else
    701 			newoff = attr.sa_vattr.va_size + (u_offset_t)off;
    702 		break;
    703 
    704 	default:
    705 		mutex_exit(&of->f_mutex);
    706 		return (EINVAL);
    707 	}
    708 
    709 	/*
    710 	 * See comments at the beginning of smb_seek.c.
    711 	 * If the offset is greater than UINT_MAX, we will return an error.
    712 	 */
    713 
    714 	if (newoff > UINT_MAX) {
    715 		rc = EOVERFLOW;
    716 	} else {
    717 		of->f_seek_pos = newoff;
    718 		*retoff = (uint32_t)newoff;
    719 	}
    720 	mutex_exit(&of->f_mutex);
    721 	return (rc);
    722 }
    723 
    724 /*
    725  * smb_ofile_is_open
    726  */
    727 boolean_t
    728 smb_ofile_is_open(smb_ofile_t *of)
    729 {
    730 	boolean_t	rc;
    731 
    732 	SMB_OFILE_VALID(of);
    733 
    734 	mutex_enter(&of->f_mutex);
    735 	rc = smb_ofile_is_open_locked(of);
    736 	mutex_exit(&of->f_mutex);
    737 	return (rc);
    738 }
    739 
    740 void
    741 smb_ofile_set_oplock_granted(smb_ofile_t *of)
    742 {
    743 	SMB_OFILE_VALID(of);
    744 	mutex_enter(&of->f_mutex);
    745 	ASSERT(!of->f_oplock_granted);
    746 	of->f_oplock_granted = B_TRUE;
    747 	of->f_oplock_exit = B_TRUE;
    748 	mutex_exit(&of->f_mutex);
    749 }
    750 
    751 /*
    752  * smb_ofile_pending_write_time
    753  *
    754  * Flag write times as pending - to be set on close, setattr
    755  * or delayed write timer.
    756  */
    757 void
    758 smb_ofile_set_write_time_pending(smb_ofile_t *of)
    759 {
    760 	SMB_OFILE_VALID(of);
    761 	mutex_enter(&of->f_mutex);
    762 	of->f_flags |= SMB_OFLAGS_TIMESTAMPS_PENDING;
    763 	mutex_exit(&of->f_mutex);
    764 }
    765 
    766 /*
    767  * smb_ofile_write_time_pending
    768  *
    769  * Get and reset the write times pending flag.
    770  */
    771 boolean_t
    772 smb_ofile_write_time_pending(smb_ofile_t *of)
    773 {
    774 	boolean_t rc = B_FALSE;
    775 
    776 	SMB_OFILE_VALID(of);
    777 	mutex_enter(&of->f_mutex);
    778 	if (of->f_flags & SMB_OFLAGS_TIMESTAMPS_PENDING) {
    779 		rc = B_TRUE;
    780 		of->f_flags &= ~SMB_OFLAGS_TIMESTAMPS_PENDING;
    781 	}
    782 	mutex_exit(&of->f_mutex);
    783 
    784 	return (rc);
    785 }
    786 
    787 /*
    788  * smb_ofile_set_explicit_time_flag
    789  *
    790  * Note the timestamps specified in "what", as having been
    791  * explicity set for the ofile.
    792  */
    793 void
    794 smb_ofile_set_explicit_times(smb_ofile_t *of, uint32_t what)
    795 {
    796 	SMB_OFILE_VALID(of);
    797 	mutex_enter(&of->f_mutex);
    798 	of->f_explicit_times |= (what & SMB_AT_TIMES);
    799 	mutex_exit(&of->f_mutex);
    800 }
    801 
    802 uint32_t
    803 smb_ofile_explicit_times(smb_ofile_t *of)
    804 {
    805 	uint32_t rc;
    806 
    807 	SMB_OFILE_VALID(of);
    808 	mutex_enter(&of->f_mutex);
    809 	rc = of->f_explicit_times;
    810 	mutex_exit(&of->f_mutex);
    811 
    812 	return (rc);
    813 }
    814 
    815 /* *************************** Static Functions ***************************** */
    816 
    817 /*
    818  * Determine whether or not an ofile is open.
    819  * This function must be called with the mutex held.
    820  */
    821 static boolean_t
    822 smb_ofile_is_open_locked(smb_ofile_t *of)
    823 {
    824 	switch (of->f_state) {
    825 	case SMB_OFILE_STATE_OPEN:
    826 		return (B_TRUE);
    827 
    828 	case SMB_OFILE_STATE_CLOSING:
    829 	case SMB_OFILE_STATE_CLOSED:
    830 		return (B_FALSE);
    831 
    832 	default:
    833 		ASSERT(0);
    834 		return (B_FALSE);
    835 	}
    836 }
    837 
    838 /*
    839  * smb_ofile_set_close_attrs
    840  *
    841  * Updates timestamps, size and readonly bit.
    842  * The last_wtime is specified in the request received
    843  * from the client. If it is neither 0 nor -1, this time
    844  * should be used as the file's mtime. It must first be
    845  * converted from the server's localtime (as received in
    846  * the client's request) to GMT.
    847  *
    848  * Call smb_node_setattr even if no attributes are being
    849  * explicitly set, to set any pending attributes.
    850  */
    851 static void
    852 smb_ofile_set_close_attrs(smb_ofile_t *of, uint32_t last_wtime)
    853 {
    854 	smb_node_t *node = of->f_node;
    855 	smb_attr_t attr;
    856 
    857 	bzero(&attr, sizeof (smb_attr_t));
    858 
    859 	/* For files created readonly, propagate readonly bit */
    860 	if (node->readonly_creator == of) {
    861 		attr.sa_mask |= SMB_AT_DOSATTR;
    862 		if (smb_fsop_getattr(NULL, kcred, node, &attr) &&
    863 		    (attr.sa_dosattr & FILE_ATTRIBUTE_READONLY)) {
    864 			attr.sa_mask = 0;
    865 		} else {
    866 			attr.sa_dosattr |= FILE_ATTRIBUTE_READONLY;
    867 		}
    868 
    869 		node->readonly_creator = NULL;
    870 	}
    871 
    872 	/* apply last_wtime if specified */
    873 	if (last_wtime != 0 && last_wtime != 0xFFFFFFFF) {
    874 		attr.sa_vattr.va_mtime.tv_sec =
    875 		    last_wtime + of->f_server->si_gmtoff;
    876 		attr.sa_mask |= SMB_AT_MTIME;
    877 	}
    878 
    879 	(void) smb_node_setattr(NULL, node, of->f_cr, of, &attr);
    880 }
    881 
    882 /*
    883  * smb_ofile_close_and_next
    884  *
    885  * This function closes the file passed in (if appropriate) and returns the
    886  * next open file in the list of open files of the tree of the open file passed
    887  * in. It requires that the list of open files of the tree be entered in
    888  * RW_READER mode before being called.
    889  */
    890 static smb_ofile_t *
    891 smb_ofile_close_and_next(smb_ofile_t *of)
    892 {
    893 	smb_ofile_t	*next_of;
    894 	smb_tree_t	*tree;
    895 
    896 	ASSERT(of);
    897 	ASSERT(of->f_magic == SMB_OFILE_MAGIC);
    898 
    899 	mutex_enter(&of->f_mutex);
    900 	switch (of->f_state) {
    901 	case SMB_OFILE_STATE_OPEN:
    902 		/* The file is still open. */
    903 		of->f_refcnt++;
    904 		ASSERT(of->f_refcnt);
    905 		tree = of->f_tree;
    906 		mutex_exit(&of->f_mutex);
    907 		smb_llist_exit(&of->f_tree->t_ofile_list);
    908 		smb_ofile_close(of, 0);
    909 		smb_ofile_release(of);
    910 		smb_llist_enter(&tree->t_ofile_list, RW_READER);
    911 		next_of = smb_llist_head(&tree->t_ofile_list);
    912 		break;
    913 	case SMB_OFILE_STATE_CLOSING:
    914 	case SMB_OFILE_STATE_CLOSED:
    915 		/*
    916 		 * The ofile exists but is closed or
    917 		 * in the process being closed.
    918 		 */
    919 		mutex_exit(&of->f_mutex);
    920 		next_of = smb_llist_next(&of->f_tree->t_ofile_list, of);
    921 		break;
    922 	default:
    923 		ASSERT(0);
    924 		mutex_exit(&of->f_mutex);
    925 		next_of = smb_llist_next(&of->f_tree->t_ofile_list, of);
    926 		break;
    927 	}
    928 	return (next_of);
    929 }
    930 
    931 /*
    932  * smb_ofile_delete
    933  *
    934  *
    935  */
    936 static void
    937 smb_ofile_delete(smb_ofile_t *of)
    938 {
    939 	ASSERT(of);
    940 	ASSERT(of->f_magic == SMB_OFILE_MAGIC);
    941 	ASSERT(of->f_refcnt == 0);
    942 	ASSERT(of->f_state == SMB_OFILE_STATE_CLOSED);
    943 
    944 	/*
    945 	 * Let's remove the ofile from the list of ofiles of the tree. This has
    946 	 * to be done before any resources associated with the ofile are
    947 	 * released.
    948 	 */
    949 	smb_llist_enter(&of->f_tree->t_ofile_list, RW_WRITER);
    950 	smb_llist_remove(&of->f_tree->t_ofile_list, of);
    951 	smb_llist_exit(&of->f_tree->t_ofile_list);
    952 	atomic_dec_32(&of->f_session->s_file_cnt);
    953 
    954 	if (of->f_ftype == SMB_FTYPE_MESG_PIPE) {
    955 		kmem_free(of->f_pipe, sizeof (smb_opipe_t));
    956 		of->f_pipe = NULL;
    957 	} else {
    958 		ASSERT(of->f_ftype == SMB_FTYPE_DISK);
    959 		ASSERT(of->f_node != NULL);
    960 		smb_node_rem_ofile(of->f_node, of);
    961 		smb_node_release(of->f_node);
    962 	}
    963 
    964 	of->f_magic = (uint32_t)~SMB_OFILE_MAGIC;
    965 	mutex_destroy(&of->f_mutex);
    966 	crfree(of->f_cr);
    967 	smb_idpool_free(&of->f_tree->t_fid_pool, of->f_fid);
    968 	kmem_cache_free(of->f_tree->t_server->si_cache_ofile, of);
    969 }
    970 
    971 /*
    972  * smb_ofile_access
    973  *
    974  * This function will check to see if the access requested is granted.
    975  * Returns NT status codes.
    976  */
    977 uint32_t
    978 smb_ofile_access(smb_ofile_t *of, cred_t *cr, uint32_t access)
    979 {
    980 
    981 	if ((of == NULL) || (cr == kcred))
    982 		return (NT_STATUS_SUCCESS);
    983 
    984 	/*
    985 	 * If the request is for something
    986 	 * I don't grant it is an error
    987 	 */
    988 	if (~(of->f_granted_access) & access) {
    989 		if (!(of->f_granted_access & ACCESS_SYSTEM_SECURITY) &&
    990 		    (access & ACCESS_SYSTEM_SECURITY)) {
    991 			return (NT_STATUS_PRIVILEGE_NOT_HELD);
    992 		}
    993 		return (NT_STATUS_ACCESS_DENIED);
    994 	}
    995 
    996 	return (NT_STATUS_SUCCESS);
    997 }
    998 
    999 
   1000 /*
   1001  * smb_ofile_open_check
   1002  *
   1003  * check file sharing rules for current open request
   1004  * against existing open instances of the same file
   1005  *
   1006  * Returns NT_STATUS_SHARING_VIOLATION if there is any
   1007  * sharing conflict, otherwise returns NT_STATUS_SUCCESS.
   1008  */
   1009 uint32_t
   1010 smb_ofile_open_check(
   1011     smb_ofile_t *of,
   1012     cred_t *cr,
   1013     uint32_t desired_access,
   1014     uint32_t share_access)
   1015 {
   1016 	smb_node_t *node;
   1017 
   1018 	ASSERT(of->f_magic == SMB_OFILE_MAGIC);
   1019 
   1020 	node = of->f_node;
   1021 
   1022 	mutex_enter(&of->f_mutex);
   1023 
   1024 	if (of->f_state !=  SMB_OFILE_STATE_OPEN) {
   1025 		mutex_exit(&of->f_mutex);
   1026 		return (NT_STATUS_INVALID_HANDLE);
   1027 	}
   1028 
   1029 	/*
   1030 	 * It appears that share modes are not relevant to
   1031 	 * directories, but this check will remain as it is not
   1032 	 * clear whether it was originally put here for a reason.
   1033 	 */
   1034 	if (smb_node_is_dir(node)) {
   1035 		if (SMB_DENY_RW(of->f_share_access) &&
   1036 		    (node->n_orig_uid != crgetuid(cr))) {
   1037 			mutex_exit(&of->f_mutex);
   1038 			return (NT_STATUS_SHARING_VIOLATION);
   1039 		}
   1040 
   1041 		mutex_exit(&of->f_mutex);
   1042 		return (NT_STATUS_SUCCESS);
   1043 	}
   1044 
   1045 	/* if it's just meta data */
   1046 	if ((of->f_granted_access & FILE_DATA_ALL) == 0) {
   1047 		mutex_exit(&of->f_mutex);
   1048 		return (NT_STATUS_SUCCESS);
   1049 	}
   1050 
   1051 	/*
   1052 	 * Check requested share access against the
   1053 	 * open granted (desired) access
   1054 	 */
   1055 	if (SMB_DENY_DELETE(share_access) && (of->f_granted_access & DELETE)) {
   1056 		mutex_exit(&of->f_mutex);
   1057 		return (NT_STATUS_SHARING_VIOLATION);
   1058 	}
   1059 
   1060 	if (SMB_DENY_READ(share_access) &&
   1061 	    (of->f_granted_access & (FILE_READ_DATA | FILE_EXECUTE))) {
   1062 		mutex_exit(&of->f_mutex);
   1063 		return (NT_STATUS_SHARING_VIOLATION);
   1064 	}
   1065 
   1066 	if (SMB_DENY_WRITE(share_access) &&
   1067 	    (of->f_granted_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) {
   1068 		mutex_exit(&of->f_mutex);
   1069 		return (NT_STATUS_SHARING_VIOLATION);
   1070 	}
   1071 
   1072 	/* check requested desired access against the open share access */
   1073 	if (SMB_DENY_DELETE(of->f_share_access) && (desired_access & DELETE)) {
   1074 		mutex_exit(&of->f_mutex);
   1075 		return (NT_STATUS_SHARING_VIOLATION);
   1076 	}
   1077 
   1078 	if (SMB_DENY_READ(of->f_share_access) &&
   1079 	    (desired_access & (FILE_READ_DATA | FILE_EXECUTE))) {
   1080 		mutex_exit(&of->f_mutex);
   1081 		return (NT_STATUS_SHARING_VIOLATION);
   1082 	}
   1083 
   1084 	if (SMB_DENY_WRITE(of->f_share_access) &&
   1085 	    (desired_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) {
   1086 		mutex_exit(&of->f_mutex);
   1087 		return (NT_STATUS_SHARING_VIOLATION);
   1088 	}
   1089 
   1090 	mutex_exit(&of->f_mutex);
   1091 	return (NT_STATUS_SUCCESS);
   1092 }
   1093 
   1094 /*
   1095  * smb_ofile_rename_check
   1096  *
   1097  * An open file can be renamed if
   1098  *
   1099  *  1. isn't opened for data writing or deleting
   1100  *
   1101  *  2. Opened with "Deny Delete" share mode
   1102  *         But not opened for data reading or executing
   1103  *         (opened for accessing meta data)
   1104  */
   1105 
   1106 uint32_t
   1107 smb_ofile_rename_check(smb_ofile_t *of)
   1108 {
   1109 	ASSERT(of->f_magic == SMB_OFILE_MAGIC);
   1110 
   1111 	mutex_enter(&of->f_mutex);
   1112 
   1113 	if (of->f_state != SMB_OFILE_STATE_OPEN) {
   1114 		mutex_exit(&of->f_mutex);
   1115 		return (NT_STATUS_INVALID_HANDLE);
   1116 	}
   1117 
   1118 	if (of->f_granted_access &
   1119 	    (FILE_WRITE_DATA | FILE_APPEND_DATA | DELETE)) {
   1120 		mutex_exit(&of->f_mutex);
   1121 		return (NT_STATUS_SHARING_VIOLATION);
   1122 	}
   1123 
   1124 	if ((of->f_share_access & FILE_SHARE_DELETE) == 0) {
   1125 		if (of->f_granted_access &
   1126 		    (FILE_READ_DATA | FILE_EXECUTE)) {
   1127 			mutex_exit(&of->f_mutex);
   1128 			return (NT_STATUS_SHARING_VIOLATION);
   1129 		}
   1130 	}
   1131 
   1132 	mutex_exit(&of->f_mutex);
   1133 	return (NT_STATUS_SUCCESS);
   1134 }
   1135 
   1136 /*
   1137  * smb_ofile_delete_check
   1138  *
   1139  * An open file can be deleted only if opened for
   1140  * accessing meta data. Share modes aren't important
   1141  * in this case.
   1142  *
   1143  * NOTE: there is another mechanism for deleting an
   1144  * open file that NT clients usually use.
   1145  * That's setting "Delete on close" flag for an open
   1146  * file.  In this way the file will be deleted after
   1147  * last close. This flag can be set by SmbTrans2SetFileInfo
   1148  * with FILE_DISPOSITION_INFO information level.
   1149  * For setting this flag, the file should be opened by
   1150  * DELETE access in the FID that is passed in the Trans2
   1151  * request.
   1152  */
   1153 
   1154 uint32_t
   1155 smb_ofile_delete_check(smb_ofile_t *of)
   1156 {
   1157 	ASSERT(of->f_magic == SMB_OFILE_MAGIC);
   1158 
   1159 	mutex_enter(&of->f_mutex);
   1160 
   1161 	if (of->f_state != SMB_OFILE_STATE_OPEN) {
   1162 		mutex_exit(&of->f_mutex);
   1163 		return (NT_STATUS_INVALID_HANDLE);
   1164 	}
   1165 
   1166 	if (of->f_granted_access &
   1167 	    (FILE_READ_DATA | FILE_WRITE_DATA |
   1168 	    FILE_APPEND_DATA | FILE_EXECUTE | DELETE)) {
   1169 		mutex_exit(&of->f_mutex);
   1170 		return (NT_STATUS_SHARING_VIOLATION);
   1171 	}
   1172 
   1173 	mutex_exit(&of->f_mutex);
   1174 	return (NT_STATUS_SUCCESS);
   1175 }
   1176 
   1177 cred_t *
   1178 smb_ofile_getcred(smb_ofile_t *of)
   1179 {
   1180 	return (of->f_cr);
   1181 }
   1182 
   1183 /*
   1184  * smb_ofile_set_delete_on_close
   1185  *
   1186  * Set the DeleteOnClose flag on the smb file. When the file is closed,
   1187  * the flag will be transferred to the smb node, which will commit the
   1188  * delete operation and inhibit subsequent open requests.
   1189  *
   1190  * When DeleteOnClose is set on an smb_node, the common open code will
   1191  * reject subsequent open requests for the file. Observation of Windows
   1192  * 2000 indicates that subsequent opens should be allowed (assuming
   1193  * there would be no sharing violation) until the file is closed using
   1194  * the fid on which the DeleteOnClose was requested.
   1195  */
   1196 void
   1197 smb_ofile_set_delete_on_close(smb_ofile_t *of)
   1198 {
   1199 	mutex_enter(&of->f_mutex);
   1200 	of->f_flags |= SMB_OFLAGS_SET_DELETE_ON_CLOSE;
   1201 	mutex_exit(&of->f_mutex);
   1202 }
   1203 
   1204 /*
   1205  * Encode open file information into a buffer; needed in user space to
   1206  * support RPC requests.
   1207  */
   1208 static int
   1209 smb_ofile_netinfo_encode(smb_ofile_t *of, uint8_t *buf, size_t buflen,
   1210     uint32_t *nbytes)
   1211 {
   1212 	smb_netfileinfo_t	fi;
   1213 	int			rc;
   1214 
   1215 	rc = smb_ofile_netinfo_init(of, &fi);
   1216 	if (rc == 0) {
   1217 		rc = smb_netfileinfo_encode(&fi, buf, buflen, nbytes);
   1218 		smb_ofile_netinfo_fini(&fi);
   1219 	}
   1220 
   1221 	return (rc);
   1222 }
   1223 
   1224 static int
   1225 smb_ofile_netinfo_init(smb_ofile_t *of, smb_netfileinfo_t *fi)
   1226 {
   1227 	smb_user_t	*user;
   1228 	smb_tree_t	*tree;
   1229 	smb_node_t	*node;
   1230 	char		*path;
   1231 	char		*buf;
   1232 	int		rc;
   1233 
   1234 	ASSERT(of);
   1235 	user = of->f_user;
   1236 	tree = of->f_tree;
   1237 	ASSERT(user);
   1238 	ASSERT(tree);
   1239 
   1240 	buf = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
   1241 
   1242 	switch (of->f_ftype) {
   1243 	case SMB_FTYPE_DISK:
   1244 		node = of->f_node;
   1245 		ASSERT(node);
   1246 
   1247 		fi->fi_permissions = of->f_granted_access;
   1248 		fi->fi_numlocks = smb_lock_get_lock_count(node);
   1249 
   1250 		path = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
   1251 
   1252 		if (node != tree->t_snode) {
   1253 			rc = vnodetopath(tree->t_snode->vp, node->vp, path,
   1254 			    MAXPATHLEN, kcred);
   1255 			if (rc == 0)
   1256 				(void) strsubst(path, '/', '\\');
   1257 			else
   1258 				(void) strlcpy(path, node->od_name, MAXPATHLEN);
   1259 		}
   1260 
   1261 		(void) snprintf(buf, MAXPATHLEN, "%s:%s", tree->t_sharename,
   1262 		    path);
   1263 		kmem_free(path, MAXPATHLEN);
   1264 		break;
   1265 
   1266 	case SMB_FTYPE_MESG_PIPE:
   1267 		ASSERT(of->f_pipe);
   1268 
   1269 		fi->fi_permissions = FILE_READ_DATA | FILE_WRITE_DATA |
   1270 		    FILE_EXECUTE;
   1271 		fi->fi_numlocks = 0;
   1272 		(void) snprintf(buf, MAXPATHLEN, "\\PIPE\\%s",
   1273 		    of->f_pipe->p_name);
   1274 		break;
   1275 
   1276 	default:
   1277 		kmem_free(buf, MAXPATHLEN);
   1278 		return (-1);
   1279 	}
   1280 
   1281 	fi->fi_fid = of->f_fid;
   1282 	fi->fi_uniqid = of->f_uniqid;
   1283 	fi->fi_pathlen = strlen(buf) + 1;
   1284 	fi->fi_path = smb_strdup(buf);
   1285 	kmem_free(buf, MAXPATHLEN);
   1286 
   1287 	fi->fi_namelen = user->u_domain_len + user->u_name_len + 2;
   1288 	fi->fi_username = kmem_alloc(fi->fi_namelen, KM_SLEEP);
   1289 	(void) snprintf(fi->fi_username, fi->fi_namelen, "%s\\%s",
   1290 	    user->u_domain, user->u_name);
   1291 	return (0);
   1292 }
   1293 
   1294 static void
   1295 smb_ofile_netinfo_fini(smb_netfileinfo_t *fi)
   1296 {
   1297 	if (fi == NULL)
   1298 		return;
   1299 
   1300 	if (fi->fi_path)
   1301 		smb_mfree(fi->fi_path);
   1302 	if (fi->fi_username)
   1303 		kmem_free(fi->fi_username, fi->fi_namelen);
   1304 
   1305 	bzero(fi, sizeof (smb_netfileinfo_t));
   1306 }
   1307