Line data Source code
1 : /* 2 : Unix SMB/CIFS implementation. 3 : client file read/write routines 4 : Copyright (C) Andrew Tridgell 1994-1998 5 : Copyright (C) James Myers 2003 6 : 7 : This program is free software; you can redistribute it and/or modify 8 : it under the terms of the GNU General Public License as published by 9 : the Free Software Foundation; either version 3 of the License, or 10 : (at your option) any later version. 11 : 12 : This program is distributed in the hope that it will be useful, 13 : but WITHOUT ANY WARRANTY; without even the implied warranty of 14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 : GNU General Public License for more details. 16 : 17 : You should have received a copy of the GNU General Public License 18 : along with this program. If not, see <http://www.gnu.org/licenses/>. 19 : */ 20 : 21 : #include "includes.h" 22 : #include "libcli/raw/libcliraw.h" 23 : #include "libcli/raw/raw_proto.h" 24 : #include "libcli/libcli.h" 25 : 26 : /**************************************************************************** 27 : Read size bytes at offset offset using SMBreadX. 28 : ****************************************************************************/ 29 1453 : ssize_t smbcli_read(struct smbcli_tree *tree, int fnum, void *_buf, off_t offset, 30 : size_t size) 31 : { 32 1453 : uint8_t *buf = (uint8_t *)_buf; 33 23 : union smb_read parms; 34 23 : int readsize; 35 1453 : ssize_t total = 0; 36 : 37 1453 : if (size == 0) { 38 0 : return 0; 39 : } 40 : 41 1453 : parms.readx.level = RAW_READ_READX; 42 1453 : parms.readx.in.file.fnum = fnum; 43 : 44 : /* 45 : * Set readsize to the maximum size we can handle in one readX, 46 : * rounded down to a multiple of 1024. 47 : */ 48 1453 : readsize = (tree->session->transport->negotiate.max_xmit - (MIN_SMB_SIZE+32)); 49 1453 : if (readsize > 0xFFFF) readsize = 0xFFFF; 50 : 51 3062 : while (total < size) { 52 23 : NTSTATUS status; 53 : 54 2002 : readsize = MIN(readsize, size-total); 55 : 56 2002 : parms.readx.in.offset = offset; 57 2002 : parms.readx.in.mincnt = readsize; 58 2002 : parms.readx.in.maxcnt = readsize; 59 2002 : parms.readx.in.remaining = size - total; 60 2002 : parms.readx.in.read_for_execute = false; 61 2002 : parms.readx.out.data = buf + total; 62 : 63 2002 : status = smb_raw_read(tree, &parms); 64 : 65 2002 : if (!NT_STATUS_IS_OK(status)) { 66 351 : return -1; 67 : } 68 : 69 1651 : total += parms.readx.out.nread; 70 1651 : offset += parms.readx.out.nread; 71 : 72 : /* If the server returned less than we asked for we're at EOF */ 73 1651 : if (parms.readx.out.nread < readsize) 74 42 : break; 75 : } 76 : 77 1080 : return total; 78 : } 79 : 80 : 81 : /**************************************************************************** 82 : write to a file 83 : write_mode: 0x0001 disallow write caching 84 : 0x0002 return bytes remaining 85 : 0x0004 use raw named pipe protocol 86 : 0x0008 start of message mode named pipe protocol 87 : ****************************************************************************/ 88 2788 : ssize_t smbcli_write(struct smbcli_tree *tree, 89 : int fnum, uint16_t write_mode, 90 : const void *_buf, off_t offset, size_t size) 91 : { 92 2788 : const uint8_t *buf = (const uint8_t *)_buf; 93 46 : union smb_write parms; 94 2788 : int block = (tree->session->transport->negotiate.max_xmit - (MIN_SMB_SIZE+32)); 95 2788 : ssize_t total = 0; 96 : 97 2788 : if (size == 0) { 98 32 : return 0; 99 : } 100 : 101 2756 : if (block > 0xFFFF) block = 0xFFFF; 102 : 103 : 104 2756 : parms.writex.level = RAW_WRITE_WRITEX; 105 2756 : parms.writex.in.file.fnum = fnum; 106 2756 : parms.writex.in.wmode = write_mode; 107 2756 : parms.writex.in.remaining = 0; 108 : 109 52 : do { 110 52 : NTSTATUS status; 111 : 112 3411 : block = MIN(block, size - total); 113 : 114 3411 : parms.writex.in.offset = offset; 115 3411 : parms.writex.in.count = block; 116 3411 : parms.writex.in.data = buf; 117 : 118 3411 : status = smb_raw_write(tree, &parms); 119 : 120 3411 : if (!NT_STATUS_IS_OK(status)) { 121 422 : return -1; 122 : } 123 : 124 2989 : offset += parms.writex.out.nwritten; 125 2989 : total += parms.writex.out.nwritten; 126 2989 : buf += parms.writex.out.nwritten; 127 2989 : } while (total < size); 128 : 129 2294 : return total; 130 : } 131 : 132 : /**************************************************************************** 133 : write to a file using a SMBwrite and not bypassing 0 byte writes 134 : ****************************************************************************/ 135 67 : ssize_t smbcli_smbwrite(struct smbcli_tree *tree, 136 : int fnum, const void *_buf, off_t offset, size_t size1) 137 : { 138 67 : const uint8_t *buf = (const uint8_t *)_buf; 139 0 : union smb_write parms; 140 67 : ssize_t total = 0; 141 : 142 67 : parms.write.level = RAW_WRITE_WRITE; 143 67 : parms.write.in.remaining = 0; 144 : 145 0 : do { 146 67 : size_t size = MIN(size1, tree->session->transport->negotiate.max_xmit - 48); 147 67 : if (size > 0xFFFF) size = 0xFFFF; 148 : 149 67 : parms.write.in.file.fnum = fnum; 150 67 : parms.write.in.offset = offset; 151 67 : parms.write.in.count = size; 152 67 : parms.write.in.data = buf + total; 153 : 154 67 : if (NT_STATUS_IS_ERR(smb_raw_write(tree, &parms))) 155 0 : return -1; 156 : 157 67 : size = parms.write.out.nwritten; 158 67 : if (size == 0) 159 52 : break; 160 : 161 15 : size1 -= size; 162 15 : total += size; 163 15 : offset += size; 164 15 : } while (size1); 165 : 166 67 : return total; 167 : }