1da6c28aaSamw /* 2da6c28aaSamw * CDDL HEADER START 3da6c28aaSamw * 4da6c28aaSamw * The contents of this file are subject to the terms of the 5da6c28aaSamw * Common Development and Distribution License (the "License"). 6da6c28aaSamw * You may not use this file except in compliance with the License. 7da6c28aaSamw * 8da6c28aaSamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9da6c28aaSamw * or http://www.opensolaris.org/os/licensing. 10da6c28aaSamw * See the License for the specific language governing permissions 11da6c28aaSamw * and limitations under the License. 12da6c28aaSamw * 13da6c28aaSamw * When distributing Covered Code, include this CDDL HEADER in each 14da6c28aaSamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15da6c28aaSamw * If applicable, add the following below this CDDL HEADER, with the 16da6c28aaSamw * fields enclosed by brackets "[]" replaced with your own identifying 17da6c28aaSamw * information: Portions Copyright [yyyy] [name of copyright owner] 18da6c28aaSamw * 19da6c28aaSamw * CDDL HEADER END 20da6c28aaSamw */ 21da6c28aaSamw /* 22*f96bd5c8SAlan Wright * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23da6c28aaSamw * Use is subject to license terms. 24da6c28aaSamw */ 25da6c28aaSamw 26da6c28aaSamw /* 27da6c28aaSamw * General Structures Layout 28da6c28aaSamw * ------------------------- 29da6c28aaSamw * 30da6c28aaSamw * This is a simplified diagram showing the relationship between most of the 31da6c28aaSamw * main structures. 32da6c28aaSamw * 33da6c28aaSamw * +-------------------+ 34da6c28aaSamw * | SMB_INFO | 35da6c28aaSamw * +-------------------+ 36da6c28aaSamw * | 37da6c28aaSamw * | 38da6c28aaSamw * v 39da6c28aaSamw * +-------------------+ +-------------------+ +-------------------+ 40da6c28aaSamw * | SESSION |<----->| SESSION |......| SESSION | 41da6c28aaSamw * +-------------------+ +-------------------+ +-------------------+ 42da6c28aaSamw * | 43da6c28aaSamw * | 44da6c28aaSamw * v 45da6c28aaSamw * +-------------------+ +-------------------+ +-------------------+ 46da6c28aaSamw * | USER |<----->| USER |......| USER | 47da6c28aaSamw * +-------------------+ +-------------------+ +-------------------+ 48da6c28aaSamw * | 49da6c28aaSamw * | 50da6c28aaSamw * v 51da6c28aaSamw * +-------------------+ +-------------------+ +-------------------+ 52da6c28aaSamw * | TREE |<----->| TREE |......| TREE | 53da6c28aaSamw * +-------------------+ +-------------------+ +-------------------+ 54da6c28aaSamw * | | 55da6c28aaSamw * | | 56da6c28aaSamw * | v 57da6c28aaSamw * | +-------+ +-------+ +-------+ 58da6c28aaSamw * | | OFILE |<----->| OFILE |......| OFILE | 59da6c28aaSamw * | +-------+ +-------+ +-------+ 60da6c28aaSamw * | 61da6c28aaSamw * | 62da6c28aaSamw * v 63da6c28aaSamw * +-------+ +------+ +------+ 64da6c28aaSamw * | ODIR |<----->| ODIR |......| ODIR | 65da6c28aaSamw * +-------+ +------+ +------+ 66da6c28aaSamw * 67da6c28aaSamw * 68da6c28aaSamw * Ofile State Machine 69da6c28aaSamw * ------------------ 70da6c28aaSamw * 71da6c28aaSamw * +-------------------------+ T0 72da6c28aaSamw * | SMB_OFILE_STATE_OPEN |<----------- Creation/Allocation 73da6c28aaSamw * +-------------------------+ 74da6c28aaSamw * | 75da6c28aaSamw * | T1 76da6c28aaSamw * | 77da6c28aaSamw * v 78da6c28aaSamw * +-------------------------+ 79da6c28aaSamw * | SMB_OFILE_STATE_CLOSING | 80da6c28aaSamw * +-------------------------+ 81da6c28aaSamw * | 82da6c28aaSamw * | T2 83da6c28aaSamw * | 84da6c28aaSamw * v 85da6c28aaSamw * +-------------------------+ T3 86da6c28aaSamw * | SMB_OFILE_STATE_CLOSED |----------> Deletion/Free 87da6c28aaSamw * +-------------------------+ 88da6c28aaSamw * 89da6c28aaSamw * SMB_OFILE_STATE_OPEN 90da6c28aaSamw * 91da6c28aaSamw * While in this state: 92da6c28aaSamw * - The ofile is queued in the list of ofiles of its tree. 93da6c28aaSamw * - References will be given out if the ofile is looked up. 94da6c28aaSamw * 95da6c28aaSamw * SMB_OFILE_STATE_CLOSING 96da6c28aaSamw * 97da6c28aaSamw * While in this state: 98da6c28aaSamw * - The ofile is queued in the list of ofiles of its tree. 99da6c28aaSamw * - References will not be given out if the ofile is looked up. 100da6c28aaSamw * - The file is closed and the locks held are being released. 101da6c28aaSamw * - The resources associated with the ofile remain. 102da6c28aaSamw * 103da6c28aaSamw * SMB_OFILE_STATE_CLOSED 104da6c28aaSamw * 105da6c28aaSamw * While in this state: 106da6c28aaSamw * - The ofile is queued in the list of ofiles of its tree. 107da6c28aaSamw * - References will not be given out if the ofile is looked up. 108da6c28aaSamw * - The resources associated with the ofile remain. 109da6c28aaSamw * 110da6c28aaSamw * Transition T0 111da6c28aaSamw * 112da6c28aaSamw * This transition occurs in smb_ofile_open(). A new ofile is created and 113da6c28aaSamw * added to the list of ofiles of a tree. 114da6c28aaSamw * 115da6c28aaSamw * Transition T1 116da6c28aaSamw * 117da6c28aaSamw * This transition occurs in smb_ofile_close(). 118da6c28aaSamw * 119da6c28aaSamw * Transition T2 120da6c28aaSamw * 121da6c28aaSamw * This transition occurs in smb_ofile_release(). The resources associated 122da6c28aaSamw * with the ofile are freed as well as the ofile structure. For the 123da6c28aaSamw * transition to occur, the ofile must be in the SMB_OFILE_STATE_CLOSED 124da6c28aaSamw * state and the reference count be zero. 125da6c28aaSamw * 126da6c28aaSamw * Comments 127da6c28aaSamw * -------- 128da6c28aaSamw * 129da6c28aaSamw * The state machine of the ofile structures is controlled by 3 elements: 130da6c28aaSamw * - The list of ofiles of the tree it belongs to. 131da6c28aaSamw * - The mutex embedded in the structure itself. 132da6c28aaSamw * - The reference count. 133da6c28aaSamw * 134da6c28aaSamw * There's a mutex embedded in the ofile structure used to protect its fields 135da6c28aaSamw * and there's a lock embedded in the list of ofiles of a tree. To 136da6c28aaSamw * increment or to decrement the reference count the mutex must be entered. 137da6c28aaSamw * To insert the ofile into the list of ofiles of the tree and to remove 138da6c28aaSamw * the ofile from it, the lock must be entered in RW_WRITER mode. 139da6c28aaSamw * 140da6c28aaSamw * Rules of access to a ofile structure: 141da6c28aaSamw * 142da6c28aaSamw * 1) In order to avoid deadlocks, when both (mutex and lock of the ofile 143da6c28aaSamw * list) have to be entered, the lock must be entered first. 144da6c28aaSamw * 145da6c28aaSamw * 2) All actions applied to an ofile require a reference count. 146da6c28aaSamw * 147da6c28aaSamw * 3) There are 2 ways of getting a reference count. One is when the ofile 148da6c28aaSamw * is opened. The other one when the ofile is looked up. This translates 149da6c28aaSamw * into 2 functions: smb_ofile_open() and smb_ofile_lookup_by_fid(). 150da6c28aaSamw * 151da6c28aaSamw * It should be noted that the reference count of an ofile registers the 152da6c28aaSamw * number of references to the ofile in other structures (such as an smb 153da6c28aaSamw * request). The reference count is not incremented in these 2 instances: 154da6c28aaSamw * 155da6c28aaSamw * 1) The ofile is open. An ofile is anchored by his state. If there's 156da6c28aaSamw * no activity involving an ofile currently open, the reference count 157da6c28aaSamw * of that ofile is zero. 158da6c28aaSamw * 159da6c28aaSamw * 2) The ofile is queued in the list of ofiles of its tree. The fact of 160da6c28aaSamw * being queued in that list is NOT registered by incrementing the 161da6c28aaSamw * reference count. 162da6c28aaSamw */ 163da6c28aaSamw #include <smbsrv/smb_kproto.h> 164da6c28aaSamw #include <smbsrv/smb_fsops.h> 165da6c28aaSamw 1661fcced4cSJordan Brown static boolean_t smb_ofile_is_open_locked(smb_ofile_t *); 1671fcced4cSJordan Brown static void smb_ofile_delete(smb_ofile_t *); 1681fcced4cSJordan Brown static smb_ofile_t *smb_ofile_close_and_next(smb_ofile_t *); 169037cac00Sjoyce mcintosh static void smb_ofile_set_close_attrs(smb_ofile_t *, uint32_t); 1701fcced4cSJordan Brown static int smb_ofile_netinfo_encode(smb_ofile_t *, uint8_t *, size_t, 1711fcced4cSJordan Brown uint32_t *); 1721fcced4cSJordan Brown static int smb_ofile_netinfo_init(smb_ofile_t *, smb_netfileinfo_t *); 1731fcced4cSJordan Brown static void smb_ofile_netinfo_fini(smb_netfileinfo_t *); 174da6c28aaSamw 175da6c28aaSamw /* 176da6c28aaSamw * smb_ofile_open 177da6c28aaSamw */ 178da6c28aaSamw smb_ofile_t * 179da6c28aaSamw smb_ofile_open( 180da6c28aaSamw smb_tree_t *tree, 181da6c28aaSamw smb_node_t *node, 182da6c28aaSamw uint16_t pid, 183c8ec8eeaSjose borrego struct open_param *op, 184da6c28aaSamw uint16_t ftype, 185dc20a302Sas200622 uint32_t uniqid, 186da6c28aaSamw smb_error_t *err) 187da6c28aaSamw { 188da6c28aaSamw smb_ofile_t *of; 189da6c28aaSamw uint16_t fid; 190037cac00Sjoyce mcintosh smb_attr_t attr; 191da6c28aaSamw 192da6c28aaSamw if (smb_idpool_alloc(&tree->t_fid_pool, &fid)) { 193da6c28aaSamw err->status = NT_STATUS_TOO_MANY_OPENED_FILES; 194da6c28aaSamw err->errcls = ERRDOS; 195da6c28aaSamw err->errcode = ERROR_TOO_MANY_OPEN_FILES; 196da6c28aaSamw return (NULL); 197da6c28aaSamw } 198da6c28aaSamw 199faa1795aSjb150015 of = kmem_cache_alloc(tree->t_server->si_cache_ofile, KM_SLEEP); 200da6c28aaSamw bzero(of, sizeof (smb_ofile_t)); 201da6c28aaSamw of->f_magic = SMB_OFILE_MAGIC; 202da6c28aaSamw of->f_refcnt = 1; 203da6c28aaSamw of->f_fid = fid; 204dc20a302Sas200622 of->f_uniqid = uniqid; 205da6c28aaSamw of->f_opened_by_pid = pid; 206c8ec8eeaSjose borrego of->f_granted_access = op->desired_access; 207c8ec8eeaSjose borrego of->f_share_access = op->share_access; 208c8ec8eeaSjose borrego of->f_create_options = op->create_options; 209b89a8333Snatalie li - Sun Microsystems - Irvine United States of->f_cr = (op->create_options & FILE_OPEN_FOR_BACKUP_INTENT) ? 210b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_user_getprivcred(tree->t_user) : tree->t_user->u_cred; 211da6c28aaSamw crhold(of->f_cr); 212da6c28aaSamw of->f_ftype = ftype; 213faa1795aSjb150015 of->f_server = tree->t_server; 214da6c28aaSamw of->f_session = tree->t_user->u_session; 215da6c28aaSamw of->f_user = tree->t_user; 216da6c28aaSamw of->f_tree = tree; 217da6c28aaSamw of->f_node = node; 218037cac00Sjoyce mcintosh of->f_explicit_times = 0; 219da6c28aaSamw mutex_init(&of->f_mutex, NULL, MUTEX_DEFAULT, NULL); 220da6c28aaSamw of->f_state = SMB_OFILE_STATE_OPEN; 221da6c28aaSamw 222037cac00Sjoyce mcintosh 223da6c28aaSamw if (ftype == SMB_FTYPE_MESG_PIPE) { 2243db3f65cSamw of->f_pipe = kmem_zalloc(sizeof (smb_opipe_t), KM_SLEEP); 225da6c28aaSamw } else { 226da6c28aaSamw ASSERT(ftype == SMB_FTYPE_DISK); /* Regular file, not a pipe */ 227da6c28aaSamw ASSERT(node); 2282c2961f8Sjose borrego 2292c2961f8Sjose borrego if (of->f_granted_access == FILE_EXECUTE) 2302c2961f8Sjose borrego of->f_flags |= SMB_OFLAGS_EXECONLY; 2312c2961f8Sjose borrego 232037cac00Sjoyce mcintosh bzero(&attr, sizeof (smb_attr_t)); 233037cac00Sjoyce mcintosh attr.sa_mask |= SMB_AT_UID; 234037cac00Sjoyce mcintosh if (smb_fsop_getattr(NULL, kcred, node, &attr) != 0) { 235037cac00Sjoyce mcintosh of->f_magic = 0; 236037cac00Sjoyce mcintosh mutex_destroy(&of->f_mutex); 237037cac00Sjoyce mcintosh crfree(of->f_cr); 238037cac00Sjoyce mcintosh smb_idpool_free(&tree->t_fid_pool, of->f_fid); 239037cac00Sjoyce mcintosh kmem_cache_free(tree->t_server->si_cache_ofile, of); 240037cac00Sjoyce mcintosh err->status = NT_STATUS_INTERNAL_ERROR; 241037cac00Sjoyce mcintosh err->errcls = ERRDOS; 242037cac00Sjoyce mcintosh err->errcode = ERROR_INTERNAL_ERROR; 243037cac00Sjoyce mcintosh return (NULL); 244037cac00Sjoyce mcintosh } 245037cac00Sjoyce mcintosh if (crgetuid(of->f_cr) == attr.sa_vattr.va_uid) { 246da6c28aaSamw /* 247da6c28aaSamw * Add this bit for the file's owner even if it's not 248da6c28aaSamw * specified in the request (Windows behavior). 249da6c28aaSamw */ 250da6c28aaSamw of->f_granted_access |= FILE_READ_ATTRIBUTES; 251da6c28aaSamw } 252da6c28aaSamw 2538c10a865Sas200622 if (node->vp->v_type == VREG) { 2548c10a865Sas200622 of->f_mode = 2558c10a865Sas200622 smb_fsop_amask_to_omode(of->f_granted_access); 256c8ec8eeaSjose borrego if (smb_fsop_open(node, of->f_mode, of->f_cr) != 0) { 257da6c28aaSamw of->f_magic = 0; 258da6c28aaSamw mutex_destroy(&of->f_mutex); 259da6c28aaSamw crfree(of->f_cr); 260c8ec8eeaSjose borrego smb_idpool_free(&tree->t_fid_pool, of->f_fid); 2618c10a865Sas200622 kmem_cache_free(tree->t_server->si_cache_ofile, 2628c10a865Sas200622 of); 263da6c28aaSamw err->status = NT_STATUS_ACCESS_DENIED; 264da6c28aaSamw err->errcls = ERRDOS; 265da6c28aaSamw err->errcode = ERROR_ACCESS_DENIED; 266da6c28aaSamw return (NULL); 267da6c28aaSamw } 2688c10a865Sas200622 } 2698c10a865Sas200622 270c8ec8eeaSjose borrego if (tree->t_flags & SMB_TREE_READONLY) 271c8ec8eeaSjose borrego of->f_flags |= SMB_OFLAGS_READONLY; 272c8ec8eeaSjose borrego 273c8ec8eeaSjose borrego if (op->created_readonly) 274c8ec8eeaSjose borrego node->readonly_creator = of; 275c8ec8eeaSjose borrego 2762c2961f8Sjose borrego smb_node_inc_open_ofiles(node); 277fc724630SAlan Wright smb_node_add_ofile(node, of); 2788b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_node_ref(node); 279da6c28aaSamw } 280da6c28aaSamw smb_llist_enter(&tree->t_ofile_list, RW_WRITER); 281da6c28aaSamw smb_llist_insert_tail(&tree->t_ofile_list, of); 282da6c28aaSamw smb_llist_exit(&tree->t_ofile_list); 2831fcced4cSJordan Brown atomic_inc_32(&tree->t_open_files); 284faa1795aSjb150015 atomic_inc_32(&tree->t_server->sv_open_files); 285da6c28aaSamw atomic_inc_32(&of->f_session->s_file_cnt); 286da6c28aaSamw 287da6c28aaSamw return (of); 288da6c28aaSamw } 289da6c28aaSamw 290da6c28aaSamw /* 291da6c28aaSamw * smb_ofile_close 292da6c28aaSamw */ 293c8ec8eeaSjose borrego void 294037cac00Sjoyce mcintosh smb_ofile_close(smb_ofile_t *of, uint32_t last_wtime) 295da6c28aaSamw { 296da6c28aaSamw ASSERT(of); 297da6c28aaSamw ASSERT(of->f_magic == SMB_OFILE_MAGIC); 2988b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States uint32_t flags = 0; 299da6c28aaSamw 300da6c28aaSamw mutex_enter(&of->f_mutex); 301da6c28aaSamw ASSERT(of->f_refcnt); 302da6c28aaSamw switch (of->f_state) { 303da6c28aaSamw case SMB_OFILE_STATE_OPEN: { 304da6c28aaSamw 305da6c28aaSamw of->f_state = SMB_OFILE_STATE_CLOSING; 306da6c28aaSamw mutex_exit(&of->f_mutex); 307da6c28aaSamw 308da6c28aaSamw if (of->f_ftype == SMB_FTYPE_MESG_PIPE) { 3093db3f65cSamw smb_opipe_close(of); 310da6c28aaSamw } else { 311037cac00Sjoyce mcintosh smb_ofile_set_close_attrs(of, last_wtime); 312da6c28aaSamw 3138b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (of->f_flags & SMB_OFLAGS_SET_DELETE_ON_CLOSE) { 3148b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States if (smb_tree_has_feature(of->f_tree, 3158b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States SMB_TREE_CATIA)) { 3168b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States flags |= SMB_CATIA; 3178b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States } 3188b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States (void) smb_node_set_delete_on_close(of->f_node, 3198b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States of->f_cr, flags); 3208b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States } 321dc20a302Sas200622 smb_fsop_unshrlock(of->f_cr, of->f_node, of->f_uniqid); 3226537f381Sas200622 smb_node_destroy_lock_by_ofile(of->f_node, of); 323dc20a302Sas200622 324dc20a302Sas200622 if (of->f_node->vp->v_type == VREG) 3258c10a865Sas200622 (void) smb_fsop_close(of->f_node, of->f_mode, 3268c10a865Sas200622 of->f_cr); 327dc20a302Sas200622 328dc20a302Sas200622 /* 329dc20a302Sas200622 * Cancel any notify change requests related 330dc20a302Sas200622 * to this open instance. 331da6c28aaSamw */ 332da6c28aaSamw if (of->f_node->flags & NODE_FLAGS_NOTIFY_CHANGE) 333da6c28aaSamw smb_process_file_notify_change_queue(of); 334da6c28aaSamw } 3351fcced4cSJordan Brown atomic_dec_32(&of->f_tree->t_open_files); 336faa1795aSjb150015 atomic_dec_32(&of->f_tree->t_server->sv_open_files); 337da6c28aaSamw 338da6c28aaSamw mutex_enter(&of->f_mutex); 339da6c28aaSamw ASSERT(of->f_refcnt); 340da6c28aaSamw ASSERT(of->f_state == SMB_OFILE_STATE_CLOSING); 341da6c28aaSamw of->f_state = SMB_OFILE_STATE_CLOSED; 34224d2db37Sjose borrego mutex_exit(&of->f_mutex); 343fc724630SAlan Wright if (of->f_node != NULL) { 3442c2961f8Sjose borrego smb_node_dec_open_ofiles(of->f_node); 345fc724630SAlan Wright if (of->f_oplock_granted) { 3462c2961f8Sjose borrego smb_oplock_release(of->f_node, of); 3472c2961f8Sjose borrego of->f_oplock_granted = B_FALSE; 3482c2961f8Sjose borrego } 349fc724630SAlan Wright } 350c8ec8eeaSjose borrego return; 351da6c28aaSamw } 352da6c28aaSamw case SMB_OFILE_STATE_CLOSED: 353da6c28aaSamw case SMB_OFILE_STATE_CLOSING: 354da6c28aaSamw break; 355da6c28aaSamw 356da6c28aaSamw default: 357da6c28aaSamw ASSERT(0); 358da6c28aaSamw break; 359da6c28aaSamw } 360da6c28aaSamw mutex_exit(&of->f_mutex); 361da6c28aaSamw } 362da6c28aaSamw 363da6c28aaSamw /* 364da6c28aaSamw * smb_ofile_close_all 365da6c28aaSamw * 366da6c28aaSamw * 367da6c28aaSamw */ 368da6c28aaSamw void 369da6c28aaSamw smb_ofile_close_all( 370da6c28aaSamw smb_tree_t *tree) 371da6c28aaSamw { 372da6c28aaSamw smb_ofile_t *of; 373da6c28aaSamw 374da6c28aaSamw ASSERT(tree); 375da6c28aaSamw ASSERT(tree->t_magic == SMB_TREE_MAGIC); 376da6c28aaSamw 377da6c28aaSamw smb_llist_enter(&tree->t_ofile_list, RW_READER); 378da6c28aaSamw of = smb_llist_head(&tree->t_ofile_list); 379da6c28aaSamw while (of) { 380da6c28aaSamw ASSERT(of->f_magic == SMB_OFILE_MAGIC); 381da6c28aaSamw ASSERT(of->f_tree == tree); 382da6c28aaSamw of = smb_ofile_close_and_next(of); 383da6c28aaSamw } 384da6c28aaSamw smb_llist_exit(&tree->t_ofile_list); 385da6c28aaSamw } 386da6c28aaSamw 387da6c28aaSamw /* 388da6c28aaSamw * smb_ofiles_close_by_pid 389da6c28aaSamw * 390da6c28aaSamw * 391da6c28aaSamw */ 392da6c28aaSamw void 393da6c28aaSamw smb_ofile_close_all_by_pid( 394da6c28aaSamw smb_tree_t *tree, 395da6c28aaSamw uint16_t pid) 396da6c28aaSamw { 397da6c28aaSamw smb_ofile_t *of; 398da6c28aaSamw 399da6c28aaSamw ASSERT(tree); 400da6c28aaSamw ASSERT(tree->t_magic == SMB_TREE_MAGIC); 401da6c28aaSamw 402da6c28aaSamw smb_llist_enter(&tree->t_ofile_list, RW_READER); 403da6c28aaSamw of = smb_llist_head(&tree->t_ofile_list); 404da6c28aaSamw while (of) { 405da6c28aaSamw ASSERT(of->f_magic == SMB_OFILE_MAGIC); 406da6c28aaSamw ASSERT(of->f_tree == tree); 407da6c28aaSamw if (of->f_opened_by_pid == pid) { 408da6c28aaSamw of = smb_ofile_close_and_next(of); 409da6c28aaSamw } else { 410da6c28aaSamw of = smb_llist_next(&tree->t_ofile_list, of); 411da6c28aaSamw } 412da6c28aaSamw } 413da6c28aaSamw smb_llist_exit(&tree->t_ofile_list); 414da6c28aaSamw } 415da6c28aaSamw 416da6c28aaSamw /* 4171fcced4cSJordan Brown * If the enumeration request is for ofile data, handle it here. 4181fcced4cSJordan Brown * Otherwise, return. 4191fcced4cSJordan Brown * 4201fcced4cSJordan Brown * This function should be called with a hold on the ofile. 4211fcced4cSJordan Brown */ 4221fcced4cSJordan Brown int 4231fcced4cSJordan Brown smb_ofile_enum(smb_ofile_t *of, smb_svcenum_t *svcenum) 4241fcced4cSJordan Brown { 4251fcced4cSJordan Brown uint8_t *pb; 4261fcced4cSJordan Brown uint_t nbytes; 4271fcced4cSJordan Brown int rc; 4281fcced4cSJordan Brown 4291fcced4cSJordan Brown ASSERT(of); 4301fcced4cSJordan Brown ASSERT(of->f_magic == SMB_OFILE_MAGIC); 4311fcced4cSJordan Brown ASSERT(of->f_refcnt); 4321fcced4cSJordan Brown 4331fcced4cSJordan Brown if (svcenum->se_type != SMB_SVCENUM_TYPE_FILE) 4341fcced4cSJordan Brown return (0); 4351fcced4cSJordan Brown 4361fcced4cSJordan Brown if (svcenum->se_nskip > 0) { 4371fcced4cSJordan Brown svcenum->se_nskip--; 4381fcced4cSJordan Brown return (0); 4391fcced4cSJordan Brown } 4401fcced4cSJordan Brown 4411fcced4cSJordan Brown if (svcenum->se_nitems >= svcenum->se_nlimit) { 4421fcced4cSJordan Brown svcenum->se_nitems = svcenum->se_nlimit; 4431fcced4cSJordan Brown return (0); 4441fcced4cSJordan Brown } 4451fcced4cSJordan Brown 4461fcced4cSJordan Brown pb = &svcenum->se_buf[svcenum->se_bused]; 4471fcced4cSJordan Brown 4481fcced4cSJordan Brown rc = smb_ofile_netinfo_encode(of, pb, svcenum->se_bavail, 4491fcced4cSJordan Brown &nbytes); 4501fcced4cSJordan Brown if (rc == 0) { 4511fcced4cSJordan Brown svcenum->se_bavail -= nbytes; 4521fcced4cSJordan Brown svcenum->se_bused += nbytes; 4531fcced4cSJordan Brown svcenum->se_nitems++; 4541fcced4cSJordan Brown } 4551fcced4cSJordan Brown 4561fcced4cSJordan Brown return (rc); 4571fcced4cSJordan Brown } 4581fcced4cSJordan Brown 4591fcced4cSJordan Brown /* 4601fcced4cSJordan Brown * Take a reference on an open file. 4611fcced4cSJordan Brown */ 4621fcced4cSJordan Brown boolean_t 4631fcced4cSJordan Brown smb_ofile_hold(smb_ofile_t *of) 4641fcced4cSJordan Brown { 4651fcced4cSJordan Brown ASSERT(of); 4661fcced4cSJordan Brown ASSERT(of->f_magic == SMB_OFILE_MAGIC); 4671fcced4cSJordan Brown 4681fcced4cSJordan Brown mutex_enter(&of->f_mutex); 4691fcced4cSJordan Brown 4701fcced4cSJordan Brown if (smb_ofile_is_open_locked(of)) { 4711fcced4cSJordan Brown of->f_refcnt++; 4721fcced4cSJordan Brown mutex_exit(&of->f_mutex); 4731fcced4cSJordan Brown return (B_TRUE); 4741fcced4cSJordan Brown } 4751fcced4cSJordan Brown 4761fcced4cSJordan Brown mutex_exit(&of->f_mutex); 4771fcced4cSJordan Brown return (B_FALSE); 4781fcced4cSJordan Brown } 4791fcced4cSJordan Brown 4801fcced4cSJordan Brown /* 481da6c28aaSamw * smb_ofile_release 482da6c28aaSamw * 483da6c28aaSamw */ 484da6c28aaSamw void 48524d2db37Sjose borrego smb_ofile_release(smb_ofile_t *of) 486da6c28aaSamw { 48724d2db37Sjose borrego boolean_t rb; 48824d2db37Sjose borrego 489da6c28aaSamw ASSERT(of); 490da6c28aaSamw ASSERT(of->f_magic == SMB_OFILE_MAGIC); 491da6c28aaSamw 492da6c28aaSamw mutex_enter(&of->f_mutex); 49324d2db37Sjose borrego if (of->f_oplock_exit) { 49424d2db37Sjose borrego mutex_exit(&of->f_mutex); 49524d2db37Sjose borrego rb = smb_oplock_broadcast(of->f_node); 49624d2db37Sjose borrego mutex_enter(&of->f_mutex); 49724d2db37Sjose borrego if (rb) 4982c2961f8Sjose borrego of->f_oplock_exit = B_FALSE; 49924d2db37Sjose borrego } 500da6c28aaSamw ASSERT(of->f_refcnt); 501da6c28aaSamw of->f_refcnt--; 502da6c28aaSamw switch (of->f_state) { 503da6c28aaSamw case SMB_OFILE_STATE_OPEN: 504da6c28aaSamw case SMB_OFILE_STATE_CLOSING: 505da6c28aaSamw break; 506da6c28aaSamw 507da6c28aaSamw case SMB_OFILE_STATE_CLOSED: 508da6c28aaSamw if (of->f_refcnt == 0) { 509da6c28aaSamw mutex_exit(&of->f_mutex); 510da6c28aaSamw smb_ofile_delete(of); 511da6c28aaSamw return; 512da6c28aaSamw } 513da6c28aaSamw break; 514da6c28aaSamw 515da6c28aaSamw default: 516da6c28aaSamw ASSERT(0); 517da6c28aaSamw break; 518da6c28aaSamw } 519da6c28aaSamw mutex_exit(&of->f_mutex); 520da6c28aaSamw } 521da6c28aaSamw 522da6c28aaSamw /* 523da6c28aaSamw * smb_ofile_lookup_by_fid 524da6c28aaSamw * 525da6c28aaSamw * Find the open file whose fid matches the one specified in the request. 526da6c28aaSamw * If we can't find the fid or the shares (trees) don't match, we have a 527da6c28aaSamw * bad fid. 528da6c28aaSamw */ 529da6c28aaSamw smb_ofile_t * 530da6c28aaSamw smb_ofile_lookup_by_fid( 531da6c28aaSamw smb_tree_t *tree, 532da6c28aaSamw uint16_t fid) 533da6c28aaSamw { 534da6c28aaSamw smb_llist_t *of_list; 535da6c28aaSamw smb_ofile_t *of; 536da6c28aaSamw 537da6c28aaSamw ASSERT(tree->t_magic == SMB_TREE_MAGIC); 538da6c28aaSamw 539da6c28aaSamw of_list = &tree->t_ofile_list; 540da6c28aaSamw 541da6c28aaSamw smb_llist_enter(of_list, RW_READER); 542da6c28aaSamw of = smb_llist_head(of_list); 543da6c28aaSamw while (of) { 544da6c28aaSamw ASSERT(of->f_magic == SMB_OFILE_MAGIC); 545da6c28aaSamw ASSERT(of->f_tree == tree); 546da6c28aaSamw if (of->f_fid == fid) { 547da6c28aaSamw mutex_enter(&of->f_mutex); 548da6c28aaSamw if (of->f_state != SMB_OFILE_STATE_OPEN) { 549da6c28aaSamw mutex_exit(&of->f_mutex); 550da6c28aaSamw smb_llist_exit(of_list); 551da6c28aaSamw return (NULL); 552da6c28aaSamw } 553da6c28aaSamw of->f_refcnt++; 554da6c28aaSamw mutex_exit(&of->f_mutex); 555da6c28aaSamw break; 556da6c28aaSamw } 557da6c28aaSamw of = smb_llist_next(of_list, of); 558da6c28aaSamw } 559da6c28aaSamw smb_llist_exit(of_list); 560da6c28aaSamw return (of); 561da6c28aaSamw } 562da6c28aaSamw 563da6c28aaSamw /* 5641fcced4cSJordan Brown * smb_ofile_lookup_by_uniqid 5651fcced4cSJordan Brown * 5661fcced4cSJordan Brown * Find the open file whose uniqid matches the one specified in the request. 5671fcced4cSJordan Brown */ 5681fcced4cSJordan Brown smb_ofile_t * 5691fcced4cSJordan Brown smb_ofile_lookup_by_uniqid(smb_tree_t *tree, uint32_t uniqid) 5701fcced4cSJordan Brown { 5711fcced4cSJordan Brown smb_llist_t *of_list; 5721fcced4cSJordan Brown smb_ofile_t *of; 5731fcced4cSJordan Brown 5741fcced4cSJordan Brown ASSERT(tree->t_magic == SMB_TREE_MAGIC); 5751fcced4cSJordan Brown 5761fcced4cSJordan Brown of_list = &tree->t_ofile_list; 5771fcced4cSJordan Brown smb_llist_enter(of_list, RW_READER); 5781fcced4cSJordan Brown of = smb_llist_head(of_list); 5791fcced4cSJordan Brown 5801fcced4cSJordan Brown while (of) { 5811fcced4cSJordan Brown ASSERT(of->f_magic == SMB_OFILE_MAGIC); 5821fcced4cSJordan Brown ASSERT(of->f_tree == tree); 5831fcced4cSJordan Brown 5841fcced4cSJordan Brown if (of->f_uniqid == uniqid) { 5851fcced4cSJordan Brown if (smb_ofile_hold(of)) { 5861fcced4cSJordan Brown smb_llist_exit(of_list); 5871fcced4cSJordan Brown return (of); 5881fcced4cSJordan Brown } 5891fcced4cSJordan Brown } 5901fcced4cSJordan Brown 5911fcced4cSJordan Brown of = smb_llist_next(of_list, of); 5921fcced4cSJordan Brown } 5931fcced4cSJordan Brown 5941fcced4cSJordan Brown smb_llist_exit(of_list); 5951fcced4cSJordan Brown return (NULL); 5961fcced4cSJordan Brown } 5971fcced4cSJordan Brown 5981fcced4cSJordan Brown /* 5991fcced4cSJordan Brown * Disallow NetFileClose on certain ofiles to avoid side-effects. 6001fcced4cSJordan Brown * Closing a tree root is not allowed: use NetSessionDel or NetShareDel. 6011fcced4cSJordan Brown * Closing SRVSVC connections is not allowed because this NetFileClose 6021fcced4cSJordan Brown * request may depend on this ofile. 6031fcced4cSJordan Brown */ 6041fcced4cSJordan Brown boolean_t 6051fcced4cSJordan Brown smb_ofile_disallow_fclose(smb_ofile_t *of) 6061fcced4cSJordan Brown { 6071fcced4cSJordan Brown ASSERT(of); 6081fcced4cSJordan Brown ASSERT(of->f_magic == SMB_OFILE_MAGIC); 6091fcced4cSJordan Brown ASSERT(of->f_refcnt); 6101fcced4cSJordan Brown 6111fcced4cSJordan Brown switch (of->f_ftype) { 6121fcced4cSJordan Brown case SMB_FTYPE_DISK: 6131fcced4cSJordan Brown ASSERT(of->f_tree); 6141fcced4cSJordan Brown return (of->f_node == of->f_tree->t_snode); 6151fcced4cSJordan Brown 6161fcced4cSJordan Brown case SMB_FTYPE_MESG_PIPE: 6171fcced4cSJordan Brown ASSERT(of->f_pipe); 618bbf6f00cSJordan Brown if (smb_strcasecmp(of->f_pipe->p_name, "SRVSVC", 0) == 0) 6191fcced4cSJordan Brown return (B_TRUE); 6201fcced4cSJordan Brown break; 6211fcced4cSJordan Brown default: 6221fcced4cSJordan Brown break; 6231fcced4cSJordan Brown } 6241fcced4cSJordan Brown 6251fcced4cSJordan Brown return (B_FALSE); 6261fcced4cSJordan Brown } 6271fcced4cSJordan Brown 6281fcced4cSJordan Brown /* 629da6c28aaSamw * smb_ofile_set_flags 630da6c28aaSamw * 631da6c28aaSamw * Return value: 632da6c28aaSamw * 633da6c28aaSamw * Current flags value 634da6c28aaSamw * 635da6c28aaSamw */ 636da6c28aaSamw void 637da6c28aaSamw smb_ofile_set_flags( 638da6c28aaSamw smb_ofile_t *of, 639da6c28aaSamw uint32_t flags) 640da6c28aaSamw { 641da6c28aaSamw ASSERT(of); 642da6c28aaSamw ASSERT(of->f_magic == SMB_OFILE_MAGIC); 643da6c28aaSamw ASSERT(of->f_refcnt); 644da6c28aaSamw 645da6c28aaSamw mutex_enter(&of->f_mutex); 646da6c28aaSamw of->f_flags |= flags; 647da6c28aaSamw mutex_exit(&of->f_mutex); 648da6c28aaSamw } 649*f96bd5c8SAlan Wright 650da6c28aaSamw /* 651da6c28aaSamw * smb_ofile_seek 652da6c28aaSamw * 653da6c28aaSamw * Return value: 654da6c28aaSamw * 655da6c28aaSamw * 0 Success 656da6c28aaSamw * EINVAL Unknown mode 657da6c28aaSamw * EOVERFLOW offset too big 658da6c28aaSamw * 659da6c28aaSamw */ 660da6c28aaSamw int 661da6c28aaSamw smb_ofile_seek( 662da6c28aaSamw smb_ofile_t *of, 663da6c28aaSamw ushort_t mode, 664da6c28aaSamw int32_t off, 665da6c28aaSamw uint32_t *retoff) 666da6c28aaSamw { 66755bf511dSas200622 u_offset_t newoff = 0; 668da6c28aaSamw int rc = 0; 669037cac00Sjoyce mcintosh smb_attr_t attr; 670da6c28aaSamw 671da6c28aaSamw ASSERT(of); 672da6c28aaSamw ASSERT(of->f_magic == SMB_OFILE_MAGIC); 673da6c28aaSamw ASSERT(of->f_refcnt); 674da6c28aaSamw 675da6c28aaSamw mutex_enter(&of->f_mutex); 676da6c28aaSamw switch (mode) { 677da6c28aaSamw case SMB_SEEK_SET: 678da6c28aaSamw if (off < 0) 679da6c28aaSamw newoff = 0; 680da6c28aaSamw else 68155bf511dSas200622 newoff = (u_offset_t)off; 682da6c28aaSamw break; 683da6c28aaSamw 684da6c28aaSamw case SMB_SEEK_CUR: 685da6c28aaSamw if (off < 0 && (-off) > of->f_seek_pos) 686da6c28aaSamw newoff = 0; 687da6c28aaSamw else 68855bf511dSas200622 newoff = of->f_seek_pos + (u_offset_t)off; 689da6c28aaSamw break; 690da6c28aaSamw 691da6c28aaSamw case SMB_SEEK_END: 692037cac00Sjoyce mcintosh bzero(&attr, sizeof (smb_attr_t)); 693037cac00Sjoyce mcintosh attr.sa_mask |= SMB_AT_SIZE; 694037cac00Sjoyce mcintosh rc = smb_fsop_getattr(NULL, kcred, of->f_node, &attr); 695037cac00Sjoyce mcintosh if (rc != 0) { 696037cac00Sjoyce mcintosh mutex_exit(&of->f_mutex); 697037cac00Sjoyce mcintosh return (rc); 698037cac00Sjoyce mcintosh } 699037cac00Sjoyce mcintosh if (off < 0 && (-off) > attr.sa_vattr.va_size) 700da6c28aaSamw newoff = 0; 701da6c28aaSamw else 702037cac00Sjoyce mcintosh newoff = attr.sa_vattr.va_size + (u_offset_t)off; 703da6c28aaSamw break; 704da6c28aaSamw 705da6c28aaSamw default: 706da6c28aaSamw mutex_exit(&of->f_mutex); 707da6c28aaSamw return (EINVAL); 708da6c28aaSamw } 709da6c28aaSamw 71055bf511dSas200622 /* 71155bf511dSas200622 * See comments at the beginning of smb_seek.c. 71255bf511dSas200622 * If the offset is greater than UINT_MAX, we will return an error. 71355bf511dSas200622 */ 71455bf511dSas200622 71555bf511dSas200622 if (newoff > UINT_MAX) { 716da6c28aaSamw rc = EOVERFLOW; 717da6c28aaSamw } else { 718da6c28aaSamw of->f_seek_pos = newoff; 719da6c28aaSamw *retoff = (uint32_t)newoff; 720da6c28aaSamw } 721da6c28aaSamw mutex_exit(&of->f_mutex); 722da6c28aaSamw return (rc); 723da6c28aaSamw } 724da6c28aaSamw 725da6c28aaSamw /* 726da6c28aaSamw * smb_ofile_is_open 727da6c28aaSamw */ 728da6c28aaSamw boolean_t 7292c2961f8Sjose borrego smb_ofile_is_open(smb_ofile_t *of) 730da6c28aaSamw { 7311fcced4cSJordan Brown boolean_t rc; 732da6c28aaSamw 7332c2961f8Sjose borrego SMB_OFILE_VALID(of); 734da6c28aaSamw 735da6c28aaSamw mutex_enter(&of->f_mutex); 7361fcced4cSJordan Brown rc = smb_ofile_is_open_locked(of); 737da6c28aaSamw mutex_exit(&of->f_mutex); 738da6c28aaSamw return (rc); 739da6c28aaSamw } 740da6c28aaSamw 7412c2961f8Sjose borrego void 7422c2961f8Sjose borrego smb_ofile_set_oplock_granted(smb_ofile_t *of) 7432c2961f8Sjose borrego { 7442c2961f8Sjose borrego SMB_OFILE_VALID(of); 7452c2961f8Sjose borrego mutex_enter(&of->f_mutex); 7462c2961f8Sjose borrego ASSERT(!of->f_oplock_granted); 7472c2961f8Sjose borrego of->f_oplock_granted = B_TRUE; 7482c2961f8Sjose borrego of->f_oplock_exit = B_TRUE; 7492c2961f8Sjose borrego mutex_exit(&of->f_mutex); 7502c2961f8Sjose borrego } 7512c2961f8Sjose borrego 752037cac00Sjoyce mcintosh /* 753037cac00Sjoyce mcintosh * smb_ofile_pending_write_time 754037cac00Sjoyce mcintosh * 755037cac00Sjoyce mcintosh * Flag write times as pending - to be set on close, setattr 756037cac00Sjoyce mcintosh * or delayed write timer. 757037cac00Sjoyce mcintosh */ 758037cac00Sjoyce mcintosh void 759037cac00Sjoyce mcintosh smb_ofile_set_write_time_pending(smb_ofile_t *of) 760037cac00Sjoyce mcintosh { 761037cac00Sjoyce mcintosh SMB_OFILE_VALID(of); 762037cac00Sjoyce mcintosh mutex_enter(&of->f_mutex); 763037cac00Sjoyce mcintosh of->f_flags |= SMB_OFLAGS_TIMESTAMPS_PENDING; 764037cac00Sjoyce mcintosh mutex_exit(&of->f_mutex); 765037cac00Sjoyce mcintosh } 766037cac00Sjoyce mcintosh 767e3f2c991SKeyur Desai /* 768e3f2c991SKeyur Desai * smb_ofile_write_time_pending 769e3f2c991SKeyur Desai * 770e3f2c991SKeyur Desai * Get and reset the write times pending flag. 771e3f2c991SKeyur Desai */ 772037cac00Sjoyce mcintosh boolean_t 773037cac00Sjoyce mcintosh smb_ofile_write_time_pending(smb_ofile_t *of) 774037cac00Sjoyce mcintosh { 775037cac00Sjoyce mcintosh boolean_t rc = B_FALSE; 776037cac00Sjoyce mcintosh 777037cac00Sjoyce mcintosh SMB_OFILE_VALID(of); 778037cac00Sjoyce mcintosh mutex_enter(&of->f_mutex); 779e3f2c991SKeyur Desai if (of->f_flags & SMB_OFLAGS_TIMESTAMPS_PENDING) { 780037cac00Sjoyce mcintosh rc = B_TRUE; 781e3f2c991SKeyur Desai of->f_flags &= ~SMB_OFLAGS_TIMESTAMPS_PENDING; 782e3f2c991SKeyur Desai } 783037cac00Sjoyce mcintosh mutex_exit(&of->f_mutex); 784037cac00Sjoyce mcintosh 785037cac00Sjoyce mcintosh return (rc); 786037cac00Sjoyce mcintosh } 787037cac00Sjoyce mcintosh 788037cac00Sjoyce mcintosh /* 789037cac00Sjoyce mcintosh * smb_ofile_set_explicit_time_flag 790037cac00Sjoyce mcintosh * 791037cac00Sjoyce mcintosh * Note the timestamps specified in "what", as having been 792e3f2c991SKeyur Desai * explicity set for the ofile. 793037cac00Sjoyce mcintosh */ 794037cac00Sjoyce mcintosh void 795037cac00Sjoyce mcintosh smb_ofile_set_explicit_times(smb_ofile_t *of, uint32_t what) 796037cac00Sjoyce mcintosh { 797037cac00Sjoyce mcintosh SMB_OFILE_VALID(of); 798037cac00Sjoyce mcintosh mutex_enter(&of->f_mutex); 799037cac00Sjoyce mcintosh of->f_explicit_times |= (what & SMB_AT_TIMES); 800037cac00Sjoyce mcintosh mutex_exit(&of->f_mutex); 801037cac00Sjoyce mcintosh } 802037cac00Sjoyce mcintosh 803037cac00Sjoyce mcintosh uint32_t 804037cac00Sjoyce mcintosh smb_ofile_explicit_times(smb_ofile_t *of) 805037cac00Sjoyce mcintosh { 806037cac00Sjoyce mcintosh uint32_t rc; 807037cac00Sjoyce mcintosh 808037cac00Sjoyce mcintosh SMB_OFILE_VALID(of); 809037cac00Sjoyce mcintosh mutex_enter(&of->f_mutex); 810037cac00Sjoyce mcintosh rc = of->f_explicit_times; 811037cac00Sjoyce mcintosh mutex_exit(&of->f_mutex); 812037cac00Sjoyce mcintosh 813037cac00Sjoyce mcintosh return (rc); 814037cac00Sjoyce mcintosh } 815037cac00Sjoyce mcintosh 816da6c28aaSamw /* *************************** Static Functions ***************************** */ 817da6c28aaSamw 818da6c28aaSamw /* 8191fcced4cSJordan Brown * Determine whether or not an ofile is open. 8201fcced4cSJordan Brown * This function must be called with the mutex held. 8211fcced4cSJordan Brown */ 8221fcced4cSJordan Brown static boolean_t 8231fcced4cSJordan Brown smb_ofile_is_open_locked(smb_ofile_t *of) 8241fcced4cSJordan Brown { 8251fcced4cSJordan Brown switch (of->f_state) { 8261fcced4cSJordan Brown case SMB_OFILE_STATE_OPEN: 8271fcced4cSJordan Brown return (B_TRUE); 8281fcced4cSJordan Brown 8291fcced4cSJordan Brown case SMB_OFILE_STATE_CLOSING: 8301fcced4cSJordan Brown case SMB_OFILE_STATE_CLOSED: 8311fcced4cSJordan Brown return (B_FALSE); 8321fcced4cSJordan Brown 8331fcced4cSJordan Brown default: 8341fcced4cSJordan Brown ASSERT(0); 8351fcced4cSJordan Brown return (B_FALSE); 8361fcced4cSJordan Brown } 8371fcced4cSJordan Brown } 8381fcced4cSJordan Brown 8391fcced4cSJordan Brown /* 840037cac00Sjoyce mcintosh * smb_ofile_set_close_attrs 841037cac00Sjoyce mcintosh * 842037cac00Sjoyce mcintosh * Updates timestamps, size and readonly bit. 843037cac00Sjoyce mcintosh * The last_wtime is specified in the request received 844037cac00Sjoyce mcintosh * from the client. If it is neither 0 nor -1, this time 845037cac00Sjoyce mcintosh * should be used as the file's mtime. It must first be 846037cac00Sjoyce mcintosh * converted from the server's localtime (as received in 847037cac00Sjoyce mcintosh * the client's request) to GMT. 848037cac00Sjoyce mcintosh * 849037cac00Sjoyce mcintosh * Call smb_node_setattr even if no attributes are being 850037cac00Sjoyce mcintosh * explicitly set, to set any pending attributes. 851037cac00Sjoyce mcintosh */ 852037cac00Sjoyce mcintosh static void 853037cac00Sjoyce mcintosh smb_ofile_set_close_attrs(smb_ofile_t *of, uint32_t last_wtime) 854037cac00Sjoyce mcintosh { 855037cac00Sjoyce mcintosh smb_node_t *node = of->f_node; 856037cac00Sjoyce mcintosh smb_attr_t attr; 857037cac00Sjoyce mcintosh 858037cac00Sjoyce mcintosh bzero(&attr, sizeof (smb_attr_t)); 859037cac00Sjoyce mcintosh 860037cac00Sjoyce mcintosh /* For files created readonly, propagate readonly bit */ 861037cac00Sjoyce mcintosh if (node->readonly_creator == of) { 862037cac00Sjoyce mcintosh attr.sa_mask |= SMB_AT_DOSATTR; 863037cac00Sjoyce mcintosh if (smb_fsop_getattr(NULL, kcred, node, &attr) && 864037cac00Sjoyce mcintosh (attr.sa_dosattr & FILE_ATTRIBUTE_READONLY)) { 865037cac00Sjoyce mcintosh attr.sa_mask = 0; 866037cac00Sjoyce mcintosh } else { 867037cac00Sjoyce mcintosh attr.sa_dosattr |= FILE_ATTRIBUTE_READONLY; 868037cac00Sjoyce mcintosh } 869037cac00Sjoyce mcintosh 870037cac00Sjoyce mcintosh node->readonly_creator = NULL; 871037cac00Sjoyce mcintosh } 872037cac00Sjoyce mcintosh 873037cac00Sjoyce mcintosh /* apply last_wtime if specified */ 874037cac00Sjoyce mcintosh if (last_wtime != 0 && last_wtime != 0xFFFFFFFF) { 875037cac00Sjoyce mcintosh attr.sa_vattr.va_mtime.tv_sec = 876037cac00Sjoyce mcintosh last_wtime + of->f_server->si_gmtoff; 877037cac00Sjoyce mcintosh attr.sa_mask |= SMB_AT_MTIME; 878037cac00Sjoyce mcintosh } 879037cac00Sjoyce mcintosh 880037cac00Sjoyce mcintosh (void) smb_node_setattr(NULL, node, of->f_cr, of, &attr); 881037cac00Sjoyce mcintosh } 882037cac00Sjoyce mcintosh 883037cac00Sjoyce mcintosh /* 884da6c28aaSamw * smb_ofile_close_and_next 885da6c28aaSamw * 886da6c28aaSamw * This function closes the file passed in (if appropriate) and returns the 887da6c28aaSamw * next open file in the list of open files of the tree of the open file passed 888da6c28aaSamw * in. It requires that the list of open files of the tree be entered in 889da6c28aaSamw * RW_READER mode before being called. 890da6c28aaSamw */ 891da6c28aaSamw static smb_ofile_t * 892037cac00Sjoyce mcintosh smb_ofile_close_and_next(smb_ofile_t *of) 893da6c28aaSamw { 894da6c28aaSamw smb_ofile_t *next_of; 895da6c28aaSamw smb_tree_t *tree; 896da6c28aaSamw 897da6c28aaSamw ASSERT(of); 898da6c28aaSamw ASSERT(of->f_magic == SMB_OFILE_MAGIC); 899da6c28aaSamw 900da6c28aaSamw mutex_enter(&of->f_mutex); 901da6c28aaSamw switch (of->f_state) { 902da6c28aaSamw case SMB_OFILE_STATE_OPEN: 903da6c28aaSamw /* The file is still open. */ 904da6c28aaSamw of->f_refcnt++; 905da6c28aaSamw ASSERT(of->f_refcnt); 906da6c28aaSamw tree = of->f_tree; 907da6c28aaSamw mutex_exit(&of->f_mutex); 908da6c28aaSamw smb_llist_exit(&of->f_tree->t_ofile_list); 909c8ec8eeaSjose borrego smb_ofile_close(of, 0); 910da6c28aaSamw smb_ofile_release(of); 911da6c28aaSamw smb_llist_enter(&tree->t_ofile_list, RW_READER); 912da6c28aaSamw next_of = smb_llist_head(&tree->t_ofile_list); 913da6c28aaSamw break; 914da6c28aaSamw case SMB_OFILE_STATE_CLOSING: 915da6c28aaSamw case SMB_OFILE_STATE_CLOSED: 916da6c28aaSamw /* 917da6c28aaSamw * The ofile exists but is closed or 918da6c28aaSamw * in the process being closed. 919da6c28aaSamw */ 920da6c28aaSamw mutex_exit(&of->f_mutex); 921da6c28aaSamw next_of = smb_llist_next(&of->f_tree->t_ofile_list, of); 922da6c28aaSamw break; 923da6c28aaSamw default: 924da6c28aaSamw ASSERT(0); 925da6c28aaSamw mutex_exit(&of->f_mutex); 926da6c28aaSamw next_of = smb_llist_next(&of->f_tree->t_ofile_list, of); 927da6c28aaSamw break; 928da6c28aaSamw } 929da6c28aaSamw return (next_of); 930da6c28aaSamw } 931da6c28aaSamw 932da6c28aaSamw /* 933da6c28aaSamw * smb_ofile_delete 934da6c28aaSamw * 935da6c28aaSamw * 936da6c28aaSamw */ 937da6c28aaSamw static void 938037cac00Sjoyce mcintosh smb_ofile_delete(smb_ofile_t *of) 939da6c28aaSamw { 940da6c28aaSamw ASSERT(of); 941da6c28aaSamw ASSERT(of->f_magic == SMB_OFILE_MAGIC); 942da6c28aaSamw ASSERT(of->f_refcnt == 0); 943da6c28aaSamw ASSERT(of->f_state == SMB_OFILE_STATE_CLOSED); 944da6c28aaSamw 945da6c28aaSamw /* 946da6c28aaSamw * Let's remove the ofile from the list of ofiles of the tree. This has 947da6c28aaSamw * to be done before any resources associated with the ofile are 948da6c28aaSamw * released. 949da6c28aaSamw */ 950da6c28aaSamw smb_llist_enter(&of->f_tree->t_ofile_list, RW_WRITER); 951da6c28aaSamw smb_llist_remove(&of->f_tree->t_ofile_list, of); 952da6c28aaSamw smb_llist_exit(&of->f_tree->t_ofile_list); 953da6c28aaSamw atomic_dec_32(&of->f_session->s_file_cnt); 954da6c28aaSamw 955da6c28aaSamw if (of->f_ftype == SMB_FTYPE_MESG_PIPE) { 9563db3f65cSamw kmem_free(of->f_pipe, sizeof (smb_opipe_t)); 9573db3f65cSamw of->f_pipe = NULL; 958da6c28aaSamw } else { 959da6c28aaSamw ASSERT(of->f_ftype == SMB_FTYPE_DISK); 960da6c28aaSamw ASSERT(of->f_node != NULL); 9612c2961f8Sjose borrego smb_node_rem_ofile(of->f_node, of); 962da6c28aaSamw smb_node_release(of->f_node); 963da6c28aaSamw } 964da6c28aaSamw 965da6c28aaSamw of->f_magic = (uint32_t)~SMB_OFILE_MAGIC; 966da6c28aaSamw mutex_destroy(&of->f_mutex); 967da6c28aaSamw crfree(of->f_cr); 968da6c28aaSamw smb_idpool_free(&of->f_tree->t_fid_pool, of->f_fid); 969faa1795aSjb150015 kmem_cache_free(of->f_tree->t_server->si_cache_ofile, of); 970da6c28aaSamw } 971da6c28aaSamw 972da6c28aaSamw /* 973da6c28aaSamw * smb_ofile_access 974da6c28aaSamw * 975da6c28aaSamw * This function will check to see if the access requested is granted. 976da6c28aaSamw * Returns NT status codes. 977da6c28aaSamw */ 978da6c28aaSamw uint32_t 979da6c28aaSamw smb_ofile_access(smb_ofile_t *of, cred_t *cr, uint32_t access) 980da6c28aaSamw { 981da6c28aaSamw 982da6c28aaSamw if ((of == NULL) || (cr == kcred)) 983da6c28aaSamw return (NT_STATUS_SUCCESS); 984da6c28aaSamw 985da6c28aaSamw /* 986da6c28aaSamw * If the request is for something 987da6c28aaSamw * I don't grant it is an error 988da6c28aaSamw */ 989da6c28aaSamw if (~(of->f_granted_access) & access) { 990da6c28aaSamw if (!(of->f_granted_access & ACCESS_SYSTEM_SECURITY) && 991da6c28aaSamw (access & ACCESS_SYSTEM_SECURITY)) { 992da6c28aaSamw return (NT_STATUS_PRIVILEGE_NOT_HELD); 993da6c28aaSamw } 994da6c28aaSamw return (NT_STATUS_ACCESS_DENIED); 995da6c28aaSamw } 996da6c28aaSamw 997da6c28aaSamw return (NT_STATUS_SUCCESS); 998da6c28aaSamw } 9993ad684d6Sjb150015 10003ad684d6Sjb150015 10013ad684d6Sjb150015 /* 10023ad684d6Sjb150015 * smb_ofile_open_check 10033ad684d6Sjb150015 * 10043ad684d6Sjb150015 * check file sharing rules for current open request 10053ad684d6Sjb150015 * against existing open instances of the same file 10063ad684d6Sjb150015 * 10073ad684d6Sjb150015 * Returns NT_STATUS_SHARING_VIOLATION if there is any 10083ad684d6Sjb150015 * sharing conflict, otherwise returns NT_STATUS_SUCCESS. 10093ad684d6Sjb150015 */ 10103ad684d6Sjb150015 uint32_t 10113ad684d6Sjb150015 smb_ofile_open_check( 10123ad684d6Sjb150015 smb_ofile_t *of, 10133ad684d6Sjb150015 cred_t *cr, 10143ad684d6Sjb150015 uint32_t desired_access, 10153ad684d6Sjb150015 uint32_t share_access) 10163ad684d6Sjb150015 { 10173ad684d6Sjb150015 smb_node_t *node; 10183ad684d6Sjb150015 10193ad684d6Sjb150015 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 10203ad684d6Sjb150015 10213ad684d6Sjb150015 node = of->f_node; 10223ad684d6Sjb150015 10233ad684d6Sjb150015 mutex_enter(&of->f_mutex); 10243ad684d6Sjb150015 10253ad684d6Sjb150015 if (of->f_state != SMB_OFILE_STATE_OPEN) { 10263ad684d6Sjb150015 mutex_exit(&of->f_mutex); 10273ad684d6Sjb150015 return (NT_STATUS_INVALID_HANDLE); 10283ad684d6Sjb150015 } 10293ad684d6Sjb150015 10303ad684d6Sjb150015 /* 10313ad684d6Sjb150015 * It appears that share modes are not relevant to 10323ad684d6Sjb150015 * directories, but this check will remain as it is not 10333ad684d6Sjb150015 * clear whether it was originally put here for a reason. 10343ad684d6Sjb150015 */ 1035037cac00Sjoyce mcintosh if (smb_node_is_dir(node)) { 10363ad684d6Sjb150015 if (SMB_DENY_RW(of->f_share_access) && 10373ad684d6Sjb150015 (node->n_orig_uid != crgetuid(cr))) { 10383ad684d6Sjb150015 mutex_exit(&of->f_mutex); 10393ad684d6Sjb150015 return (NT_STATUS_SHARING_VIOLATION); 10403ad684d6Sjb150015 } 10413ad684d6Sjb150015 10423ad684d6Sjb150015 mutex_exit(&of->f_mutex); 10433ad684d6Sjb150015 return (NT_STATUS_SUCCESS); 10443ad684d6Sjb150015 } 10453ad684d6Sjb150015 10463ad684d6Sjb150015 /* if it's just meta data */ 10473ad684d6Sjb150015 if ((of->f_granted_access & FILE_DATA_ALL) == 0) { 10483ad684d6Sjb150015 mutex_exit(&of->f_mutex); 10493ad684d6Sjb150015 return (NT_STATUS_SUCCESS); 10503ad684d6Sjb150015 } 10513ad684d6Sjb150015 10523ad684d6Sjb150015 /* 10533ad684d6Sjb150015 * Check requested share access against the 10543ad684d6Sjb150015 * open granted (desired) access 10553ad684d6Sjb150015 */ 10563ad684d6Sjb150015 if (SMB_DENY_DELETE(share_access) && (of->f_granted_access & DELETE)) { 10573ad684d6Sjb150015 mutex_exit(&of->f_mutex); 10583ad684d6Sjb150015 return (NT_STATUS_SHARING_VIOLATION); 10593ad684d6Sjb150015 } 10603ad684d6Sjb150015 10613ad684d6Sjb150015 if (SMB_DENY_READ(share_access) && 10623ad684d6Sjb150015 (of->f_granted_access & (FILE_READ_DATA | FILE_EXECUTE))) { 10633ad684d6Sjb150015 mutex_exit(&of->f_mutex); 10643ad684d6Sjb150015 return (NT_STATUS_SHARING_VIOLATION); 10653ad684d6Sjb150015 } 10663ad684d6Sjb150015 10673ad684d6Sjb150015 if (SMB_DENY_WRITE(share_access) && 10683ad684d6Sjb150015 (of->f_granted_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) { 10693ad684d6Sjb150015 mutex_exit(&of->f_mutex); 10703ad684d6Sjb150015 return (NT_STATUS_SHARING_VIOLATION); 10713ad684d6Sjb150015 } 10723ad684d6Sjb150015 10733ad684d6Sjb150015 /* check requested desired access against the open share access */ 10743ad684d6Sjb150015 if (SMB_DENY_DELETE(of->f_share_access) && (desired_access & DELETE)) { 10753ad684d6Sjb150015 mutex_exit(&of->f_mutex); 10763ad684d6Sjb150015 return (NT_STATUS_SHARING_VIOLATION); 10773ad684d6Sjb150015 } 10783ad684d6Sjb150015 10793ad684d6Sjb150015 if (SMB_DENY_READ(of->f_share_access) && 10803ad684d6Sjb150015 (desired_access & (FILE_READ_DATA | FILE_EXECUTE))) { 10813ad684d6Sjb150015 mutex_exit(&of->f_mutex); 10823ad684d6Sjb150015 return (NT_STATUS_SHARING_VIOLATION); 10833ad684d6Sjb150015 } 10843ad684d6Sjb150015 10853ad684d6Sjb150015 if (SMB_DENY_WRITE(of->f_share_access) && 10863ad684d6Sjb150015 (desired_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) { 10873ad684d6Sjb150015 mutex_exit(&of->f_mutex); 10883ad684d6Sjb150015 return (NT_STATUS_SHARING_VIOLATION); 10893ad684d6Sjb150015 } 10903ad684d6Sjb150015 10913ad684d6Sjb150015 mutex_exit(&of->f_mutex); 10923ad684d6Sjb150015 return (NT_STATUS_SUCCESS); 10933ad684d6Sjb150015 } 10943ad684d6Sjb150015 10953ad684d6Sjb150015 /* 10963ad684d6Sjb150015 * smb_ofile_rename_check 10973ad684d6Sjb150015 * 10983ad684d6Sjb150015 * An open file can be renamed if 10993ad684d6Sjb150015 * 11003ad684d6Sjb150015 * 1. isn't opened for data writing or deleting 11013ad684d6Sjb150015 * 11023ad684d6Sjb150015 * 2. Opened with "Deny Delete" share mode 11033ad684d6Sjb150015 * But not opened for data reading or executing 11043ad684d6Sjb150015 * (opened for accessing meta data) 11053ad684d6Sjb150015 */ 11063ad684d6Sjb150015 11073ad684d6Sjb150015 uint32_t 11083ad684d6Sjb150015 smb_ofile_rename_check(smb_ofile_t *of) 11093ad684d6Sjb150015 { 11103ad684d6Sjb150015 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 11113ad684d6Sjb150015 11123ad684d6Sjb150015 mutex_enter(&of->f_mutex); 11133ad684d6Sjb150015 11143ad684d6Sjb150015 if (of->f_state != SMB_OFILE_STATE_OPEN) { 11153ad684d6Sjb150015 mutex_exit(&of->f_mutex); 11163ad684d6Sjb150015 return (NT_STATUS_INVALID_HANDLE); 11173ad684d6Sjb150015 } 11183ad684d6Sjb150015 11193ad684d6Sjb150015 if (of->f_granted_access & 11203ad684d6Sjb150015 (FILE_WRITE_DATA | FILE_APPEND_DATA | DELETE)) { 11213ad684d6Sjb150015 mutex_exit(&of->f_mutex); 11223ad684d6Sjb150015 return (NT_STATUS_SHARING_VIOLATION); 11233ad684d6Sjb150015 } 11243ad684d6Sjb150015 11253ad684d6Sjb150015 if ((of->f_share_access & FILE_SHARE_DELETE) == 0) { 11263ad684d6Sjb150015 if (of->f_granted_access & 11273ad684d6Sjb150015 (FILE_READ_DATA | FILE_EXECUTE)) { 11283ad684d6Sjb150015 mutex_exit(&of->f_mutex); 11293ad684d6Sjb150015 return (NT_STATUS_SHARING_VIOLATION); 11303ad684d6Sjb150015 } 11313ad684d6Sjb150015 } 11323ad684d6Sjb150015 11333ad684d6Sjb150015 mutex_exit(&of->f_mutex); 11343ad684d6Sjb150015 return (NT_STATUS_SUCCESS); 11353ad684d6Sjb150015 } 11363ad684d6Sjb150015 11373ad684d6Sjb150015 /* 11383ad684d6Sjb150015 * smb_ofile_delete_check 11393ad684d6Sjb150015 * 11403ad684d6Sjb150015 * An open file can be deleted only if opened for 11413ad684d6Sjb150015 * accessing meta data. Share modes aren't important 11423ad684d6Sjb150015 * in this case. 11433ad684d6Sjb150015 * 11443ad684d6Sjb150015 * NOTE: there is another mechanism for deleting an 11453ad684d6Sjb150015 * open file that NT clients usually use. 11463ad684d6Sjb150015 * That's setting "Delete on close" flag for an open 11473ad684d6Sjb150015 * file. In this way the file will be deleted after 11483ad684d6Sjb150015 * last close. This flag can be set by SmbTrans2SetFileInfo 11493ad684d6Sjb150015 * with FILE_DISPOSITION_INFO information level. 11503ad684d6Sjb150015 * For setting this flag, the file should be opened by 11513ad684d6Sjb150015 * DELETE access in the FID that is passed in the Trans2 11523ad684d6Sjb150015 * request. 11533ad684d6Sjb150015 */ 11543ad684d6Sjb150015 11553ad684d6Sjb150015 uint32_t 11563ad684d6Sjb150015 smb_ofile_delete_check(smb_ofile_t *of) 11573ad684d6Sjb150015 { 11583ad684d6Sjb150015 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 11593ad684d6Sjb150015 11603ad684d6Sjb150015 mutex_enter(&of->f_mutex); 11613ad684d6Sjb150015 11623ad684d6Sjb150015 if (of->f_state != SMB_OFILE_STATE_OPEN) { 11633ad684d6Sjb150015 mutex_exit(&of->f_mutex); 11643ad684d6Sjb150015 return (NT_STATUS_INVALID_HANDLE); 11653ad684d6Sjb150015 } 11663ad684d6Sjb150015 11673ad684d6Sjb150015 if (of->f_granted_access & 11683ad684d6Sjb150015 (FILE_READ_DATA | FILE_WRITE_DATA | 11693ad684d6Sjb150015 FILE_APPEND_DATA | FILE_EXECUTE | DELETE)) { 11703ad684d6Sjb150015 mutex_exit(&of->f_mutex); 11713ad684d6Sjb150015 return (NT_STATUS_SHARING_VIOLATION); 11723ad684d6Sjb150015 } 11733ad684d6Sjb150015 11743ad684d6Sjb150015 mutex_exit(&of->f_mutex); 11753ad684d6Sjb150015 return (NT_STATUS_SUCCESS); 11763ad684d6Sjb150015 } 1177b89a8333Snatalie li - Sun Microsystems - Irvine United States 1178b89a8333Snatalie li - Sun Microsystems - Irvine United States cred_t * 1179b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ofile_getcred(smb_ofile_t *of) 1180b89a8333Snatalie li - Sun Microsystems - Irvine United States { 1181b89a8333Snatalie li - Sun Microsystems - Irvine United States return (of->f_cr); 1182b89a8333Snatalie li - Sun Microsystems - Irvine United States } 11838b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 11848b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States /* 11858b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * smb_ofile_set_delete_on_close 11868b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * 11878b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * Set the DeleteOnClose flag on the smb file. When the file is closed, 11888b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * the flag will be transferred to the smb node, which will commit the 11898b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * delete operation and inhibit subsequent open requests. 11908b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * 11918b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * When DeleteOnClose is set on an smb_node, the common open code will 11928b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * reject subsequent open requests for the file. Observation of Windows 11938b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * 2000 indicates that subsequent opens should be allowed (assuming 11948b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * there would be no sharing violation) until the file is closed using 11958b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * the fid on which the DeleteOnClose was requested. 11968b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States */ 11978b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States void 11988b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_ofile_set_delete_on_close(smb_ofile_t *of) 11998b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States { 12008b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States mutex_enter(&of->f_mutex); 12018b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States of->f_flags |= SMB_OFLAGS_SET_DELETE_ON_CLOSE; 12028b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States mutex_exit(&of->f_mutex); 12038b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States } 12041fcced4cSJordan Brown 12051fcced4cSJordan Brown /* 12061fcced4cSJordan Brown * Encode open file information into a buffer; needed in user space to 12071fcced4cSJordan Brown * support RPC requests. 12081fcced4cSJordan Brown */ 12091fcced4cSJordan Brown static int 12101fcced4cSJordan Brown smb_ofile_netinfo_encode(smb_ofile_t *of, uint8_t *buf, size_t buflen, 12111fcced4cSJordan Brown uint32_t *nbytes) 12121fcced4cSJordan Brown { 12131fcced4cSJordan Brown smb_netfileinfo_t fi; 12141fcced4cSJordan Brown int rc; 12151fcced4cSJordan Brown 12161fcced4cSJordan Brown rc = smb_ofile_netinfo_init(of, &fi); 12171fcced4cSJordan Brown if (rc == 0) { 12181fcced4cSJordan Brown rc = smb_netfileinfo_encode(&fi, buf, buflen, nbytes); 12191fcced4cSJordan Brown smb_ofile_netinfo_fini(&fi); 12201fcced4cSJordan Brown } 12211fcced4cSJordan Brown 12221fcced4cSJordan Brown return (rc); 12231fcced4cSJordan Brown } 12241fcced4cSJordan Brown 12251fcced4cSJordan Brown static int 12261fcced4cSJordan Brown smb_ofile_netinfo_init(smb_ofile_t *of, smb_netfileinfo_t *fi) 12271fcced4cSJordan Brown { 12281fcced4cSJordan Brown smb_user_t *user; 12291fcced4cSJordan Brown smb_tree_t *tree; 12301fcced4cSJordan Brown smb_node_t *node; 12311fcced4cSJordan Brown char *path; 12321fcced4cSJordan Brown char *buf; 12331fcced4cSJordan Brown int rc; 12341fcced4cSJordan Brown 12351fcced4cSJordan Brown ASSERT(of); 12361fcced4cSJordan Brown user = of->f_user; 12371fcced4cSJordan Brown tree = of->f_tree; 12381fcced4cSJordan Brown ASSERT(user); 12391fcced4cSJordan Brown ASSERT(tree); 12401fcced4cSJordan Brown 12411fcced4cSJordan Brown buf = kmem_zalloc(MAXPATHLEN, KM_SLEEP); 12421fcced4cSJordan Brown 12431fcced4cSJordan Brown switch (of->f_ftype) { 12441fcced4cSJordan Brown case SMB_FTYPE_DISK: 12451fcced4cSJordan Brown node = of->f_node; 12461fcced4cSJordan Brown ASSERT(node); 12471fcced4cSJordan Brown 12481fcced4cSJordan Brown fi->fi_permissions = of->f_granted_access; 12491fcced4cSJordan Brown fi->fi_numlocks = smb_lock_get_lock_count(node); 12501fcced4cSJordan Brown 12511fcced4cSJordan Brown path = kmem_zalloc(MAXPATHLEN, KM_SLEEP); 12521fcced4cSJordan Brown 12531fcced4cSJordan Brown if (node != tree->t_snode) { 12541fcced4cSJordan Brown rc = vnodetopath(tree->t_snode->vp, node->vp, path, 12551fcced4cSJordan Brown MAXPATHLEN, kcred); 12561fcced4cSJordan Brown if (rc == 0) 12571fcced4cSJordan Brown (void) strsubst(path, '/', '\\'); 12581fcced4cSJordan Brown else 12591fcced4cSJordan Brown (void) strlcpy(path, node->od_name, MAXPATHLEN); 12601fcced4cSJordan Brown } 12611fcced4cSJordan Brown 12621fcced4cSJordan Brown (void) snprintf(buf, MAXPATHLEN, "%s:%s", tree->t_sharename, 12631fcced4cSJordan Brown path); 12641fcced4cSJordan Brown kmem_free(path, MAXPATHLEN); 12651fcced4cSJordan Brown break; 12661fcced4cSJordan Brown 12671fcced4cSJordan Brown case SMB_FTYPE_MESG_PIPE: 12681fcced4cSJordan Brown ASSERT(of->f_pipe); 12691fcced4cSJordan Brown 12701fcced4cSJordan Brown fi->fi_permissions = FILE_READ_DATA | FILE_WRITE_DATA | 12711fcced4cSJordan Brown FILE_EXECUTE; 12721fcced4cSJordan Brown fi->fi_numlocks = 0; 12731fcced4cSJordan Brown (void) snprintf(buf, MAXPATHLEN, "\\PIPE\\%s", 12741fcced4cSJordan Brown of->f_pipe->p_name); 12751fcced4cSJordan Brown break; 12761fcced4cSJordan Brown 12771fcced4cSJordan Brown default: 12781fcced4cSJordan Brown kmem_free(buf, MAXPATHLEN); 12791fcced4cSJordan Brown return (-1); 12801fcced4cSJordan Brown } 12811fcced4cSJordan Brown 12821fcced4cSJordan Brown fi->fi_fid = of->f_fid; 12831fcced4cSJordan Brown fi->fi_uniqid = of->f_uniqid; 12841fcced4cSJordan Brown fi->fi_pathlen = strlen(buf) + 1; 1285bbf6f00cSJordan Brown fi->fi_path = smb_strdup(buf); 12861fcced4cSJordan Brown kmem_free(buf, MAXPATHLEN); 12871fcced4cSJordan Brown 12881fcced4cSJordan Brown fi->fi_namelen = user->u_domain_len + user->u_name_len + 2; 12891fcced4cSJordan Brown fi->fi_username = kmem_alloc(fi->fi_namelen, KM_SLEEP); 12901fcced4cSJordan Brown (void) snprintf(fi->fi_username, fi->fi_namelen, "%s\\%s", 12911fcced4cSJordan Brown user->u_domain, user->u_name); 12921fcced4cSJordan Brown return (0); 12931fcced4cSJordan Brown } 12941fcced4cSJordan Brown 12951fcced4cSJordan Brown static void 12961fcced4cSJordan Brown smb_ofile_netinfo_fini(smb_netfileinfo_t *fi) 12971fcced4cSJordan Brown { 12981fcced4cSJordan Brown if (fi == NULL) 12991fcced4cSJordan Brown return; 13001fcced4cSJordan Brown 13011fcced4cSJordan Brown if (fi->fi_path) 1302bbf6f00cSJordan Brown smb_mfree(fi->fi_path); 13031fcced4cSJordan Brown if (fi->fi_username) 13041fcced4cSJordan Brown kmem_free(fi->fi_username, fi->fi_namelen); 13051fcced4cSJordan Brown 13061fcced4cSJordan Brown bzero(fi, sizeof (smb_netfileinfo_t)); 13071fcced4cSJordan Brown } 1308