Ignore:
Timestamp:
Nov 27, 2012, 4:43:17 PM (13 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: updated trunk to 3.6.0

Location:
trunk/server
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/server

  • trunk/server/source3/libsmb/clireadwrite.c

    r668 r745  
    1919
    2020#include "includes.h"
     21#include "libsmb/libsmb.h"
     22#include "../lib/util/tevent_ntstatus.h"
     23#include "async_smb.h"
     24#include "trans2.h"
    2125
    2226/****************************************************************************
     
    2529static size_t cli_read_max_bufsize(struct cli_state *cli)
    2630{
     31        size_t data_offset = smb_size - 4;
     32        size_t wct = 12;
     33
     34        size_t useable_space;
     35
    2736        if (!client_is_signing_on(cli) && !cli_encryption_on(cli)
    28             && (cli->posix_capabilities & CIFS_UNIX_LARGE_READ_CAP)) {
     37            && (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP)) {
    2938                return CLI_SAMBA_MAX_POSIX_LARGE_READX_SIZE;
    3039        }
     
    3443                        : CLI_WINDOWS_MAX_LARGE_READX_SIZE;
    3544        }
    36         return (cli->max_xmit - (smb_size+32)) & ~1023;
     45
     46        data_offset += wct * sizeof(uint16_t);
     47        data_offset += 1; /* pad */
     48
     49        useable_space = cli->max_xmit - data_offset;
     50
     51        return useable_space;
    3752}
    3853
     
    4055  Calculate the recommended write buffer size
    4156****************************************************************************/
    42 static size_t cli_write_max_bufsize(struct cli_state *cli, uint16_t write_mode)
     57static size_t cli_write_max_bufsize(struct cli_state *cli,
     58                                    uint16_t write_mode,
     59                                    uint8_t wct)
    4360{
    4461        if (write_mode == 0 &&
    4562            !client_is_signing_on(cli) &&
    4663            !cli_encryption_on(cli) &&
    47             (cli->posix_capabilities & CIFS_UNIX_LARGE_WRITE_CAP) &&
     64            (cli->server_posix_capabilities & CIFS_UNIX_LARGE_WRITE_CAP) &&
    4865            (cli->capabilities & CAP_LARGE_FILES)) {
    4966                /* Only do massive writes if we can do them direct
     
    5976            || client_is_signing_on(cli)
    6077            || strequal(cli->dev, "LPT1:")) {
    61 
    62                 /*
    63                  * Printer devices are restricted to max_xmit writesize in
    64                  * Vista and XPSP3 as are signing connections.
    65                  */
    66 
    67                 return (cli->max_xmit - (smb_size+32)) & ~1023;
     78                size_t data_offset = smb_size - 4;
     79                size_t useable_space;
     80
     81                data_offset += wct * sizeof(uint16_t);
     82                data_offset += 1; /* pad */
     83
     84                useable_space = cli->max_xmit - data_offset;
     85
     86                return useable_space;
    6887        }
    6988
     
    89108        struct tevent_req *req, *subreq;
    90109        struct cli_read_andx_state *state;
    91         bool bigoffset = False;
    92110        uint8_t wct = 10;
    93111
     
    117135
    118136        if ((uint64_t)offset >> 32) {
    119                 bigoffset = true;
    120137                SIVAL(state->vwv + 10, 0,
    121138                      (((uint64_t)offset)>>32) & 0xffffffff);
     
    149166
    150167        status = cli_smb_req_send(subreq);
    151         if (!NT_STATUS_IS_OK(status)) {
    152                 tevent_req_nterror(req, status);
     168        if (tevent_req_nterror(req, status)) {
    153169                return tevent_req_post(req, ev);
    154170        }
     
    168184        uint8_t *bytes;
    169185
    170         state->status = cli_smb_recv(subreq, 12, &wct, &vwv, &num_bytes,
    171                                      &bytes);
     186        state->status = cli_smb_recv(subreq, state, &inbuf, 12, &wct, &vwv,
     187                                     &num_bytes, &bytes);
     188        TALLOC_FREE(subreq);
    172189        if (NT_STATUS_IS_ERR(state->status)) {
    173190                tevent_req_nterror(req, state->status);
     
    197214        }
    198215
    199         inbuf = cli_smb_inbuf(subreq);
    200216        state->buf = (uint8_t *)smb_base(inbuf) + SVAL(vwv+6, 0);
    201217
     
    283299
    284300        status = cli_read_andx_recv(subreq, &received, &buf);
    285         if (!NT_STATUS_IS_OK(status)) {
    286                 tevent_req_nterror(req, status);
     301        if (tevent_req_nterror(req, status)) {
    287302                return;
    288303        }
     
    411426        char *result;
    412427
    413         result = tevent_req_print(mem_ctx, req);
     428        result = tevent_req_default_print(req, mem_ctx);
    414429        if (result == NULL) {
    415430                return NULL;
     
    570585                status = state->sink((char *)top_subreq->buf,
    571586                                     top_subreq->received, state->priv);
    572                 if (!NT_STATUS_IS_OK(status)) {
    573                         tevent_req_nterror(state->req, status);
     587                if (tevent_req_nterror(state->req, status)) {
    574588                        return;
    575589                }
     
    697711
    698712/****************************************************************************
    699  Issue a single SMBwrite and don't wait for a reply.
    700 ****************************************************************************/
    701 
    702 static bool cli_issue_write(struct cli_state *cli,
    703                                 uint16_t fnum,
    704                                 off_t offset,
    705                                 uint16 mode,
    706                                 const char *buf,
    707                                 size_t size)
    708 {
    709         char *p;
    710         bool large_writex = false;
    711         /* We can only do direct writes if not signing and not encrypting. */
    712         bool direct_writes = !client_is_signing_on(cli) && !cli_encryption_on(cli);
    713 
    714         if (!direct_writes && size + 1 > cli->bufsize) {
    715                 cli->outbuf = (char *)SMB_REALLOC(cli->outbuf, size + 1024);
    716                 if (!cli->outbuf) {
    717                         return False;
    718                 }
    719                 cli->inbuf = (char *)SMB_REALLOC(cli->inbuf, size + 1024);
    720                 if (cli->inbuf == NULL) {
    721                         SAFE_FREE(cli->outbuf);
    722                         return False;
    723                 }
    724                 cli->bufsize = size + 1024;
    725         }
    726 
    727         memset(cli->outbuf,'\0',smb_size);
    728         memset(cli->inbuf,'\0',smb_size);
    729 
    730         if (cli->capabilities & CAP_LARGE_FILES) {
    731                 large_writex = True;
    732         }
    733 
    734         if (large_writex) {
    735                 cli_set_message(cli->outbuf,14,0,True);
    736         } else {
    737                 cli_set_message(cli->outbuf,12,0,True);
    738         }
    739 
    740         SCVAL(cli->outbuf,smb_com,SMBwriteX);
    741         SSVAL(cli->outbuf,smb_tid,cli->cnum);
    742         cli_setup_packet(cli);
    743 
    744         SCVAL(cli->outbuf,smb_vwv0,0xFF);
    745         SSVAL(cli->outbuf,smb_vwv2,fnum);
    746 
    747         SIVAL(cli->outbuf,smb_vwv3,offset);
    748         SIVAL(cli->outbuf,smb_vwv5,0);
    749         SSVAL(cli->outbuf,smb_vwv7,mode);
    750 
    751         SSVAL(cli->outbuf,smb_vwv8,(mode & 0x0008) ? size : 0);
    752         /*
    753          * According to CIFS-TR-1p00, this following field should only
    754          * be set if CAP_LARGE_WRITEX is set. We should check this
    755          * locally. However, this check might already have been
    756          * done by our callers.
    757          */
    758         SSVAL(cli->outbuf,smb_vwv9,(size>>16));
    759         SSVAL(cli->outbuf,smb_vwv10,size);
    760         /* +1 is pad byte. */
    761         SSVAL(cli->outbuf,smb_vwv11,
    762               smb_buf(cli->outbuf) - smb_base(cli->outbuf) + 1);
    763 
    764         if (large_writex) {
    765                 SIVAL(cli->outbuf,smb_vwv12,(((uint64_t)offset)>>32) & 0xffffffff);
    766         }
    767 
    768         p = smb_base(cli->outbuf) + SVAL(cli->outbuf,smb_vwv11) -1;
    769         *p++ = '\0'; /* pad byte. */
    770         if (!direct_writes) {
    771                 memcpy(p, buf, size);
    772         }
    773         if (size > 0x1FFFF) {
    774                 /* This is a POSIX 14 word large write. */
    775                 set_message_bcc(cli->outbuf, 0); /* Set bcc to zero. */
    776                 _smb_setlen_large(cli->outbuf,smb_size + 28 + 1 /* pad */ + size - 4);
    777         } else {
    778                 cli_setup_bcc(cli, p+size);
    779         }
    780 
    781         show_msg(cli->outbuf);
    782         if (direct_writes) {
    783                 /* For direct writes we now need to write the data
    784                  * directly out of buf. */
    785                 return cli_send_smb_direct_writeX(cli, buf, size);
    786         } else {
    787                 return cli_send_smb(cli);
    788         }
    789 }
    790 
    791 /****************************************************************************
    792   write to a file
    793   write_mode: 0x0001 disallow write cacheing
    794               0x0002 return bytes remaining
    795               0x0004 use raw named pipe protocol
    796               0x0008 start of message mode named pipe protocol
    797 ****************************************************************************/
    798 
    799 ssize_t cli_write(struct cli_state *cli,
    800                  uint16_t fnum, uint16 write_mode,
    801                  const char *buf, off_t offset, size_t size)
    802 {
    803         ssize_t bwritten = 0;
    804         unsigned int issued = 0;
    805         unsigned int received = 0;
    806         int mpx = 1;
    807         size_t writesize;
    808         int blocks;
    809 
    810         if(cli->max_mux > 1) {
    811                 mpx = cli->max_mux-1;
    812         } else {
    813                 mpx = 1;
    814         }
    815 
    816         writesize = cli_write_max_bufsize(cli, write_mode);
    817 
    818         blocks = (size + (writesize-1)) / writesize;
    819 
    820         while (received < blocks) {
    821 
    822                 while ((issued - received < mpx) && (issued < blocks)) {
    823                         ssize_t bsent = issued * writesize;
    824                         ssize_t size1 = MIN(writesize, size - bsent);
    825 
    826                         if (!cli_issue_write(cli, fnum, offset + bsent,
    827                                         write_mode,
    828                                         buf + bsent,
    829                                         size1))
    830                                 return -1;
    831                         issued++;
    832                 }
    833 
    834                 if (!cli_receive_smb(cli)) {
    835                         return bwritten;
    836                 }
    837 
    838                 received++;
    839 
    840                 if (cli_is_error(cli))
    841                         break;
    842 
    843                 bwritten += SVAL(cli->inbuf, smb_vwv2);
    844                 if (writesize > 0xFFFF) {
    845                         bwritten += (((int)(SVAL(cli->inbuf, smb_vwv4)))<<16);
    846                 }
    847         }
    848 
    849         while (received < issued && cli_receive_smb(cli)) {
    850                 received++;
    851         }
    852 
    853         return bwritten;
    854 }
    855 
    856 /****************************************************************************
    857713  write to a file using a SMBwrite and not bypassing 0 byte writes
    858714****************************************************************************/
    859715
    860 ssize_t cli_smbwrite(struct cli_state *cli,
    861                      uint16_t fnum, char *buf, off_t offset, size_t size1)
    862 {
    863         char *p;
     716NTSTATUS cli_smbwrite(struct cli_state *cli, uint16_t fnum, char *buf,
     717                      off_t offset, size_t size1, size_t *ptotal)
     718{
     719        uint8_t *bytes;
    864720        ssize_t total = 0;
     721
     722        /*
     723         * 3 bytes prefix
     724         */
     725
     726        bytes = TALLOC_ARRAY(talloc_tos(), uint8_t, 3);
     727        if (bytes == NULL) {
     728                return NT_STATUS_NO_MEMORY;
     729        }
     730        bytes[0] = 1;
    865731
    866732        do {
    867733                size_t size = MIN(size1, cli->max_xmit - 48);
    868 
    869                 memset(cli->outbuf,'\0',smb_size);
    870                 memset(cli->inbuf,'\0',smb_size);
    871 
    872                 cli_set_message(cli->outbuf,5, 0,True);
    873 
    874                 SCVAL(cli->outbuf,smb_com,SMBwrite);
    875                 SSVAL(cli->outbuf,smb_tid,cli->cnum);
    876                 cli_setup_packet(cli);
    877 
    878                 SSVAL(cli->outbuf,smb_vwv0,fnum);
    879                 SSVAL(cli->outbuf,smb_vwv1,size);
    880                 SIVAL(cli->outbuf,smb_vwv2,offset);
    881                 SSVAL(cli->outbuf,smb_vwv4,0);
    882 
    883                 p = smb_buf(cli->outbuf);
    884                 *p++ = 1;
    885                 SSVAL(p, 0, size); p += 2;
    886                 memcpy(p, buf + total, size); p += size;
    887 
    888                 cli_setup_bcc(cli, p);
    889 
    890                 if (!cli_send_smb(cli))
    891                         return -1;
    892 
    893                 if (!cli_receive_smb(cli))
    894                         return -1;
    895 
    896                 if (cli_is_error(cli))
    897                         return -1;
    898 
    899                 size = SVAL(cli->inbuf,smb_vwv0);
    900                 if (size == 0)
     734                struct tevent_req *req;
     735                uint16_t vwv[5];
     736                uint16_t *ret_vwv;
     737                NTSTATUS status;
     738
     739                SSVAL(vwv+0, 0, fnum);
     740                SSVAL(vwv+1, 0, size);
     741                SIVAL(vwv+2, 0, offset);
     742                SSVAL(vwv+4, 0, 0);
     743
     744                bytes = TALLOC_REALLOC_ARRAY(talloc_tos(), bytes, uint8_t,
     745                                             size+3);
     746                if (bytes == NULL) {
     747                        return NT_STATUS_NO_MEMORY;
     748                }
     749                SSVAL(bytes, 1, size);
     750                memcpy(bytes + 3, buf + total, size);
     751
     752                status = cli_smb(talloc_tos(), cli, SMBwrite, 0, 5, vwv,
     753                                 size+3, bytes, &req, 1, NULL, &ret_vwv,
     754                                 NULL, NULL);
     755                if (!NT_STATUS_IS_OK(status)) {
     756                        TALLOC_FREE(bytes);
     757                        return status;
     758                }
     759
     760                size = SVAL(ret_vwv+0, 0);
     761                TALLOC_FREE(req);
     762                if (size == 0) {
    901763                        break;
    902 
     764                }
    903765                size1 -= size;
    904766                total += size;
     
    907769        } while (size1);
    908770
    909         return total;
     771        TALLOC_FREE(bytes);
     772
     773        if (ptotal != NULL) {
     774                *ptotal = total;
     775        }
     776        return NT_STATUS_OK;
    910777}
    911778
     
    937804        bool bigoffset = ((cli->capabilities & CAP_LARGE_FILES) != 0);
    938805        uint8_t wct = bigoffset ? 14 : 12;
    939         size_t max_write = cli_write_max_bufsize(cli, mode);
     806        size_t max_write = cli_write_max_bufsize(cli, mode, wct);
    940807        uint16_t *vwv;
    941808
     
    1003870
    1004871        status = cli_smb_req_send(subreq);
    1005         if (!NT_STATUS_IS_OK(status)) {
    1006                 tevent_req_nterror(req, status);
     872        if (tevent_req_nterror(req, status)) {
    1007873                return tevent_req_post(req, ev);
    1008874        }
     
    1018884        uint8_t wct;
    1019885        uint16_t *vwv;
    1020         NTSTATUS status;
    1021 
    1022         status = cli_smb_recv(subreq, 6, &wct, &vwv, NULL, NULL);
     886        uint8_t *inbuf;
     887        NTSTATUS status;
     888
     889        status = cli_smb_recv(subreq, state, &inbuf, 6, &wct, &vwv,
     890                              NULL, NULL);
     891        TALLOC_FREE(subreq);
    1023892        if (NT_STATUS_IS_ERR(status)) {
    1024                 TALLOC_FREE(subreq);
    1025893                tevent_req_nterror(req, status);
    1026894                return;
     
    1102970        status = cli_write_andx_recv(subreq, &written);
    1103971        TALLOC_FREE(subreq);
    1104         if (!NT_STATUS_IS_OK(status)) {
    1105                 tevent_req_nterror(req, status);
     972        if (tevent_req_nterror(req, status)) {
    1106973                return;
    1107974        }
     
    1131998}
    1132999
    1133 static NTSTATUS cli_writeall_recv(struct tevent_req *req)
    1134 {
    1135         return tevent_req_simple_recv_ntstatus(req);
     1000static NTSTATUS cli_writeall_recv(struct tevent_req *req,
     1001                                  size_t *pwritten)
     1002{
     1003        struct cli_writeall_state *state = tevent_req_data(
     1004                req, struct cli_writeall_state);
     1005        NTSTATUS status;
     1006
     1007        if (tevent_req_is_nterror(req, &status)) {
     1008                return status;
     1009        }
     1010        if (pwritten != NULL) {
     1011                *pwritten = state->written;
     1012        }
     1013        return NT_STATUS_OK;
     1014}
     1015
     1016NTSTATUS cli_writeall(struct cli_state *cli, uint16_t fnum, uint16_t mode,
     1017                      const uint8_t *buf, off_t offset, size_t size,
     1018                      size_t *pwritten)
     1019{
     1020        TALLOC_CTX *frame = talloc_stackframe();
     1021        struct event_context *ev;
     1022        struct tevent_req *req;
     1023        NTSTATUS status = NT_STATUS_NO_MEMORY;
     1024
     1025        if (cli_has_async_calls(cli)) {
     1026                /*
     1027                 * Can't use sync call while an async call is in flight
     1028                 */
     1029                status = NT_STATUS_INVALID_PARAMETER;
     1030                goto fail;
     1031        }
     1032        ev = event_context_init(frame);
     1033        if (ev == NULL) {
     1034                goto fail;
     1035        }
     1036        req = cli_writeall_send(frame, ev, cli, fnum, mode, buf, offset, size);
     1037        if (req == NULL) {
     1038                goto fail;
     1039        }
     1040        if (!tevent_req_poll(req, ev)) {
     1041                status = map_nt_error_from_unix(errno);
     1042                goto fail;
     1043        }
     1044        status = cli_writeall_recv(req, pwritten);
     1045 fail:
     1046        TALLOC_FREE(frame);
     1047        if (!NT_STATUS_IS_OK(status)) {
     1048                cli_set_error(cli, status);
     1049        }
     1050        return status;
    11361051}
    11371052
     
    12451160        state->next_offset = start_offset;
    12461161
    1247         state->chunk_size = cli_write_max_bufsize(cli, mode);
     1162        state->chunk_size = cli_write_max_bufsize(cli, mode, 14);
    12481163
    12491164        if (window_size == 0) {
     
    12981213        state->pending -= 1;
    12991214
    1300         status = cli_writeall_recv(subreq);
     1215        status = cli_writeall_recv(subreq, NULL);
    13011216        TALLOC_FREE(subreq);
    13021217        TALLOC_FREE(substate);
    1303         if (!NT_STATUS_IS_OK(status)) {
    1304                 tevent_req_nterror(req, status);
     1218        if (tevent_req_nterror(req, status)) {
    13051219                return;
    13061220        }
Note: See TracChangeset for help on using the changeset viewer.