LCOV - code coverage report
Current view: top level - libcli/smb - smb1cli_write.c (source / functions) Hit Total Coverage
Test: coverage report for fix-15632 9995c5c2 Lines: 53 92 57.6 %
Date: 2024-04-13 12:30:31 Functions: 3 4 75.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Copyright (C) Gregor Beck 2013
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "includes.h"
      21             : #include "system/network.h"
      22             : #include "lib/util/tevent_ntstatus.h"
      23             : #include "smb_common.h"
      24             : #include "smbXcli_base.h"
      25             : 
      26             : struct smb1cli_writex_state {
      27             :         uint32_t size;
      28             :         uint16_t vwv[14];
      29             :         uint32_t written;
      30             :         uint16_t available;
      31             :         uint8_t pad;
      32             :         struct iovec iov[2];
      33             : };
      34             : 
      35             : static void smb1cli_writex_done(struct tevent_req *subreq);
      36             : 
      37             : /**
      38             :  * Send an asynchrounus SMB_COM_WRITE_ANDX request.
      39             :  * <a href="http://msdn.microsoft.com/en-us/library/ee441954.aspx">MS-CIFS 2.2.4.43.1</a>
      40             :  * @see smb1cli_writex_recv(), smb1cli_writex()
      41             :  *
      42             :  * @param[in] mem_ctx The memory context for the result.
      43             :  * @param[in] ev The event context to work on.
      44             :  * @param[in] conn The smb connection.
      45             :  * @param[in] timeout_msec If positive a timeout for the request.
      46             :  * @param[in] pid The process identifier
      47             :  * @param[in] tcon The smb tree connect.
      48             :  * @param[in] session The smb session.
      49             :  * @param[in] fnum The file id of the file the data should be written to.
      50             :  * @param[in] mode A bitfield containing the write mode.
      51             :  * @param[in] buf The data to be written to the file.
      52             :  * @param[in] offset The offset in bytes from the begin of file where to write.
      53             :  * @param[in] size The number of bytes to write.
      54             :  *
      55             :  * @return a tevent_req or NULL
      56             :  */
      57           8 : struct tevent_req *smb1cli_writex_send(TALLOC_CTX *mem_ctx,
      58             :                                        struct tevent_context *ev,
      59             :                                        struct smbXcli_conn *conn,
      60             :                                        uint32_t timeout_msec,
      61             :                                        uint32_t pid,
      62             :                                        struct smbXcli_tcon *tcon,
      63             :                                        struct smbXcli_session *session,
      64             :                                        uint16_t fnum,
      65             :                                        uint16_t mode,
      66             :                                        const uint8_t *buf,
      67             :                                        uint64_t offset,
      68             :                                        uint32_t size)
      69             : {
      70           0 :         struct tevent_req *req, *subreq;
      71           0 :         struct smb1cli_writex_state *state;
      72           8 :         bool bigoffset = ((smb1cli_conn_capabilities(conn) & CAP_LARGE_FILES) != 0);
      73           8 :         uint8_t wct = bigoffset ? 14 : 12;
      74           0 :         uint16_t *vwv;
      75           8 :         uint16_t data_offset =
      76           8 :                 smb1cli_req_wct_ofs(NULL, 0) /* reqs_before */
      77             :                 + 1                          /* the wct field */
      78           8 :                 + wct * 2                    /* vwv */
      79             :                 + 2                          /* num_bytes field */
      80             :                 + 1;                         /* pad */
      81           0 :         NTSTATUS status;
      82             : 
      83           8 :         req = tevent_req_create(mem_ctx, &state, struct smb1cli_writex_state);
      84           8 :         if (req == NULL) {
      85           0 :                 return NULL;
      86             :         }
      87             : 
      88           8 :         state->size = size;
      89             : 
      90           8 :         vwv = state->vwv;
      91             : 
      92           8 :         SCVAL(vwv+0, 0, 0xFF);
      93           8 :         SCVAL(vwv+0, 1, 0);
      94           8 :         SSVAL(vwv+1, 0, 0);
      95           8 :         SSVAL(vwv+2, 0, fnum);
      96           8 :         SIVAL(vwv+3, 0, offset);
      97           8 :         SIVAL(vwv+5, 0, 0);
      98           8 :         SSVAL(vwv+7, 0, mode);
      99           8 :         SSVAL(vwv+8, 0, 0);
     100           8 :         SSVAL(vwv+9, 0, (state->size>>16));
     101           8 :         SSVAL(vwv+10, 0, state->size);
     102           8 :         SSVAL(vwv+11, 0, data_offset);
     103             : 
     104           8 :         if (bigoffset) {
     105           8 :                 SIVAL(vwv+12, 0, (((uint64_t)offset)>>32) & 0xffffffff);
     106             :         }
     107             : 
     108           8 :         state->pad = 0;
     109           8 :         state->iov[0].iov_base = (void *)&state->pad;
     110           8 :         state->iov[0].iov_len = 1;
     111           8 :         state->iov[1].iov_base = discard_const_p(void, buf);
     112           8 :         state->iov[1].iov_len = state->size;
     113             : 
     114          16 :         subreq = smb1cli_req_create(state, ev, conn, SMBwriteX,
     115             :                                     0, 0, /* *_flags */
     116             :                                     0, 0, /* *_flags2 */
     117             :                                     timeout_msec, pid, tcon, session,
     118             :                                     wct, vwv,
     119           8 :                                     ARRAY_SIZE(state->iov), state->iov);
     120           8 :         if (tevent_req_nomem(subreq, req)) {
     121           0 :                 return tevent_req_post(req, ev);
     122             :         }
     123           8 :         tevent_req_set_callback(subreq, smb1cli_writex_done, req);
     124             : 
     125           8 :         status = smb1cli_req_chain_submit(&subreq, 1);
     126           8 :         if (tevent_req_nterror(req, status)) {
     127           0 :                 return tevent_req_post(req, ev);
     128             :         }
     129             : 
     130           8 :         return req;
     131             : }
     132             : 
     133           8 : static void smb1cli_writex_done(struct tevent_req *subreq)
     134             : {
     135           8 :         struct tevent_req *req = tevent_req_callback_data(
     136             :                 subreq, struct tevent_req);
     137           8 :         struct smb1cli_writex_state *state = tevent_req_data(
     138             :                 req, struct smb1cli_writex_state);
     139           8 :         struct iovec *recv_iov = NULL;
     140           0 :         uint8_t wct;
     141           0 :         uint16_t *vwv;
     142           0 :         NTSTATUS status;
     143           0 :         static const struct smb1cli_req_expected_response expected[] = {
     144             :         {
     145             :                 .status = NT_STATUS_OK,
     146             :                 .wct = 0x06
     147             :         },
     148             :         };
     149             : 
     150           8 :         status = smb1cli_req_recv(subreq, state,
     151             :                                   &recv_iov,
     152             :                                   NULL, /* phdr */
     153             :                                   &wct,
     154             :                                   &vwv,
     155             :                                   NULL, /* pvwv_offset */
     156             :                                   NULL, /* num_bytes */
     157             :                                   NULL, /* bytes */
     158             :                                   NULL, /* pbytes_offset */
     159             :                                   NULL, /* inbuf */
     160             :                                   expected, ARRAY_SIZE(expected));
     161           8 :         TALLOC_FREE(subreq);
     162           8 :         if (tevent_req_nterror(req, status)) {
     163           0 :                 return;
     164             :         }
     165             : 
     166           8 :         state->written = SVAL(vwv+2, 0);
     167           8 :         if (state->size > UINT16_MAX) {
     168             :                 /*
     169             :                  * It is important that we only set the
     170             :                  * high bits only if we asked for a large write.
     171             :                  *
     172             :                  * OS/2 print shares get this wrong and may send
     173             :                  * invalid values.
     174             :                  *
     175             :                  * See bug #5326.
     176             :                  */
     177           0 :                 state->written |= SVAL(vwv+4, 0)<<16;
     178             :         }
     179           8 :         state->available = SVAL(vwv+3, 0);
     180             : 
     181           8 :         tevent_req_done(req);
     182             : }
     183             : 
     184             : /**
     185             :  * Receive the response to an asynchronous SMB_COM_WRITE_ANDX request.
     186             :  * <a href="http://msdn.microsoft.com/en-us/library/ee441673.aspx">MS-CIFS:2.2.4.43.2</a>
     187             :  *
     188             :  *
     189             :  * @param[in] req req A tevent request created with smb1cli_writex_send()
     190             :  * @param[out] pwritten The number of bytes written to the file.
     191             :  * @param[out] pavailable Valid if writing to a named pipe or IO device.
     192             :  *
     193             :  * @return NT_STATUS_OK on success.
     194             :  */
     195           8 : NTSTATUS smb1cli_writex_recv(struct tevent_req *req, uint32_t *pwritten, uint16_t *pavailable)
     196             : {
     197           8 :         struct smb1cli_writex_state *state = tevent_req_data(
     198             :                 req, struct smb1cli_writex_state);
     199           0 :         NTSTATUS status;
     200             : 
     201           8 :         if (tevent_req_is_nterror(req, &status)) {
     202           0 :                 return status;
     203             :         }
     204           8 :         if (pwritten != NULL) {
     205           8 :                 *pwritten = state->written;
     206             :         }
     207           8 :         if (pavailable != NULL) {
     208           0 :                 *pavailable = state->available;
     209             :         }
     210           8 :         return NT_STATUS_OK;
     211             : }
     212             : 
     213             : /**
     214             :  * Send an synchrounus SMB_COM_WRITE_ANDX request.
     215             :  * <a href="http://msdn.microsoft.com/en-us/library/ee441848.aspx">MS-CIFS 2.2.4.43</a>
     216             :  * @see smb1cli_writex_send(), smb1cli_writex_recv()
     217             :  *
     218             :  * @param[in] conn The smb connection.
     219             :  * @param[in] timeout_msec If positive a timeout for the request.
     220             :  * @param[in] pid The process identifier
     221             :  * @param[in] tcon The smb tree connect.
     222             :  * @param[in] session The smb session.
     223             :  * @param[in] fnum The file id of the file the data should be written to.
     224             :  * @param[in] mode A bitfield containing the write mode.
     225             :  * @param[in] buf The data to be written to the file.
     226             :  * @param[in] offset The offset in bytes from the begin of file where to write.
     227             :  * @param[in] size The number of bytes to write.
     228             :  * @param[out] pwritten The number of bytes written to the file.
     229             :  * @param[out] pavailable Valid if writing to a named pipe or IO device.
     230             :  *
     231             :  * @return NT_STATUS_OK on success.
     232             :  */
     233           0 : NTSTATUS smb1cli_writex(struct smbXcli_conn *conn,
     234             :                         uint32_t timeout_msec,
     235             :                         uint32_t pid,
     236             :                         struct smbXcli_tcon *tcon,
     237             :                         struct smbXcli_session *session,
     238             :                         uint16_t fnum,
     239             :                         uint16_t mode,
     240             :                         const uint8_t *buf,
     241             :                         uint64_t offset,
     242             :                         uint32_t size,
     243             :                         uint32_t *pwritten,
     244             :                         uint16_t *pavailable)
     245             : {
     246           0 :         TALLOC_CTX *frame = NULL;
     247           0 :         struct tevent_context *ev;
     248           0 :         struct tevent_req *req;
     249           0 :         NTSTATUS status = NT_STATUS_OK;
     250             : 
     251           0 :         frame = talloc_stackframe();
     252             : 
     253           0 :         if (smbXcli_conn_has_async_calls(conn)) {
     254             :                 /*
     255             :                  * Can't use sync call while an async call is in flight
     256             :                  */
     257           0 :                 status = NT_STATUS_INVALID_PARAMETER;
     258           0 :                 goto done;
     259             :         }
     260             : 
     261           0 :         ev = samba_tevent_context_init(frame);
     262           0 :         if (ev == NULL) {
     263           0 :                 status = NT_STATUS_NO_MEMORY;
     264           0 :                 goto done;
     265             :         }
     266             : 
     267           0 :         req = smb1cli_writex_send(frame, ev, conn,
     268             :                                   timeout_msec,
     269             :                                   pid, tcon, session,
     270             :                                   fnum, mode, buf, offset, size);
     271           0 :         if (req == NULL) {
     272           0 :                 status = NT_STATUS_NO_MEMORY;
     273           0 :                 goto done;
     274             :         }
     275             : 
     276           0 :         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     277           0 :                 goto done;
     278             :         }
     279             : 
     280           0 :         status = smb1cli_writex_recv(req, pwritten, pavailable);
     281           0 : done:
     282           0 :         TALLOC_FREE(frame);
     283           0 :         return status;
     284             : }

Generated by: LCOV version 1.14