da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER START
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The contents of this file are subject to the terms of the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Common Development and Distribution License (the "License").
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You may not use this file except in compliance with the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * See the License for the specific language governing permissions
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and limitations under the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * When distributing Covered Code, include this CDDL HEADER in each
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If applicable, add the following below this CDDL HEADER, with the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * fields enclosed by brackets "[]" replaced with your own identifying
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * information: Portions Copyright [yyyy] [name of copyright owner]
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER END
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
1fb4a876cbadf3a151ab8a149be6956199e83e22Gordon Ross * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
faa1795a28a5c712eed6d0a3f84d98c368a316c6jbstatic int smb_write_truncate(smb_request_t *, smb_rw_param_t *);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Write count bytes at the specified offset in a file. The offset is
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * limited to 32-bits. If the count is zero, the file is truncated to
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * the length specified by the offset.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The response count indicates the actual number of bytes written, which
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * will equal the requested count on success. If request and response
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * counts differ but there is no error, the client will assume that the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * server encountered a resource issue.
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego rc = smbsr_decode_vwv(sr, "wwl", &sr->smb_fid, &count, &off);
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego param->rw_vdb.vdb_uio.uio_loffset = (offset_t)param->rw_offset;
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
b89a8333f5e1f75ec0c269b22524bd2eccb972banatalie li - Sun Microsystems - Irvine United States sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego if ((rc != 0) || (param->rw_vdb.vdb_len != param->rw_count)) {
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego param->rw_vdb.vdb_uio.uio_loffset = (offset_t)param->rw_offset;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rc != 0) {
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb if (sr->smb_error.status != NT_STATUS_FILE_LOCK_CONFLICT)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Write count bytes to a file and then close the file. This function
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * can only be used to write to 32-bit offsets and the client must set
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * WordCount (6 or 12) correctly in order to locate the data to be
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * written. If an error occurs on the write, the file should still be
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * closed. If Count is 0, the file is truncated (or extended) to offset.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If the last_write time is non-zero, last_write should be used to set
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * the mtime. Otherwise the file system stamps the mtime. Failure to
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * set mtime should not result in an error response.
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb DTRACE_SMB_2(op__WriteAndClose__start, smb_request_t *, sr,
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb DTRACE_SMB_2(op__WriteAndClose__done, smb_request_t *, sr,
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
b89a8333f5e1f75ec0c269b22524bd2eccb972banatalie li - Sun Microsystems - Irvine United States sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * There may be a bug here: should this be "3.#B"?
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego if ((rc != 0) || (param->rw_vdb.vdb_len != param->rw_count)) {
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego param->rw_vdb.vdb_uio.uio_loffset = (offset_t)param->rw_offset;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rc != 0) {
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb if (sr->smb_error.status != NT_STATUS_FILE_LOCK_CONFLICT)
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego smb_ofile_close(sr->fid_ofile, param->rw_last_write);
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego rc = smbsr_encode_result(sr, 1, 0, "bww", 1, count, 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Write count bytes to a file at the specified offset and then unlock
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * them. Write behind is safe because the client should have the range
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * locked and this request is allowed to extend the file - note that
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * offset is limited to 32-bits.
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * Spec advice: it is an error for count to be zero. For compatibility,
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * we take no action and return success.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The SmbLockAndRead/SmbWriteAndUnlock sub-dialect is only valid on disk
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * files. Reject any attempt to use it on other shares.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The response count indicates the actual number of bytes written, which
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * will equal the requested count on success. If request and response
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * counts differ but there is no error, the client will assume that the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * server encountered a resource issue.
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid, &count, &off, &remcnt);
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb DTRACE_SMB_2(op__WriteAndUnlock__start, smb_request_t *, sr,
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb DTRACE_SMB_2(op__WriteAndUnlock__done, smb_request_t *, sr,
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess);
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
b89a8333f5e1f75ec0c269b22524bd2eccb972banatalie li - Sun Microsystems - Irvine United States sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego if ((rc != 0) || (param->rw_count != param->rw_vdb.vdb_len)) {
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego param->rw_vdb.vdb_uio.uio_loffset = (offset_t)param->rw_offset;
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb if (sr->smb_error.status != NT_STATUS_FILE_LOCK_CONFLICT)
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb status = smb_unlock_range(sr, sr->fid_ofile->f_node, param->rw_offset,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Write bytes to a file (SMB Core). This request was extended in
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * LM 0.12 to support 64-bit offsets, indicated by sending a wct of
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * 14, instead of 12, and including additional offset information.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * A ByteCount of 0 does not truncate the file - use SMB_COM_WRITE
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * to truncate a file. A zero length merely transfers zero bytes.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If bit 0 of WriteMode is set, Fid must refer to a disk file and
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * the data must be on stable storage before responding.
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego * MS-SMB 3.3.5.8 update to LM 0.12 4.2.5:
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego * If CAP_LARGE_WRITEX is set, the byte count may be larger than the
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego * negotiated buffer size and the server is expected to write the
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego * number of bytes specified.
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego rc = smbsr_decode_vwv(sr, "4.wl4.wwwwwl", &sr->smb_fid,
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego &off_low, ¶m->rw_mode, &remcnt, &datalen_high,
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego rc = smbsr_decode_vwv(sr, "4.wl4.wwwww", &sr->smb_fid,
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego &off_low, ¶m->rw_mode, &remcnt, &datalen_high,
1fb4a876cbadf3a151ab8a149be6956199e83e22Gordon Ross /* off_high not present */
1fb4a876cbadf3a151ab8a149be6956199e83e22Gordon Ross * Work-around a Win7 bug, where it fails to set the
1fb4a876cbadf3a151ab8a149be6956199e83e22Gordon Ross * CAP_LARGE_WRITEX flag during session setup. Assume
1fb4a876cbadf3a151ab8a149be6956199e83e22Gordon Ross * a large write if the data remaining is >= 64k.
1fb4a876cbadf3a151ab8a149be6956199e83e22Gordon Ross if ((sr->session->capabilities & CAP_LARGE_WRITEX) != 0 ||
1fb4a876cbadf3a151ab8a149be6956199e83e22Gordon Ross (sr->smb_data.max_bytes > (sr->smb_data.chain_offset + 0xFFFF)))
3a6c5f83d4cb79e49561f3fad2b016450f0e6fecAlan Wright param->rw_count |= ((uint32_t)datalen_high << 16);
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
b89a8333f5e1f75ec0c269b22524bd2eccb972banatalie li - Sun Microsystems - Irvine United States sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb rc = smbsr_decode_data(sr, "#.#B", param->rw_dsoff, param->rw_count,
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego if ((rc != 0) || (param->rw_vdb.vdb_len != param->rw_count)) {
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego param->rw_vdb.vdb_uio.uio_loffset = (offset_t)param->rw_offset;
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego rc = smbsr_encode_result(sr, 6, 0, "bb1.wwwwww",
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego 6, sr->andx_com, 15, count_low, 0, count_high, 0, 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Common function for writing files or IPC/MSRPC named pipes.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns errno values.
f96bd5c800e73e351b0b6e4bd7f00b578dad29bbAlan Wrightsmb_common_write(smb_request_t *sr, smb_rw_param_t *param)
5fd03bc0f2e00e7ba02316c2e08f45d52aab15dbGordon Ross * Used to have code here to set mtime.
5fd03bc0f2e00e7ba02316c2e08f45d52aab15dbGordon Ross * We have just done a write, so we know
5fd03bc0f2e00e7ba02316c2e08f45d52aab15dbGordon Ross * the file system will update mtime.
5fd03bc0f2e00e7ba02316c2e08f45d52aab15dbGordon Ross * No need to do it again here.
5fd03bc0f2e00e7ba02316c2e08f45d52aab15dbGordon Ross * However, keep track of the fact that
5fd03bc0f2e00e7ba02316c2e08f45d52aab15dbGordon Ross * we have written data via this handle.
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego param->rw_count = param->rw_vdb.vdb_uio.uio_resid;
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego if ((rc = smb_opipe_write(sr, ¶m->rw_vdb.vdb_uio)) != 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Truncate a disk file to the specified offset.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Typically, w_count will be zero here.
037cac007b685e7ea79f6ef7e8e62bfd342a4d56joyce mcintosh * Note that smb_write_andx cannot be used to reduce the file size so,
037cac007b685e7ea79f6ef7e8e62bfd342a4d56joyce mcintosh * if this is required, smb_write is called with a count of zero and
037cac007b685e7ea79f6ef7e8e62bfd342a4d56joyce mcintosh * the appropriate file length in offset. The file should be resized
037cac007b685e7ea79f6ef7e8e62bfd342a4d56joyce mcintosh * to the length specified by the offset.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns errno values.
faa1795a28a5c712eed6d0a3f84d98c368a316c6jbsmb_write_truncate(smb_request_t *sr, smb_rw_param_t *param)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb status = smb_lock_range_access(sr, node, param->rw_offset,
037cac007b685e7ea79f6ef7e8e62bfd342a4d56joyce mcintosh rc = smb_node_setattr(sr, node, sr->user_cr, ofile, &attr);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);