15331Samw /* 25331Samw * CDDL HEADER START 35331Samw * 45331Samw * The contents of this file are subject to the terms of the 55331Samw * Common Development and Distribution License (the "License"). 65331Samw * You may not use this file except in compliance with the License. 75331Samw * 85331Samw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 95331Samw * or http://www.opensolaris.org/os/licensing. 105331Samw * See the License for the specific language governing permissions 115331Samw * and limitations under the License. 125331Samw * 135331Samw * When distributing Covered Code, include this CDDL HEADER in each 145331Samw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 155331Samw * If applicable, add the following below this CDDL HEADER, with the 165331Samw * fields enclosed by brackets "[]" replaced with your own identifying 175331Samw * information: Portions Copyright [yyyy] [name of copyright owner] 185331Samw * 195331Samw * CDDL HEADER END 205331Samw */ 215331Samw /* 225331Samw * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 235331Samw * Use is subject to license terms. 245331Samw */ 255331Samw 265331Samw #pragma ident "%Z%%M% %I% %E% SMI" 275331Samw 285331Samw #include <sys/sdt.h> 295331Samw #include <smbsrv/smb_incl.h> 305331Samw #include <smbsrv/smb_fsops.h> 315331Samw #include <smbsrv/mbuf.h> 325331Samw #include <smbsrv/netbios.h> 335331Samw 345331Samw 355331Samw #define SMB_WRMODE_WRITE_THRU 0x0001 365331Samw #define SMB_WRMODE_IS_STABLE(M) ((M) & SMB_WRMODE_WRITE_THRU) 375331Samw 385331Samw 395331Samw typedef struct smb_write_param { 405331Samw struct vardata_block w_vdb; 415331Samw uint64_t w_offset; 425331Samw uint16_t w_mode; 435331Samw uint16_t w_count; 445331Samw } smb_write_param_t; 455331Samw 465331Samw 475331Samw int smb_write_common(struct smb_request *sr, smb_write_param_t *param); 485331Samw int smb_write_truncate(struct smb_request *sr, smb_write_param_t *param); 495331Samw int smb_set_file_size(struct smb_request *sr); 505331Samw 515331Samw 525331Samw /* 535331Samw * Write count bytes at the specified offset in a file. The offset is 545331Samw * limited to 32-bits. If the count is zero, the file is truncated to 555331Samw * the length specified by the offset. 565331Samw * 575331Samw * The response count indicates the actual number of bytes written, which 585331Samw * will equal the requested count on success. If request and response 595331Samw * counts differ but there is no error, the client will assume that the 605331Samw * server encountered a resource issue. 615331Samw */ 625331Samw int 635331Samw smb_com_write(struct smb_request *sr) 645331Samw { 655331Samw smb_write_param_t *param; 665331Samw uint32_t off; 675331Samw int rc; 685331Samw 695331Samw param = kmem_zalloc(sizeof (smb_write_param_t), KM_SLEEP); 705331Samw 715331Samw rc = smbsr_decode_vwv(sr, "wwl", &sr->smb_fid, ¶m->w_count, &off); 725331Samw if (rc != 0) { 735331Samw kmem_free(param, sizeof (smb_write_param_t)); 745331Samw smbsr_decode_error(sr); 755331Samw /* NOTREACHED */ 765331Samw } 775331Samw 785331Samw sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); 795331Samw if (sr->fid_ofile == NULL) { 805331Samw kmem_free(param, sizeof (smb_write_param_t)); 815331Samw smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, 825331Samw ERRDOS, ERRbadfid); 835331Samw /* NOTREACHED */ 845331Samw } 855331Samw 865331Samw param->w_offset = (uint64_t)off; 87*5521Sas200622 param->w_vdb.uio.uio_loffset = (offset_t)param->w_offset; 885331Samw 895331Samw if (param->w_count == 0) { 905331Samw rc = smb_write_truncate(sr, param); 915331Samw } else { 925331Samw rc = smbsr_decode_data(sr, "D", ¶m->w_vdb); 935331Samw 945331Samw if ((rc != 0) || (param->w_vdb.len != param->w_count)) { 955331Samw kmem_free(param, sizeof (smb_write_param_t)); 965331Samw smbsr_decode_error(sr); 975331Samw /* NOTREACHED */ 985331Samw } 995331Samw 100*5521Sas200622 param->w_vdb.uio.uio_loffset = (offset_t)param->w_offset; 1015331Samw 1025331Samw rc = smb_write_common(sr, param); 1035331Samw } 1045331Samw 1055331Samw if (rc != 0) { 1065331Samw kmem_free(param, sizeof (smb_write_param_t)); 1075331Samw smbsr_raise_errno(sr, rc); 1085331Samw /* NOTREACHED */ 1095331Samw } 1105331Samw 1115331Samw smbsr_encode_result(sr, 1, 0, "bww", 1, param->w_count, 0); 1125331Samw kmem_free(param, sizeof (smb_write_param_t)); 1135331Samw return (SDRC_NORMAL_REPLY); 1145331Samw } 1155331Samw 1165331Samw /* 1175331Samw * Write count bytes to a file and then close the file. This function 1185331Samw * can only be used to write to 32-bit offsets and the client must set 1195331Samw * WordCount (6 or 12) correctly in order to locate the data to be 1205331Samw * written. If an error occurs on the write, the file should still be 1215331Samw * closed. If Count is 0, the file is truncated (or extended) to offset. 1225331Samw * 1235331Samw * If the last_write time is non-zero, last_write should be used to set 1245331Samw * the mtime. Otherwise the file system stamps the mtime. Failure to 1255331Samw * set mtime should not result in an error response. 1265331Samw */ 1275331Samw int 1285331Samw smb_com_write_and_close(struct smb_request *sr) 1295331Samw { 1305331Samw smb_write_param_t *param; 1315331Samw uint32_t last_write; 1325331Samw uint32_t off; 1335331Samw int rc = 0; 1345331Samw 1355331Samw param = kmem_zalloc(sizeof (smb_write_param_t), KM_SLEEP); 1365331Samw 1375331Samw if (sr->smb_wct == 12) { 1385331Samw rc = smbsr_decode_vwv(sr, "wwll12.", &sr->smb_fid, 1395331Samw ¶m->w_count, &off, &last_write); 1405331Samw } else { 1415331Samw rc = smbsr_decode_vwv(sr, "wwll", &sr->smb_fid, 1425331Samw ¶m->w_count, &off, &last_write); 1435331Samw } 1445331Samw 1455331Samw if (rc != 0) { 1465331Samw kmem_free(param, sizeof (smb_write_param_t)); 1475331Samw smbsr_decode_error(sr); 1485331Samw /* NOTREACHED */ 1495331Samw } 1505331Samw 1515331Samw sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); 1525331Samw if (sr->fid_ofile == NULL) { 1535331Samw kmem_free(param, sizeof (smb_write_param_t)); 1545331Samw smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, 1555331Samw ERRDOS, ERRbadfid); 1565331Samw /* NOTREACHED */ 1575331Samw } 1585331Samw 1595331Samw param->w_offset = (uint64_t)off; 1605331Samw 1615331Samw if (param->w_count == 0) { 1625331Samw rc = smb_write_truncate(sr, param); 1635331Samw } else { 1645331Samw /* 1655331Samw * There may be a bug here: should this be "3.#B"? 1665331Samw */ 1675331Samw rc = smbsr_decode_data(sr, ".#B", param->w_count, 1685331Samw ¶m->w_vdb); 1695331Samw 1705331Samw if ((rc != 0) || (param->w_vdb.len != param->w_count)) { 1715331Samw kmem_free(param, sizeof (smb_write_param_t)); 1725331Samw smbsr_decode_error(sr); 1735331Samw /* NOTREACHED */ 1745331Samw } 1755331Samw 176*5521Sas200622 param->w_vdb.uio.uio_loffset = (offset_t)param->w_offset; 1775331Samw 1785331Samw rc = smb_write_common(sr, param); 1795331Samw } 1805331Samw 1815331Samw if (rc != 0) { 1825331Samw kmem_free(param, sizeof (smb_write_param_t)); 1835331Samw smbsr_raise_errno(sr, rc); 1845331Samw /* NOTREACHED */ 1855331Samw } 1865331Samw 1875331Samw if ((rc = smb_common_close(sr, last_write)) != 0) { 1885331Samw kmem_free(param, sizeof (smb_write_param_t)); 1895331Samw smbsr_raise_errno(sr, rc); 1905331Samw /* NOTREACHED */ 1915331Samw } 1925331Samw 1935331Samw smbsr_encode_result(sr, 1, 0, "bww", 1, param->w_count, 0); 1945331Samw kmem_free(param, sizeof (smb_write_param_t)); 1955331Samw return (SDRC_NORMAL_REPLY); 1965331Samw } 1975331Samw 1985331Samw /* 1995331Samw * Write count bytes to a file at the specified offset and then unlock 2005331Samw * them. Write behind is safe because the client should have the range 2015331Samw * locked and this request is allowed to extend the file - note that 2025331Samw * offest is limited to 32-bits. It is an error for count to be zero. 2035331Samw * 2045331Samw * The SmbLockAndRead/SmbWriteAndUnlock sub-dialect is only valid on disk 2055331Samw * files. Reject any attempt to use it on other shares. 2065331Samw * 2075331Samw * The response count indicates the actual number of bytes written, which 2085331Samw * will equal the requested count on success. If request and response 2095331Samw * counts differ but there is no error, the client will assume that the 2105331Samw * server encountered a resource issue. 2115331Samw */ 2125331Samw int 2135331Samw smb_com_write_and_unlock(struct smb_request *sr) 2145331Samw { 2155331Samw smb_write_param_t *param; 2165331Samw uint32_t off; 2175331Samw uint32_t result; 2185331Samw uint16_t remcnt; 2195331Samw int rc = 0; 2205331Samw 2215331Samw if (STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) { 2225331Samw smbsr_raise_error(sr, ERRDOS, ERRnoaccess); 2235331Samw /* NOTREACHED */ 2245331Samw } 2255331Samw 2265331Samw param = kmem_zalloc(sizeof (smb_write_param_t), KM_SLEEP); 2275331Samw 2285331Samw rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid, ¶m->w_count, &off, 2295331Samw &remcnt); 2305331Samw if (rc != 0) { 2315331Samw kmem_free(param, sizeof (smb_write_param_t)); 2325331Samw smbsr_decode_error(sr); 2335331Samw /* NOTREACHED */ 2345331Samw } 2355331Samw 2365331Samw sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); 2375331Samw if (sr->fid_ofile == NULL) { 2385331Samw kmem_free(param, sizeof (smb_write_param_t)); 2395331Samw smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, 2405331Samw ERRDOS, ERRbadfid); 2415331Samw /* NOTREACHED */ 2425331Samw } 2435331Samw 2445331Samw if (param->w_count == 0) { 2455331Samw smbsr_decode_error(sr); 2465331Samw /* NOTREACHED */ 2475331Samw } 2485331Samw 2495331Samw rc = smbsr_decode_data(sr, "D", ¶m->w_vdb); 2505331Samw 2515331Samw if ((rc != 0) || (param->w_count != param->w_vdb.len)) { 2525331Samw kmem_free(param, sizeof (smb_write_param_t)); 2535331Samw smbsr_decode_error(sr); 2545331Samw /* NOTREACHED */ 2555331Samw } 2565331Samw 2575331Samw param->w_offset = (uint64_t)off; 258*5521Sas200622 param->w_vdb.uio.uio_loffset = (offset_t)param->w_offset; 2595331Samw 2605331Samw if ((rc = smb_write_common(sr, param)) != 0) { 2615331Samw kmem_free(param, sizeof (smb_write_param_t)); 2625331Samw smbsr_raise_errno(sr, rc); 2635331Samw /* NOTREACHED */ 2645331Samw } 2655331Samw 2665331Samw result = smb_unlock_range(sr, sr->fid_ofile->f_node, param->w_offset, 2675331Samw (uint64_t)param->w_count); 2685331Samw if (result != NT_STATUS_SUCCESS) { 2695331Samw kmem_free(param, sizeof (smb_write_param_t)); 2705331Samw smb_unlock_range_raise_error(sr, result); 2715331Samw /* NOTREACHED */ 2725331Samw } 2735331Samw 2745331Samw smbsr_encode_result(sr, 1, 0, "bww", 1, param->w_count, 0); 2755331Samw kmem_free(param, sizeof (smb_write_param_t)); 2765331Samw return (SDRC_NORMAL_REPLY); 2775331Samw } 2785331Samw 2795331Samw /* 2805331Samw * Write bytes to a file (SMB Core). This request was extended in 2815331Samw * LM 0.12 to support 64-bit offsets, indicated by sending a wct of 2825331Samw * 14, instead of 12, and including additional offset information. 2835331Samw * 2845331Samw * A ByteCount of 0 does not truncate the file - use SMB_COM_WRITE 2855331Samw * to truncate a file. A zero length merely transfers zero bytes. 2865331Samw * 2875331Samw * If bit 0 of WriteMode is set, Fid must refer to a disk file and 2885331Samw * the data must be on stable storage before responding. 2895331Samw */ 2905331Samw int 2915331Samw smb_com_write_andx(struct smb_request *sr) 2925331Samw { 2935331Samw smb_write_param_t *param; 2945331Samw uint32_t off_low; 2955331Samw uint32_t off_high; 2965331Samw uint16_t data_offset; 2975331Samw uint16_t remcnt; 2985331Samw int rc = 0; 2995331Samw 3005331Samw param = kmem_zalloc(sizeof (smb_write_param_t), KM_SLEEP); 3015331Samw 3025331Samw if (sr->smb_wct == 14) { 3035331Samw rc = smbsr_decode_vwv(sr, "4.wl4.ww2.wwl", &sr->smb_fid, 3045331Samw &off_low, ¶m->w_mode, &remcnt, ¶m->w_count, 3055331Samw &data_offset, &off_high); 3065331Samw 3075331Samw data_offset -= 63; 3085331Samw param->w_offset = ((uint64_t)off_high << 32) | off_low; 3095331Samw } else { 3105331Samw rc = smbsr_decode_vwv(sr, "4.wl4.ww2.ww", &sr->smb_fid, 3115331Samw &off_low, ¶m->w_mode, &remcnt, ¶m->w_count, 3125331Samw &data_offset); 3135331Samw 3145331Samw param->w_offset = (uint64_t)off_low; 3155331Samw data_offset -= 59; 3165331Samw } 3175331Samw 3185331Samw if (rc != 0) { 3195331Samw kmem_free(param, sizeof (smb_write_param_t)); 3205331Samw smbsr_decode_error(sr); 3215331Samw /* NOTREACHED */ 3225331Samw } 3235331Samw 3245331Samw sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); 3255331Samw if (sr->fid_ofile == NULL) { 3265331Samw kmem_free(param, sizeof (smb_write_param_t)); 3275331Samw smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, 3285331Samw ERRDOS, ERRbadfid); 3295331Samw /* NOTREACHED */ 3305331Samw } 3315331Samw 3325331Samw if (SMB_WRMODE_IS_STABLE(param->w_mode) && 3335331Samw STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) { 3345331Samw kmem_free(param, sizeof (smb_write_param_t)); 3355331Samw smbsr_raise_error(sr, ERRSRV, ERRaccess); 3365331Samw /* NOTREACHED */ 3375331Samw } 3385331Samw 3395331Samw rc = smbsr_decode_data(sr, "#.#B", data_offset, param->w_count, 3405331Samw ¶m->w_vdb); 3415331Samw if ((rc != 0) || (param->w_vdb.len != param->w_count)) { 3425331Samw kmem_free(param, sizeof (smb_write_param_t)); 3435331Samw smbsr_decode_error(sr); 3445331Samw /* NOTREACHED */ 3455331Samw } 3465331Samw 347*5521Sas200622 param->w_vdb.uio.uio_loffset = (offset_t)param->w_offset; 3485331Samw 3495331Samw if (param->w_count != 0) { 3505331Samw if ((rc = smb_write_common(sr, param)) != 0) { 3515331Samw kmem_free(param, sizeof (smb_write_param_t)); 3525331Samw smbsr_raise_errno(sr, rc); 3535331Samw /* NOTREACHED */ 3545331Samw } 3555331Samw } 3565331Samw 3575331Samw smbsr_encode_result(sr, 6, 0, "bb1.ww6.w", 3585331Samw 6, sr->andx_com, 15, param->w_count, 0); 3595331Samw 3605331Samw kmem_free(param, sizeof (smb_write_param_t)); 3615331Samw return (SDRC_NORMAL_REPLY); 3625331Samw } 3635331Samw 3645331Samw /* 3655331Samw * Common function for writing files or IPC/MSRPC named pipes. 3665331Samw * 3675331Samw * Returns errno values. 3685331Samw */ 3695331Samw int 3705331Samw smb_write_common(struct smb_request *sr, smb_write_param_t *param) 3715331Samw { 3725331Samw struct smb_ofile *ofile = sr->fid_ofile; 3735331Samw smb_node_t *node; 3745331Samw uint32_t stability = FSSTAB_UNSTABLE; 3755331Samw uint32_t lcount; 3765331Samw int rc = 0; 3775331Samw 3785331Samw switch (sr->tid_tree->t_res_type & STYPE_MASK) { 3795331Samw case STYPE_DISKTREE: 3805331Samw node = ofile->f_node; 3815331Samw 3825331Samw if (node->attr.sa_vattr.va_type != VDIR) { 3835331Samw rc = smb_lock_range_access(sr, node, param->w_offset, 3845331Samw param->w_count, FILE_WRITE_DATA); 3855331Samw if (rc != NT_STATUS_SUCCESS) { 3865331Samw smbsr_raise_cifs_error(sr, rc, 3875331Samw ERRSRV, ERRaccess); 3885331Samw /* NOTREACHED */ 3895331Samw } 3905331Samw } 3915331Samw 3925331Samw if (SMB_WRMODE_IS_STABLE(param->w_mode) || 3935331Samw (node->flags & NODE_FLAGS_WRITE_THROUGH)) { 3945331Samw stability = FSSTAB_FILE_SYNC; 3955331Samw } 3965331Samw 3975331Samw rc = smb_fsop_write(sr, sr->user_cr, node, 3985331Samw ¶m->w_vdb.uio, &lcount, &node->attr, &stability); 3995331Samw 4005331Samw if (rc) 4015331Samw return (rc); 4025331Samw 4035331Samw node->flags |= NODE_FLAGS_SYNCATIME; 4045331Samw 4055331Samw if (node->flags & NODE_FLAGS_SET_SIZE) { 4065331Samw if ((param->w_offset + lcount) >= node->n_size) { 4075331Samw node->flags &= ~NODE_FLAGS_SET_SIZE; 4085331Samw node->n_size = param->w_offset + lcount; 4095331Samw } 4105331Samw } 4115331Samw 4125331Samw param->w_count = (uint16_t)lcount; 4135331Samw break; 4145331Samw 4155331Samw case STYPE_IPC: 4165331Samw param->w_count = (uint16_t)param->w_vdb.uio.uio_resid; 4175331Samw 4185331Samw if ((rc = smb_rpc_write(sr, ¶m->w_vdb.uio)) != 0) 4195331Samw param->w_count = 0; 4205331Samw break; 4215331Samw 4225331Samw default: 4235331Samw rc = EACCES; 4245331Samw break; 4255331Samw } 4265331Samw 4275331Samw if (rc != 0) 4285331Samw return (rc); 4295331Samw 4305331Samw mutex_enter(&ofile->f_mutex); 4315331Samw ofile->f_seek_pos = param->w_offset + param->w_count; 4325331Samw mutex_exit(&ofile->f_mutex); 4335331Samw return (rc); 4345331Samw } 4355331Samw 4365331Samw /* 4375331Samw * Truncate a disk file to the specified offset. 4385331Samw * Typically, w_count will be zero here. 4395331Samw * 4405331Samw * Returns errno values. 4415331Samw */ 4425331Samw int 4435331Samw smb_write_truncate(struct smb_request *sr, smb_write_param_t *param) 4445331Samw { 4455331Samw struct smb_ofile *ofile = sr->fid_ofile; 4465331Samw smb_node_t *node = ofile->f_node; 4475331Samw int rc; 4485331Samw 4495331Samw if (STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) 4505331Samw return (0); 4515331Samw 4525331Samw if (node->attr.sa_vattr.va_type != VDIR) { 4535331Samw rc = smb_lock_range_access(sr, node, param->w_offset, 4545331Samw param->w_count, FILE_WRITE_DATA); 4555331Samw if (rc != NT_STATUS_SUCCESS) { 4565331Samw smbsr_raise_cifs_error(sr, rc, 4575331Samw ERRSRV, ERRaccess); 4585331Samw /* NOTREACHED */ 4595331Samw } 4605331Samw } 4615331Samw 4625331Samw /* 4635331Samw * XXX what if the file has been opened only with 4645331Samw * FILE_APPEND_DATA? 4655331Samw */ 4665331Samw rc = smb_ofile_access(ofile, sr->user_cr, FILE_WRITE_DATA); 4675331Samw if (rc != NT_STATUS_SUCCESS) { 4685331Samw smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, 4695331Samw ERRDOS, ERROR_ACCESS_DENIED); 4705331Samw /* NOTREACHED */ 4715331Samw } 4725331Samw 4735331Samw node->flags |= NODE_FLAGS_SET_SIZE; 4745331Samw node->n_size = param->w_offset; 4755331Samw 4765331Samw if ((rc = smb_set_file_size(sr)) != 0) 4775331Samw return (rc); 4785331Samw 4795331Samw mutex_enter(&ofile->f_mutex); 4805331Samw ofile->f_seek_pos = param->w_offset + param->w_count; 4815331Samw mutex_exit(&ofile->f_mutex); 4825331Samw return (0); 4835331Samw } 4845331Samw 4855331Samw /* 4865331Samw * Set the file size using the value in the node. The file will only be 4875331Samw * updated if NODE_FLAGS_SET_SIZE is set. It is safe to pass a null node 4885331Samw * pointer, we just return success. 4895331Samw * 4905331Samw * The node attributes are refreshed here from the file system. So any 4915331Samw * attributes that are affected by file size changes, i.e. the mtime, 4925331Samw * will be current. 4935331Samw * 4945331Samw * Note that smb_write_andx cannot be used to reduce the file size so, 4955331Samw * if this is required, smb_write is called with a count of zero and 4965331Samw * the appropriate file length in offset. The file should be resized 4975331Samw * to the length specified by the offset. 4985331Samw * 4995331Samw * Returns 0 on success. Otherwise returns EACCES. 5005331Samw */ 5015331Samw int 5025331Samw smb_set_file_size(struct smb_request *sr) 5035331Samw { 5045331Samw struct smb_node *node; 5055331Samw smb_attr_t new_attr; 5065331Samw uint32_t dosattr; 5075331Samw 5085331Samw if ((node = sr->fid_ofile->f_node) == 0) 5095331Samw return (0); 5105331Samw 5115331Samw if ((node->flags & NODE_FLAGS_SET_SIZE) == 0) 5125331Samw return (0); 5135331Samw 5145331Samw node->flags &= ~NODE_FLAGS_SET_SIZE; 5155331Samw 5165331Samw dosattr = smb_node_get_dosattr(node); 5175331Samw 5185331Samw if (dosattr & SMB_FA_READONLY) { 5195331Samw if (((node->flags & NODE_FLAGS_CREATED) == 0) || 5205331Samw (sr->session->s_kid != node->n_orig_session_id)) 5215331Samw return (EACCES); 5225331Samw } 5235331Samw 5245331Samw bzero(&new_attr, sizeof (new_attr)); 5255331Samw new_attr.sa_vattr.va_size = node->n_size; 5265331Samw new_attr.sa_mask = SMB_AT_SIZE; 5275331Samw 5285331Samw (void) smb_fsop_setattr(sr, sr->user_cr, node, &new_attr, 5295331Samw &node->attr); 5305331Samw 5315331Samw return (0); 5325331Samw } 5335331Samw 5345331Samw /* 5355331Samw * write_complete is sent acknowledge completion of raw write requests. 5365331Samw * We never send raw write commands to other servers so, if we receive a 5375331Samw * write_complete, we treat it as an error. 5385331Samw */ 5395331Samw int 5405331Samw smb_com_write_complete(struct smb_request *sr) 5415331Samw { 5425331Samw smbsr_decode_error(sr); 5435331Samw /* NOT REACHED */ 5445331Samw return (0); 5455331Samw } 5465331Samw 5475331Samw /* 5485331Samw * The Write Block Multiplexed protocol is used to maximize performance 5495331Samw * when writing a large block of data. 5505331Samw * 5515331Samw * The mpx sub protocol is not supported because we support only 5525331Samw * connection oriented transports and NT supports SMB_COM_READ_MPX 5535331Samw * only over connectionless transports. 5545331Samw */ 5555331Samw int /*ARGSUSED*/ 5565331Samw smb_com_write_mpx(struct smb_request *sr) 5575331Samw { 5585331Samw return (SDRC_UNIMPLEMENTED); 5595331Samw } 5605331Samw 5615331Samw int /*ARGSUSED*/ 5625331Samw smb_com_write_mpx_secondary(struct smb_request *sr) 5635331Samw { 5645331Samw return (SDRC_UNIMPLEMENTED); 5655331Samw } 566