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