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