LCOV - code coverage report
Current view: top level - source4/torture/raw - write.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 423 499 84.8 %
Date: 2024-04-21 15:09:00 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    test suite for various write operations
       4             : 
       5             :    Copyright (C) Andrew Tridgell 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 "system/time.h"
      24             : #include "system/filesys.h"
      25             : #include "libcli/libcli.h"
      26             : #include "torture/util.h"
      27             : #include "torture/raw/proto.h"
      28             : #include "libcli/raw/raw_proto.h"
      29             : 
      30             : #define CHECK_STATUS(status, correct) do { \
      31             :         if (!NT_STATUS_EQUAL(status, correct)) { \
      32             :                 torture_fail(tctx, talloc_asprintf(tctx, "(%s) Incorrect status %s - should be %s\n", \
      33             :                        __location__, nt_errstr(status), nt_errstr(correct))); \
      34             :                 ret = false; \
      35             :                 goto done; \
      36             :         }} while (0)
      37             : 
      38             : #define CHECK_VALUE(v, correct) do { \
      39             :         if ((v) != (correct)) { \
      40             :                 torture_fail(tctx, talloc_asprintf(tctx, "(%s) Incorrect value %s=%d - should be %d\n", \
      41             :                        __location__, #v, v, correct)); \
      42             :                 ret = false; \
      43             :                 goto done; \
      44             :         }} while (0)
      45             : 
      46             : #define CHECK_BUFFER(buf, seed, len) do { \
      47             :         if (!check_buffer(tctx, buf, seed, len, __location__)) { \
      48             :                 ret = false; \
      49             :                 goto done; \
      50             :         }} while (0)
      51             : 
      52             : #define CHECK_ALL_INFO(v, field) do { \
      53             :         finfo.all_info.level = RAW_FILEINFO_ALL_INFO; \
      54             :         finfo.all_info.in.file.path = fname; \
      55             :         status = smb_raw_pathinfo(cli->tree, tctx, &finfo); \
      56             :         CHECK_STATUS(status, NT_STATUS_OK); \
      57             :         if ((v) != finfo.all_info.out.field) { \
      58             :                 torture_comment(tctx, "(%s) wrong value for field %s  %.0f - %.0f\n", \
      59             :                        __location__, #field, (double)v, (double)finfo.all_info.out.field); \
      60             :                 dump_all_info(tctx, &finfo); \
      61             :                 ret = false; \
      62             :         }} while (0)
      63             : 
      64             : 
      65             : #define BASEDIR "\\testwrite"
      66             : 
      67             : 
      68             : /*
      69             :   setup a random buffer based on a seed
      70             : */
      71          90 : static void setup_buffer(uint8_t *buf, unsigned int seed, int len)
      72             : {
      73          15 :         int i;
      74          90 :         srandom(seed);
      75     8100105 :         for (i=0;i<len;i++) buf[i] = random();
      76          90 : }
      77             : 
      78             : /*
      79             :   check a random buffer based on a seed
      80             : */
      81          84 : static bool check_buffer(struct torture_context *tctx,
      82             :                          uint8_t *buf, unsigned int seed, int len, const char *location)
      83             : {
      84          14 :         int i;
      85          84 :         srandom(seed);
      86      192422 :         for (i=0;i<len;i++) {
      87      192324 :                 uint8_t v = random();
      88      192324 :                 if (buf[i] != v) {
      89           0 :                         torture_fail(tctx, talloc_asprintf(tctx, "Buffer incorrect at %s! ofs=%d buf=0x%x correct=0x%x\n",
      90             :                                location, i, buf[i], v));
      91             :                         return false;
      92             :                 }
      93             :         }
      94          70 :         return true;
      95             : }
      96             : 
      97             : /*
      98             :   test write ops
      99             : */
     100           6 : static bool test_write(struct torture_context *tctx,
     101             :                        struct smbcli_state *cli)
     102             : {
     103           1 :         union smb_write io;
     104           1 :         NTSTATUS status;
     105           6 :         bool ret = true;
     106           1 :         int fnum;
     107           1 :         uint8_t *buf;
     108           6 :         const int maxsize = 90000;
     109           6 :         const char *fname = BASEDIR "\\test.txt";
     110           6 :         unsigned int seed = time(NULL);
     111           1 :         union smb_fileinfo finfo;
     112             : 
     113           6 :         buf = talloc_zero_array(tctx, uint8_t, maxsize);
     114             : 
     115           6 :         if (!torture_setup_dir(cli, BASEDIR)) {
     116           0 :                 torture_fail(tctx, "failed to setup basedir");
     117             :         }
     118             : 
     119           6 :         torture_comment(tctx, "Testing RAW_WRITE_WRITE\n");
     120           6 :         io.generic.level = RAW_WRITE_WRITE;
     121             : 
     122           6 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
     123           6 :         if (fnum == -1) {
     124           0 :                 ret = false;
     125           0 :                 torture_fail_goto(tctx, done,
     126             :                         talloc_asprintf(tctx, "Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree)));
     127             :         }
     128             : 
     129           6 :         torture_comment(tctx, "Trying zero write\n");
     130           6 :         io.write.in.file.fnum = fnum;
     131           6 :         io.write.in.count = 0;
     132           6 :         io.write.in.offset = 0;
     133           6 :         io.write.in.remaining = 0;
     134           6 :         io.write.in.data = buf;
     135           6 :         status = smb_raw_write(cli->tree, &io);
     136           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     137           6 :         CHECK_VALUE(io.write.out.nwritten, 0);
     138             : 
     139           6 :         setup_buffer(buf, seed, maxsize);
     140             : 
     141           6 :         torture_comment(tctx, "Trying small write\n");
     142           6 :         io.write.in.count = 9;
     143           6 :         io.write.in.offset = 4;
     144           6 :         io.write.in.data = buf;
     145           6 :         status = smb_raw_write(cli->tree, &io);
     146           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     147           6 :         CHECK_VALUE(io.write.out.nwritten, io.write.in.count);
     148             : 
     149           6 :         memset(buf, 0, maxsize);
     150           6 :         if (smbcli_read(cli->tree, fnum, buf, 0, 13) != 13) {
     151           0 :                 ret = false;
     152           0 :                 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "read failed at %s\n", __location__));
     153             :         }
     154           6 :         CHECK_BUFFER(buf+4, seed, 9);
     155           6 :         CHECK_VALUE(IVAL(buf,0), 0);
     156             : 
     157           6 :         setup_buffer(buf, seed, maxsize);
     158             : 
     159           6 :         torture_comment(tctx, "Trying large write\n");
     160           6 :         io.write.in.count = 4000;
     161           6 :         io.write.in.offset = 0;
     162           6 :         io.write.in.data = buf;
     163           6 :         status = smb_raw_write(cli->tree, &io);
     164           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     165           6 :         CHECK_VALUE(io.write.out.nwritten, 4000);
     166             : 
     167           6 :         memset(buf, 0, maxsize);
     168           6 :         if (smbcli_read(cli->tree, fnum, buf, 0, 4000) != 4000) {
     169           0 :                 ret = false;
     170           0 :                 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "read failed at %s\n", __location__));
     171             :         }
     172           6 :         CHECK_BUFFER(buf, seed, 4000);
     173             : 
     174           6 :         torture_comment(tctx, "Trying bad fnum\n");
     175           6 :         io.write.in.file.fnum = fnum+1;
     176           6 :         io.write.in.count = 4000;
     177           6 :         io.write.in.offset = 0;
     178           6 :         io.write.in.data = buf;
     179           6 :         status = smb_raw_write(cli->tree, &io);
     180           6 :         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
     181             : 
     182           6 :         torture_comment(tctx, "Setting file as sparse\n");
     183           6 :         status = torture_set_sparse(cli->tree, fnum);
     184           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     185             : 
     186           6 :         if (!(cli->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
     187           0 :                 torture_comment(tctx, "skipping large file tests - CAP_LARGE_FILES not set\n");
     188           0 :                 goto done;
     189             :         }
     190             : 
     191           6 :         torture_comment(tctx, "Trying 2^32 offset\n");
     192           6 :         setup_buffer(buf, seed, maxsize);
     193           6 :         io.write.in.file.fnum = fnum;
     194           6 :         io.write.in.count = 4000;
     195           6 :         io.write.in.offset = 0xFFFFFFFF - 2000;
     196           6 :         io.write.in.data = buf;
     197           6 :         status = smb_raw_write(cli->tree, &io);
     198           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     199           6 :         CHECK_VALUE(io.write.out.nwritten, 4000);
     200           6 :         CHECK_ALL_INFO(io.write.in.count + (uint64_t)io.write.in.offset, size);
     201             : 
     202           6 :         memset(buf, 0, maxsize);
     203           6 :         if (smbcli_read(cli->tree, fnum, buf, io.write.in.offset, 4000) != 4000) {
     204           0 :                 ret = false;
     205           0 :                 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "read failed at %s\n", __location__));
     206             :         }
     207           6 :         CHECK_BUFFER(buf, seed, 4000);
     208             : 
     209           6 : done:
     210           6 :         smbcli_close(cli->tree, fnum);
     211           6 :         smb_raw_exit(cli->session);
     212           6 :         smbcli_deltree(cli->tree, BASEDIR);
     213           6 :         return ret;
     214             : }
     215             : 
     216             : 
     217             : /*
     218             :   test writex ops
     219             : */
     220           6 : static bool test_writex(struct torture_context *tctx,
     221             :                         struct smbcli_state *cli)
     222             : {
     223           1 :         union smb_write io;
     224           1 :         NTSTATUS status;
     225           6 :         bool ret = true;
     226           1 :         int fnum, i;
     227           1 :         uint8_t *buf;
     228           6 :         const int maxsize = 90000;
     229           6 :         const char *fname = BASEDIR "\\test.txt";
     230           6 :         unsigned int seed = time(NULL);
     231           1 :         union smb_fileinfo finfo;
     232           6 :         int max_bits=63;
     233             : 
     234           6 :         if (!torture_setting_bool(tctx, "dangerous", false)) {
     235           6 :                 max_bits=33;
     236           6 :                 torture_comment(tctx, "dangerous not set - limiting range of test to 2^%d\n", max_bits);
     237             :         }
     238             : 
     239           6 :         buf = talloc_zero_array(tctx, uint8_t, maxsize);
     240             : 
     241           6 :         if (!cli->transport->negotiate.lockread_supported) {
     242           0 :                 torture_comment(tctx, "Server does not support writeunlock - skipping\n");
     243           0 :                 return true;
     244             :         }
     245             : 
     246           6 :         if (!torture_setup_dir(cli, BASEDIR)) {
     247           0 :                 torture_fail(tctx, "failed to setup basedir");
     248             :         }
     249             : 
     250           6 :         torture_comment(tctx, "Testing RAW_WRITE_WRITEX\n");
     251           6 :         io.generic.level = RAW_WRITE_WRITEX;
     252             : 
     253           6 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
     254           6 :         if (fnum == -1) {
     255           0 :                 ret = false;
     256           0 :                 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree)));
     257             :         }
     258             : 
     259           6 :         torture_comment(tctx, "Trying zero write\n");
     260           6 :         io.writex.in.file.fnum = fnum;
     261           6 :         io.writex.in.offset = 0;
     262           6 :         io.writex.in.wmode = 0;
     263           6 :         io.writex.in.remaining = 0;
     264           6 :         io.writex.in.count = 0;
     265           6 :         io.writex.in.data = buf;
     266           6 :         status = smb_raw_write(cli->tree, &io);
     267           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     268           6 :         CHECK_VALUE(io.writex.out.nwritten, 0);
     269             : 
     270           6 :         setup_buffer(buf, seed, maxsize);
     271             : 
     272           6 :         torture_comment(tctx, "Trying small write\n");
     273           6 :         io.writex.in.count = 9;
     274           6 :         io.writex.in.offset = 4;
     275           6 :         io.writex.in.data = buf;
     276           6 :         status = smb_raw_write(cli->tree, &io);
     277           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     278           6 :         CHECK_VALUE(io.writex.out.nwritten, io.writex.in.count);
     279             : 
     280           6 :         memset(buf, 0, maxsize);
     281           6 :         if (smbcli_read(cli->tree, fnum, buf, 0, 13) != 13) {
     282           0 :                 ret = false;
     283           0 :                 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "read failed at %s\n", __location__));
     284             :         }
     285           6 :         CHECK_BUFFER(buf+4, seed, 9);
     286           6 :         CHECK_VALUE(IVAL(buf,0), 0);
     287             : 
     288           6 :         setup_buffer(buf, seed, maxsize);
     289             : 
     290           6 :         torture_comment(tctx, "Trying large write\n");
     291           6 :         io.writex.in.count = 4000;
     292           6 :         io.writex.in.offset = 0;
     293           6 :         io.writex.in.data = buf;
     294           6 :         status = smb_raw_write(cli->tree, &io);
     295           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     296           6 :         CHECK_VALUE(io.writex.out.nwritten, 4000);
     297             : 
     298           6 :         memset(buf, 0, maxsize);
     299           6 :         if (smbcli_read(cli->tree, fnum, buf, 0, 4000) != 4000) {
     300           0 :                 ret = false;
     301           0 :                 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "read failed at %s\n", __location__));
     302             :         }
     303           6 :         CHECK_BUFFER(buf, seed, 4000);
     304             : 
     305           6 :         torture_comment(tctx, "Trying bad fnum\n");
     306           6 :         io.writex.in.file.fnum = fnum+1;
     307           6 :         io.writex.in.count = 4000;
     308           6 :         io.writex.in.offset = 0;
     309           6 :         io.writex.in.data = buf;
     310           6 :         status = smb_raw_write(cli->tree, &io);
     311           6 :         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
     312             : 
     313           6 :         torture_comment(tctx, "Testing wmode\n");
     314           6 :         io.writex.in.file.fnum = fnum;
     315           6 :         io.writex.in.count = 1;
     316           6 :         io.writex.in.offset = 0;
     317           6 :         io.writex.in.wmode = 1;
     318           6 :         io.writex.in.data = buf;
     319           6 :         status = smb_raw_write(cli->tree, &io);
     320           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     321           6 :         CHECK_VALUE(io.writex.out.nwritten, io.writex.in.count);
     322             : 
     323           6 :         io.writex.in.wmode = 2;
     324           6 :         status = smb_raw_write(cli->tree, &io);
     325           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     326           6 :         CHECK_VALUE(io.writex.out.nwritten, io.writex.in.count);
     327             : 
     328             : 
     329           6 :         torture_comment(tctx, "Trying locked region\n");
     330           6 :         cli->session->pid++;
     331           6 :         if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum, 3, 1, 0, WRITE_LOCK))) {
     332           0 :                 ret = false;
     333           0 :                 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "Failed to lock file at %s\n", __location__));
     334             :         }
     335           6 :         cli->session->pid--;
     336           6 :         io.writex.in.wmode = 0;
     337           6 :         io.writex.in.count = 4;
     338           6 :         io.writex.in.offset = 0;
     339           6 :         status = smb_raw_write(cli->tree, &io);
     340           6 :         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
     341             : 
     342           6 :         torture_comment(tctx, "Setting file as sparse\n");
     343           6 :         status = torture_set_sparse(cli->tree, fnum);
     344           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     345             : 
     346           6 :         if (!(cli->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
     347           0 :                 torture_skip(tctx, "skipping large file tests - CAP_LARGE_FILES not set\n");
     348             :         }
     349             : 
     350           6 :         torture_comment(tctx, "Trying 2^32 offset\n");
     351           6 :         setup_buffer(buf, seed, maxsize);
     352           6 :         io.writex.in.file.fnum = fnum;
     353           6 :         io.writex.in.count = 4000;
     354           6 :         io.writex.in.offset = 0xFFFFFFFF - 2000;
     355           6 :         io.writex.in.data = buf;
     356           6 :         status = smb_raw_write(cli->tree, &io);
     357           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     358           6 :         CHECK_VALUE(io.writex.out.nwritten, 4000);
     359           6 :         CHECK_ALL_INFO(io.writex.in.count + (uint64_t)io.writex.in.offset, size);
     360             : 
     361           6 :         memset(buf, 0, maxsize);
     362           6 :         if (smbcli_read(cli->tree, fnum, buf, io.writex.in.offset, 4000) != 4000) {
     363           0 :                 ret = false;
     364           0 :                 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "read failed at %s\n", __location__));
     365             :         }
     366           6 :         CHECK_BUFFER(buf, seed, 4000);
     367             : 
     368           6 :         for (i=33;i<max_bits;i++) {
     369           0 :                 torture_comment(tctx, "Trying 2^%d offset\n", i);
     370           0 :                 setup_buffer(buf, seed+1, maxsize);
     371           0 :                 io.writex.in.file.fnum = fnum;
     372           0 :                 io.writex.in.count = 4000;
     373           0 :                 io.writex.in.offset = ((uint64_t)1) << i;
     374           0 :                 io.writex.in.data = buf;
     375           0 :                 status = smb_raw_write(cli->tree, &io);
     376           0 :                 if (i>33 &&
     377           0 :                     NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
     378           0 :                         break;
     379             :                 }
     380           0 :                 CHECK_STATUS(status, NT_STATUS_OK);
     381           0 :                 CHECK_VALUE(io.writex.out.nwritten, 4000);
     382           0 :                 CHECK_ALL_INFO(io.writex.in.count + (uint64_t)io.writex.in.offset, size);
     383             : 
     384           0 :                 memset(buf, 0, maxsize);
     385           0 :                 if (smbcli_read(cli->tree, fnum, buf, io.writex.in.offset, 4000) != 4000) {
     386           0 :                         ret = false;
     387           0 :                         torture_fail_goto(tctx, done, talloc_asprintf(tctx, "read failed at %s\n", __location__));
     388             :                 }
     389           0 :                 CHECK_BUFFER(buf, seed+1, 4000);
     390             :         }
     391           6 :         torture_comment(tctx, "limit is 2^%d\n", i);
     392             : 
     393           6 :         setup_buffer(buf, seed, maxsize);
     394             : 
     395           6 : done:
     396           6 :         smbcli_close(cli->tree, fnum);
     397           6 :         smb_raw_exit(cli->session);
     398           6 :         smbcli_deltree(cli->tree, BASEDIR);
     399           6 :         return ret;
     400             : }
     401             : 
     402             : 
     403             : /*
     404             :   test write unlock ops
     405             : */
     406           6 : static bool test_writeunlock(struct torture_context *tctx,
     407             :                              struct smbcli_state *cli)
     408             : {
     409           1 :         union smb_write io;
     410           1 :         NTSTATUS status;
     411           6 :         bool ret = true;
     412           1 :         int fnum;
     413           1 :         uint8_t *buf;
     414           6 :         const int maxsize = 90000;
     415           6 :         const char *fname = BASEDIR "\\test.txt";
     416           6 :         unsigned int seed = time(NULL);
     417           1 :         union smb_fileinfo finfo;
     418             : 
     419           6 :         buf = talloc_zero_array(tctx, uint8_t, maxsize);
     420             : 
     421           6 :         if (!cli->transport->negotiate.lockread_supported) {
     422           0 :                 torture_skip(tctx, "Server does not support writeunlock - skipping\n");
     423             :         }
     424             : 
     425           6 :         if (!torture_setup_dir(cli, BASEDIR)) {
     426           0 :                 torture_fail(tctx, "failed to setup basedir");
     427             :         }
     428             : 
     429           6 :         torture_comment(tctx, "Testing RAW_WRITE_WRITEUNLOCK\n");
     430           6 :         io.generic.level = RAW_WRITE_WRITEUNLOCK;
     431             : 
     432           6 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
     433           6 :         if (fnum == -1) {
     434           0 :                 ret = false;
     435           0 :                 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree)));
     436             :         }
     437             : 
     438           6 :         torture_comment(tctx, "Trying zero write\n");
     439           6 :         io.writeunlock.in.file.fnum = fnum;
     440           6 :         io.writeunlock.in.count = 0;
     441           6 :         io.writeunlock.in.offset = 0;
     442           6 :         io.writeunlock.in.remaining = 0;
     443           6 :         io.writeunlock.in.data = buf;
     444           6 :         status = smb_raw_write(cli->tree, &io);
     445           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     446           6 :         CHECK_VALUE(io.writeunlock.out.nwritten, io.writeunlock.in.count);
     447             : 
     448           6 :         setup_buffer(buf, seed, maxsize);
     449             : 
     450           6 :         torture_comment(tctx, "Trying small write\n");
     451           6 :         io.writeunlock.in.count = 9;
     452           6 :         io.writeunlock.in.offset = 4;
     453           6 :         io.writeunlock.in.data = buf;
     454           6 :         status = smb_raw_write(cli->tree, &io);
     455           6 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     456           6 :         if (smbcli_read(cli->tree, fnum, buf, 0, 13) != 13) {
     457           0 :                 ret = false;
     458           0 :                 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "read failed at %s\n", __location__));
     459             :         }
     460           6 :         CHECK_BUFFER(buf+4, seed, 9);
     461           6 :         CHECK_VALUE(IVAL(buf,0), 0);
     462             : 
     463           6 :         setup_buffer(buf, seed, maxsize);
     464           6 :         smbcli_lock(cli->tree, fnum, io.writeunlock.in.offset, io.writeunlock.in.count,
     465             :                  0, WRITE_LOCK);
     466           6 :         status = smb_raw_write(cli->tree, &io);
     467           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     468           6 :         CHECK_VALUE(io.writeunlock.out.nwritten, io.writeunlock.in.count);
     469             : 
     470           6 :         memset(buf, 0, maxsize);
     471           6 :         if (smbcli_read(cli->tree, fnum, buf, 0, 13) != 13) {
     472           0 :                 ret = false;
     473           0 :                 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "read failed at %s\n", __location__));
     474             :         }
     475           6 :         CHECK_BUFFER(buf+4, seed, 9);
     476           6 :         CHECK_VALUE(IVAL(buf,0), 0);
     477             : 
     478           6 :         setup_buffer(buf, seed, maxsize);
     479             : 
     480           6 :         torture_comment(tctx, "Trying large write\n");
     481           6 :         io.writeunlock.in.count = 4000;
     482           6 :         io.writeunlock.in.offset = 0;
     483           6 :         io.writeunlock.in.data = buf;
     484           6 :         smbcli_lock(cli->tree, fnum, io.writeunlock.in.offset, io.writeunlock.in.count,
     485             :                  0, WRITE_LOCK);
     486           6 :         status = smb_raw_write(cli->tree, &io);
     487           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     488           6 :         CHECK_VALUE(io.writeunlock.out.nwritten, 4000);
     489             : 
     490           6 :         status = smb_raw_write(cli->tree, &io);
     491           6 :         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
     492             : 
     493           6 :         memset(buf, 0, maxsize);
     494           6 :         if (smbcli_read(cli->tree, fnum, buf, 0, 4000) != 4000) {
     495           0 :                 ret = false;
     496           0 :                 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "read failed at %s\n", __location__));
     497             :         }
     498           6 :         CHECK_BUFFER(buf, seed, 4000);
     499             : 
     500           6 :         torture_comment(tctx, "Trying bad fnum\n");
     501           6 :         io.writeunlock.in.file.fnum = fnum+1;
     502           6 :         io.writeunlock.in.count = 4000;
     503           6 :         io.writeunlock.in.offset = 0;
     504           6 :         io.writeunlock.in.data = buf;
     505           6 :         status = smb_raw_write(cli->tree, &io);
     506           6 :         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
     507             : 
     508           6 :         torture_comment(tctx, "Setting file as sparse\n");
     509           6 :         status = torture_set_sparse(cli->tree, fnum);
     510           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     511             : 
     512           6 :         if (!(cli->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
     513           0 :                 torture_skip(tctx, "skipping large file tests - CAP_LARGE_FILES not set\n");
     514             :         }
     515             : 
     516           6 :         torture_comment(tctx, "Trying 2^32 offset\n");
     517           6 :         setup_buffer(buf, seed, maxsize);
     518           6 :         io.writeunlock.in.file.fnum = fnum;
     519           6 :         io.writeunlock.in.count = 4000;
     520           6 :         io.writeunlock.in.offset = 0xFFFFFFFF - 2000;
     521           6 :         io.writeunlock.in.data = buf;
     522           6 :         smbcli_lock(cli->tree, fnum, io.writeunlock.in.offset, io.writeunlock.in.count,
     523             :                  0, WRITE_LOCK);
     524           6 :         status = smb_raw_write(cli->tree, &io);
     525           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     526           6 :         CHECK_VALUE(io.writeunlock.out.nwritten, 4000);
     527           6 :         CHECK_ALL_INFO(io.writeunlock.in.count + (uint64_t)io.writeunlock.in.offset, size);
     528             : 
     529           6 :         memset(buf, 0, maxsize);
     530           6 :         if (smbcli_read(cli->tree, fnum, buf, io.writeunlock.in.offset, 4000) != 4000) {
     531           0 :                 ret = false;
     532           0 :                 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "read failed at %s\n", __location__));
     533             :         }
     534           6 :         CHECK_BUFFER(buf, seed, 4000);
     535             : 
     536           6 : done:
     537           6 :         smbcli_close(cli->tree, fnum);
     538           6 :         smb_raw_exit(cli->session);
     539           6 :         smbcli_deltree(cli->tree, BASEDIR);
     540           6 :         return ret;
     541             : }
     542             : 
     543             : 
     544             : /*
     545             :   test write close ops
     546             : */
     547           6 : static bool test_writeclose(struct torture_context *tctx,
     548             :                             struct smbcli_state *cli)
     549             : {
     550           1 :         union smb_write io;
     551           1 :         NTSTATUS status;
     552           6 :         bool ret = true;
     553           1 :         int fnum;
     554           1 :         uint8_t *buf;
     555           6 :         const int maxsize = 90000;
     556           6 :         const char *fname = BASEDIR "\\test.txt";
     557           6 :         unsigned int seed = time(NULL);
     558           1 :         union smb_fileinfo finfo;
     559             : 
     560           6 :         buf = talloc_zero_array(tctx, uint8_t, maxsize);
     561             : 
     562           6 :         if (!torture_setting_bool(tctx, "writeclose_support", true)) {
     563           0 :                 torture_skip(tctx, "Server does not support writeclose - skipping\n");
     564             :         }
     565             : 
     566           6 :         if (!torture_setup_dir(cli, BASEDIR)) {
     567           0 :                 torture_fail(tctx, "failed to setup basedir");
     568             :         }
     569             : 
     570           6 :         torture_comment(tctx, "Testing RAW_WRITE_WRITECLOSE\n");
     571           6 :         io.generic.level = RAW_WRITE_WRITECLOSE;
     572             : 
     573           6 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
     574           6 :         if (fnum == -1) {
     575           0 :                 ret = false;
     576           0 :                 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree)));
     577             :         }
     578             : 
     579           6 :         torture_comment(tctx, "Trying zero write\n");
     580           6 :         io.writeclose.in.file.fnum = fnum;
     581           6 :         io.writeclose.in.count = 0;
     582           6 :         io.writeclose.in.offset = 0;
     583           6 :         io.writeclose.in.mtime = 0;
     584           6 :         io.writeclose.in.data = buf;
     585           6 :         status = smb_raw_write(cli->tree, &io);
     586           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     587           6 :         CHECK_VALUE(io.writeclose.out.nwritten, io.writeclose.in.count);
     588             : 
     589           6 :         status = smb_raw_write(cli->tree, &io);
     590           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     591           6 :         CHECK_VALUE(io.writeclose.out.nwritten, io.writeclose.in.count);
     592             : 
     593           6 :         setup_buffer(buf, seed, maxsize);
     594             : 
     595           6 :         torture_comment(tctx, "Trying small write\n");
     596           6 :         io.writeclose.in.count = 9;
     597           6 :         io.writeclose.in.offset = 4;
     598           6 :         io.writeclose.in.data = buf;
     599           6 :         status = smb_raw_write(cli->tree, &io);
     600           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     601             : 
     602           6 :         status = smb_raw_write(cli->tree, &io);
     603           6 :         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
     604             : 
     605           6 :         fnum = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
     606           6 :         io.writeclose.in.file.fnum = fnum;
     607             : 
     608           6 :         if (smbcli_read(cli->tree, fnum, buf, 0, 13) != 13) {
     609           0 :                 ret = false;
     610           0 :                 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "read failed at %s\n", __location__));
     611             :         }
     612           6 :         CHECK_BUFFER(buf+4, seed, 9);
     613           6 :         CHECK_VALUE(IVAL(buf,0), 0);
     614             : 
     615           6 :         setup_buffer(buf, seed, maxsize);
     616           6 :         status = smb_raw_write(cli->tree, &io);
     617           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     618           6 :         CHECK_VALUE(io.writeclose.out.nwritten, io.writeclose.in.count);
     619             : 
     620           6 :         fnum = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
     621           6 :         io.writeclose.in.file.fnum = fnum;
     622             : 
     623           6 :         memset(buf, 0, maxsize);
     624           6 :         if (smbcli_read(cli->tree, fnum, buf, 0, 13) != 13) {
     625           0 :                 ret = false;
     626           0 :                 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "read failed at %s\n", __location__));
     627             :         }
     628           6 :         CHECK_BUFFER(buf+4, seed, 9);
     629           6 :         CHECK_VALUE(IVAL(buf,0), 0);
     630             : 
     631           6 :         setup_buffer(buf, seed, maxsize);
     632             : 
     633           6 :         torture_comment(tctx, "Trying large write\n");
     634           6 :         io.writeclose.in.count = 4000;
     635           6 :         io.writeclose.in.offset = 0;
     636           6 :         io.writeclose.in.data = buf;
     637           6 :         status = smb_raw_write(cli->tree, &io);
     638           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     639           6 :         CHECK_VALUE(io.writeclose.out.nwritten, 4000);
     640             : 
     641           6 :         status = smb_raw_write(cli->tree, &io);
     642           6 :         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
     643             : 
     644           6 :         fnum = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
     645           6 :         io.writeclose.in.file.fnum = fnum;
     646             : 
     647           6 :         memset(buf, 0, maxsize);
     648           6 :         if (smbcli_read(cli->tree, fnum, buf, 0, 4000) != 4000) {
     649           0 :                 ret = false;
     650           0 :                 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "read failed at %s\n", __location__));
     651             :         }
     652           6 :         CHECK_BUFFER(buf, seed, 4000);
     653             : 
     654           6 :         torture_comment(tctx, "Trying bad fnum\n");
     655           6 :         io.writeclose.in.file.fnum = fnum+1;
     656           6 :         io.writeclose.in.count = 4000;
     657           6 :         io.writeclose.in.offset = 0;
     658           6 :         io.writeclose.in.data = buf;
     659           6 :         status = smb_raw_write(cli->tree, &io);
     660           6 :         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
     661             : 
     662           6 :         torture_comment(tctx, "Setting file as sparse\n");
     663           6 :         status = torture_set_sparse(cli->tree, fnum);
     664           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     665             : 
     666           6 :         if (!(cli->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
     667           0 :                 torture_skip(tctx, "skipping large file tests - CAP_LARGE_FILES not set\n");
     668             :         }
     669             : 
     670           6 :         torture_comment(tctx, "Trying 2^32 offset\n");
     671           6 :         setup_buffer(buf, seed, maxsize);
     672           6 :         io.writeclose.in.file.fnum = fnum;
     673           6 :         io.writeclose.in.count = 4000;
     674           6 :         io.writeclose.in.offset = 0xFFFFFFFF - 2000;
     675           6 :         io.writeclose.in.data = buf;
     676           6 :         status = smb_raw_write(cli->tree, &io);
     677           6 :         CHECK_STATUS(status, NT_STATUS_OK);
     678           6 :         CHECK_VALUE(io.writeclose.out.nwritten, 4000);
     679           6 :         CHECK_ALL_INFO(io.writeclose.in.count + (uint64_t)io.writeclose.in.offset, size);
     680             : 
     681           6 :         fnum = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
     682           6 :         io.writeclose.in.file.fnum = fnum;
     683             : 
     684           6 :         memset(buf, 0, maxsize);
     685           6 :         if (smbcli_read(cli->tree, fnum, buf, io.writeclose.in.offset, 4000) != 4000) {
     686           0 :                 ret = false;
     687           0 :                 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "read failed at %s\n", __location__));
     688             :         }
     689           6 :         CHECK_BUFFER(buf, seed, 4000);
     690             : 
     691           6 : done:
     692           6 :         smbcli_close(cli->tree, fnum);
     693           6 :         smb_raw_exit(cli->session);
     694           6 :         smbcli_deltree(cli->tree, BASEDIR);
     695           6 :         return ret;
     696             : }
     697             : 
     698             : /*
     699             :   test a deliberately bad SMB1 write.
     700             : */
     701           6 : static bool test_bad_write(struct torture_context *tctx,
     702             :                        struct smbcli_state *cli)
     703             : {
     704           6 :         bool ret = false;
     705           6 :         int fnum = -1;
     706           6 :         struct smbcli_request *req = NULL;
     707           6 :         const char *fname = BASEDIR "\\badwrite.txt";
     708           6 :         bool ok = false;
     709             : 
     710           6 :         if (!torture_setup_dir(cli, BASEDIR)) {
     711           0 :                 torture_fail(tctx, "failed to setup basedir");
     712             :         }
     713             : 
     714           6 :         torture_comment(tctx, "Testing RAW_BAD_WRITE\n");
     715             : 
     716           6 :         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
     717           6 :         if (fnum == -1) {
     718           0 :                 torture_fail_goto(tctx,
     719             :                         done,
     720             :                         talloc_asprintf(tctx,
     721             :                                 "Failed to create %s - %s\n",
     722             :                                 fname,
     723             :                                 smbcli_errstr(cli->tree)));
     724             :         }
     725             : 
     726           6 :         req = smbcli_request_setup(cli->tree,
     727             :                                    SMBwrite,
     728             :                                    5,
     729             :                                    0);
     730           6 :         if (req == NULL) {
     731           0 :                 torture_fail_goto(tctx,
     732             :                         done,
     733             :                         talloc_asprintf(tctx, "talloc fail\n"));
     734             :         }
     735             : 
     736           6 :         SSVAL(req->out.vwv, VWV(0), fnum);
     737           6 :         SSVAL(req->out.vwv, VWV(1), 65535); /* bad write length. */
     738           6 :         SIVAL(req->out.vwv, VWV(2), 0); /* offset */
     739           6 :         SSVAL(req->out.vwv, VWV(4), 0); /* remaining. */
     740             : 
     741           6 :         if (!smbcli_request_send(req)) {
     742           0 :                 torture_fail_goto(tctx,
     743             :                         done,
     744             :                         talloc_asprintf(tctx, "Send failed\n"));
     745             :         }
     746             : 
     747           6 :         if (!smbcli_request_receive(req)) {
     748           0 :                 torture_fail_goto(tctx,
     749             :                         done,
     750             :                         talloc_asprintf(tctx, "Receive failed\n"));
     751             :         }
     752             : 
     753             :         /*
     754             :          * Check for expected error codes.
     755             :          * ntvfs returns NT_STATUS_UNSUCCESSFUL.
     756             :          */
     757           7 :         ok = (NT_STATUS_EQUAL(req->status, NT_STATUS_INVALID_PARAMETER) ||
     758           1 :              NT_STATUS_EQUAL(req->status, NT_STATUS_UNSUCCESSFUL));
     759             : 
     760           6 :         if (!ok) {
     761           0 :                 torture_fail_goto(tctx,
     762             :                         done,
     763             :                         talloc_asprintf(tctx,
     764             :                                 "Should have returned "
     765             :                                 "NT_STATUS_INVALID_PARAMETER or "
     766             :                                 "NT_STATUS_UNSUCCESSFUL "
     767             :                                 "got %s\n",
     768             :                                 nt_errstr(req->status)));
     769             :         }
     770             : 
     771           5 :         ret = true;
     772             : 
     773           6 : done:
     774           6 :         if (req != NULL) {
     775           6 :                 smbcli_request_destroy(req);
     776             :         }
     777           6 :         if (fnum != -1) {
     778           6 :                 smbcli_close(cli->tree, fnum);
     779             :         }
     780           6 :         smb_raw_exit(cli->session);
     781           6 :         smbcli_deltree(cli->tree, BASEDIR);
     782           6 :         return ret;
     783             : }
     784             : 
     785             : /*
     786             :    basic testing of write calls
     787             : */
     788        2354 : struct torture_suite *torture_raw_write(TALLOC_CTX *mem_ctx)
     789             : {
     790        2354 :         struct torture_suite *suite = torture_suite_create(mem_ctx, "write");
     791             : 
     792        2354 :         torture_suite_add_1smb_test(suite, "write", test_write);
     793        2354 :         torture_suite_add_1smb_test(suite, "write unlock", test_writeunlock);
     794        2354 :         torture_suite_add_1smb_test(suite, "write close", test_writeclose);
     795        2354 :         torture_suite_add_1smb_test(suite, "writex", test_writex);
     796        2354 :         torture_suite_add_1smb_test(suite, "bad-write", test_bad_write);
     797             : 
     798        2354 :         return suite;
     799             : }

Generated by: LCOV version 1.14