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