r23792: convert Samba4 to GPLv3
[tprouty/samba.git] / source4 / libcli / raw / rawreadwrite.c
index 8381c7b2b0121ab6a9572dcbe7298d01e1f9c349..a288b7ec5421c8e783abebb5eb53293e6bf9416b 100644 (file)
@@ -6,7 +6,7 @@
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
@@ -15,8 +15,7 @@
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
@@ -27,7 +26,6 @@
        if (!req) return NULL; \
 } while (0)
 
-
 /****************************************************************************
  low level read operation (async send)
 ****************************************************************************/
@@ -42,7 +40,7 @@ struct smbcli_request *smb_raw_read_send(struct smbcli_tree *tree, union smb_rea
                        bigoffset = True;
                }
                SETUP_REQUEST(SMBreadbraw, bigoffset? 10:8, 0);
-               SSVAL(req->out.vwv, VWV(0), parms->readbraw.in.fnum);
+               SSVAL(req->out.vwv, VWV(0), parms->readbraw.in.file.fnum);
                SIVAL(req->out.vwv, VWV(1), parms->readbraw.in.offset);
                SSVAL(req->out.vwv, VWV(3), parms->readbraw.in.maxcnt);
                SSVAL(req->out.vwv, VWV(4), parms->readbraw.in.mincnt);
