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