@@ -55,7 +53,7 @@ struct smbcli_request *smb_raw_read_send(struct smbcli_tree *tree, union smb_rea
 
        case RAW_READ_LOCKREAD:
                SETUP_REQUEST(SMBlockread, 5, 0);
-               SSVAL(req->out.vwv, VWV(0), parms->lockread.in.fnum);
+               SSVAL(req->out.vwv, VWV(0), parms->lockread.in.file.fnum);
                SSVAL(req->out.vwv, VWV(1), parms->lockread.in.count);
                SIVAL(req->out.vwv, VWV(2), parms->lockread.in.offset);
                SSVAL(req->out.vwv, VWV(4), parms->lockread.in.remaining);
@@ -63,7 +61,7 @@ struct smbcli_request *smb_raw_read_send(struct smbcli_tree *tree, union smb_rea
 
        case RAW_READ_READ:
                SETUP_REQUEST(SMBread, 5, 0);
-               SSVAL(req->out.vwv, VWV(0), parms->read.in.fnum);
+               SSVAL(req->out.vwv, VWV(0), parms->read.in.file.fnum);
                SSVAL(req->out.vwv, VWV(1), parms->read.in.count);
                SIVAL(req->out.vwv, VWV(2), parms->read.in.offset);
                SSVAL(req->out.vwv, VWV(4), parms->read.in.remaining);
@@ -74,18 +72,30 @@ struct smbcli_request *smb_raw_read_send(struct smbcli_tree *tree, union smb_rea
                        bigoffset = True;
                }
                SETUP_REQUEST(SMBreadX, bigoffset ? 12 : 10, 0);
-               SSVAL(req->out.vwv, VWV(0), 0xFF);
+               SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
                SSVAL(req->out.vwv, VWV(1), 0);
-               SSVAL(req->out.vwv, VWV(2), parms->readx.in.fnum);
+               SSVAL(req->out.vwv, VWV(2), parms->readx.in.file.fnum);
                SIVAL(req->out.vwv, VWV(3), parms->readx.in.offset);
                SSVAL(req->out.vwv, VWV(5), parms->readx.in.maxcnt & 0xFFFF);
                SSVAL(req->out.vwv, VWV(6), parms->readx.in.mincnt);
                SIVAL(req->out.vwv, VWV(7), parms->readx.in.maxcnt >> 16);
                SSVAL(req->out.vwv, VWV(9), parms->readx.in.remaining);
+               /*
+                * TODO: give an error when the offset is 64 bit
+                *       and the server doesn't support it
+                */
                if (bigoffset) {
                        SIVAL(req->out.vwv, VWV(10),parms->readx.in.offset>>32);
                }
+               if (parms->readx.in.read_for_execute) {
+                       uint16_t flags2 = SVAL(req->out.hdr, HDR_FLG2);
+                       flags2 |= FLAGS2_READ_PERMIT_EXECUTE;
+                       SSVAL(req->out.hdr, HDR_FLG2, flags2);
+               }
                break;
+
+       case RAW_READ_SMB2:
+               return NULL;
        }
 
        if (!smbcli_request_send(req)) {
@@ -150,6 +160,20 @@ NTSTATUS smb_raw_read_recv(struct smbcli_request *req, union smb_read *parms)
                parms->readx.out.remaining       = SVAL(req->in.vwv, VWV(2));
                parms->readx.out.compaction_mode = SVAL(req->in.vwv, VWV(3));
                parms->readx.out.nread = SVAL(req->in.vwv, VWV(5));
+
+               /* handle oversize replies for non-chained readx replies with
+                  CAP_LARGE_READX. The snia spec has must to answer for. */
+               if ((req->tree->session->transport->negotiate.capabilities & CAP_LARGE_READX)
+                   && CVAL(req->in.vwv, VWV(0)) == SMB_CHAIN_NONE &&
+                   req->in.size >= 0x10000) {
+                       parms->readx.out.nread += (SVAL(req->in.vwv, VWV(7)) << 16);
+                       if (req->in.hdr + SVAL(req->in.vwv, VWV(6)) +
+                           parms->readx.out.nread <= 
+                           req->in.buffer + req->in.size) {
+                               req->in.data_size += (SVAL(req->in.vwv, VWV(7)) << 16);
+                       }
+               }
+
                if (parms->readx.out.nread > MAX(parms->readx.in.mincnt, parms->readx.in.maxcnt) ||
                    !smbcli_raw_pull_data(req, req->in.hdr + SVAL(req->in.vwv, VWV(6)), 
                                       parms->readx.out.nread, 
@@ -157,6 +181,10 @@ NTSTATUS smb_raw_read_recv(struct smbcli_request *req, union smb_read *parms)
                        req->status = NT_STATUS_BUFFER_TOO_SMALL;
                }
                break;
+
+       case RAW_READ_SMB2:
+               req->status = NT_STATUS_INTERNAL_ERROR;
+               break;
        }
 
 failed:
@@ -184,7 +212,7 @@ struct smbcli_request *smb_raw_write_send(struct smbcli_tree *tree, union smb_wr
        switch (parms->generic.level) {
        case RAW_WRITE_WRITEUNLOCK:
                SETUP_REQUEST(SMBwriteunlock, 5, 3 + parms->writeunlock.in.count);
-               SSVAL(req->out.vwv, VWV(0), parms->writeunlock.in.fnum);
+               SSVAL(req->out.vwv, VWV(0), parms->writeunlock.in.file.fnum);
                SSVAL(req->out.vwv, VWV(1), parms->writeunlock.in.count);
                SIVAL(req->out.vwv, VWV(2), parms->writeunlock.in.offset);
                SSVAL(req->out.vwv, VWV(4), parms->writeunlock.in.remaining);
@@ -198,7 +226,7 @@ struct smbcli_request *smb_raw_write_send(struct smbcli_tree *tree, union smb_wr
 
        case RAW_WRITE_WRITE:
                SETUP_REQUEST(SMBwrite, 5,  3 + parms->write.in.count);
-               SSVAL(req->out.vwv, VWV(0), parms->write.in.fnum);
+               SSVAL(req->out.vwv, VWV(0), parms->write.in.file.fnum);
                SSVAL(req->out.vwv, VWV(1), parms->write.in.count);
                SIVAL(req->out.vwv, VWV(2), parms->write.in.offset);
                SSVAL(req->out.vwv, VWV(4), parms->write.in.remaining);
@@ -211,7 +239,7 @@ struct smbcli_request *smb_raw_write_send(struct smbcli_tree *tree, union smb_wr
 
        case RAW_WRITE_WRITECLOSE:
                SETUP_REQUEST(SMBwriteclose, 6, 1 + parms->writeclose.in.count);
-               SSVAL(req->out.vwv, VWV(0), parms->writeclose.in.fnum);
+               SSVAL(req->out.vwv, VWV(0), parms->writeclose.in.file.fnum);
                SSVAL(req->out.vwv, VWV(1), parms->writeclose.in.count);
                SIVAL(req->out.vwv, VWV(2), parms->writeclose.in.offset);
                raw_push_dos_date3(tree->session->transport,
@@ -228,9 +256,9 @@ struct smbcli_request *smb_raw_write_send(struct smbcli_tree *tree, union smb_wr
                        bigoffset = True;
                }
                SETUP_REQUEST(SMBwriteX, bigoffset ? 14 : 12, parms->writex.in.count);
-               SSVAL(req->out.vwv, VWV(0), 0xFF);
+               SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
                SSVAL(req->out.vwv, VWV(1), 0);
-               SSVAL(req->out.vwv, VWV(2), parms->writex.in.fnum);
+               SSVAL(req->out.vwv, VWV(2), parms->writex.in.file.fnum);
                SIVAL(req->out.vwv, VWV(3), parms->writex.in.offset);
                SIVAL(req->out.vwv, VWV(5), 0); /* reserved */
                SSVAL(req->out.vwv, VWV(7), parms->writex.in.wmode);
@@ -248,11 +276,14 @@ struct smbcli_request *smb_raw_write_send(struct smbcli_tree *tree, union smb_wr
 
        case RAW_WRITE_SPLWRITE:
                SETUP_REQUEST(SMBsplwr, 1, parms->splwrite.in.count);
-               SSVAL(req->out.vwv, VWV(0), parms->splwrite.in.fnum);
+               SSVAL(req->out.vwv, VWV(0), parms->splwrite.in.file.fnum);
                if (parms->splwrite.in.count > 0) {
                        memcpy(req->out.data, parms->splwrite.in.data, parms->splwrite.in.count);
                }
                break;
+
+       case RAW_WRITE_SMB2:
+               return NULL;
        }
 
        if (!smbcli_request_send(req)) {
@@ -295,6 +326,9 @@ NTSTATUS smb_raw_write_recv(struct smbcli_request *req, union smb_write *parms)
                break;
        case RAW_WRITE_SPLWRITE:
                break;
+       case RAW_WRITE_SMB2:
+               req->status = NT_STATUS_INTERNAL_ERROR;
+               break;
        }
 
 failed: