build: Remove SMB_OFF_T, replace with off_t
[vlendec/samba-autobuild/.git] / source3 / torture / torture.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB torture tester
4    Copyright (C) Andrew Tridgell 1997-1998
5    Copyright (C) Jeremy Allison 2009
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 "system/shmem.h"
23 #include "wbc_async.h"
24 #include "torture/proto.h"
25 #include "libcli/security/security.h"
26 #include "tldap.h"
27 #include "tldap_util.h"
28 #include "../librpc/gen_ndr/svcctl.h"
29 #include "memcache.h"
30 #include "nsswitch/winbind_client.h"
31 #include "dbwrap/dbwrap.h"
32 #include "dbwrap/dbwrap_open.h"
33 #include "dbwrap/dbwrap_rbt.h"
34 #include "talloc_dict.h"
35 #include "async_smb.h"
36 #include "libsmb/libsmb.h"
37 #include "libsmb/clirap.h"
38 #include "trans2.h"
39 #include "libsmb/nmblib.h"
40 #include "../lib/util/tevent_ntstatus.h"
41 #include "util_tdb.h"
42 #include "../libcli/smb/read_smb.h"
43
44 extern char *optarg;
45 extern int optind;
46
47 fstring host, workgroup, share, password, username, myname;
48 static int max_protocol = PROTOCOL_NT1;
49 static const char *sockops="TCP_NODELAY";
50 static int nprocs=1;
51 static int port_to_use=0;
52 int torture_numops=100;
53 int torture_blocksize=1024*1024;
54 static int procnum; /* records process count number when forking */
55 static struct cli_state *current_cli;
56 static fstring randomfname;
57 static bool use_oplocks;
58 static bool use_level_II_oplocks;
59 static const char *client_txt = "client_oplocks.txt";
60 static bool disable_spnego;
61 static bool use_kerberos;
62 static bool force_dos_errors;
63 static fstring multishare_conn_fname;
64 static bool use_multishare_conn = False;
65 static bool do_encrypt;
66 static const char *local_path = NULL;
67 static int signing_state = SMB_SIGNING_DEFAULT;
68 char *test_filename;
69
70 bool torture_showall = False;
71
72 static double create_procs(bool (*fn)(int), bool *result);
73
74
75 /* return a pointer to a anonymous shared memory segment of size "size"
76    which will persist across fork() but will disappear when all processes
77    exit 
78
79    The memory is not zeroed 
80
81    This function uses system5 shared memory. It takes advantage of a property
82    that the memory is not destroyed if it is attached when the id is removed
83    */
84 void *shm_setup(int size)
85 {
86         int shmid;
87         void *ret;
88
89 #ifdef __QNXNTO__
90         shmid = shm_open("private", O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
91         if (shmid == -1) {
92                 printf("can't get shared memory\n");
93                 exit(1);
94         }
95         shm_unlink("private");
96         if (ftruncate(shmid, size) == -1) {
97                 printf("can't set shared memory size\n");
98                 exit(1);
99         }
100         ret = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, shmid, 0);
101         if (ret == MAP_FAILED) {
102                 printf("can't map shared memory\n");
103                 exit(1);
104         }
105 #else
106         shmid = shmget(IPC_PRIVATE, size, S_IRUSR | S_IWUSR);
107         if (shmid == -1) {
108                 printf("can't get shared memory\n");
109                 exit(1);
110         }
111         ret = (void *)shmat(shmid, 0, 0);
112         if (!ret || ret == (void *)-1) {
113                 printf("can't attach to shared memory\n");
114                 return NULL;
115         }
116         /* the following releases the ipc, but note that this process
117            and all its children will still have access to the memory, its
118            just that the shmid is no longer valid for other shm calls. This
119            means we don't leave behind lots of shm segments after we exit 
120
121            See Stevens "advanced programming in unix env" for details
122            */
123         shmctl(shmid, IPC_RMID, 0);
124 #endif
125
126         return ret;
127 }
128
129 /********************************************************************
130  Ensure a connection is encrypted.
131 ********************************************************************/
132
133 static bool force_cli_encryption(struct cli_state *c,
134                         const char *sharename)
135 {
136         uint16 major, minor;
137         uint32 caplow, caphigh;
138         NTSTATUS status;
139
140         if (!SERVER_HAS_UNIX_CIFS(c)) {
141                 d_printf("Encryption required and "
142                         "server that doesn't support "
143                         "UNIX extensions - failing connect\n");
144                         return false;
145         }
146
147         status = cli_unix_extensions_version(c, &major, &minor, &caplow,
148                                              &caphigh);
149         if (!NT_STATUS_IS_OK(status)) {
150                 d_printf("Encryption required and "
151                         "can't get UNIX CIFS extensions "
152                         "version from server: %s\n", nt_errstr(status));
153                 return false;
154         }
155
156         if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
157                 d_printf("Encryption required and "
158                         "share %s doesn't support "
159                         "encryption.\n", sharename);
160                 return false;
161         }
162
163         if (c->use_kerberos) {
164                 status = cli_gss_smb_encryption_start(c);
165         } else {
166                 status = cli_raw_ntlm_smb_encryption_start(c,
167                                                 username,
168                                                 password,
169                                                 workgroup);
170         }
171
172         if (!NT_STATUS_IS_OK(status)) {
173                 d_printf("Encryption required and "
174                         "setup failed with error %s.\n",
175                         nt_errstr(status));
176                 return false;
177         }
178
179         return true;
180 }
181
182
183 static struct cli_state *open_nbt_connection(void)
184 {
185         struct cli_state *c;
186         NTSTATUS status;
187         int flags = 0;
188
189         if (disable_spnego) {
190                 flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
191         }
192
193         if (use_oplocks) {
194                 flags |= CLI_FULL_CONNECTION_OPLOCKS;
195         }
196
197         if (use_level_II_oplocks) {
198                 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
199         }
200
201         if (use_kerberos) {
202                 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
203         }
204
205         if (force_dos_errors) {
206                 flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
207         }
208
209         status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
210                                 signing_state, flags, &c);
211         if (!NT_STATUS_IS_OK(status)) {
212                 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
213                 return NULL;
214         }
215
216         cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
217
218         return c;
219 }
220
221 /****************************************************************************
222  Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
223 ****************************************************************************/
224
225 static bool cli_bad_session_request(int fd,
226                          struct nmb_name *calling, struct nmb_name *called)
227 {
228         TALLOC_CTX *frame;
229         uint8_t len_buf[4];
230         struct iovec iov[3];
231         ssize_t len;
232         uint8_t *inbuf;
233         int err;
234         bool ret = false;
235         uint8_t message_type;
236         uint8_t error;
237         struct event_context *ev;
238         struct tevent_req *req;
239
240         frame = talloc_stackframe();
241
242         iov[0].iov_base = len_buf;
243         iov[0].iov_len  = sizeof(len_buf);
244
245         /* put in the destination name */
246
247         iov[1].iov_base = name_mangle(talloc_tos(), called->name,
248                                       called->name_type);
249         if (iov[1].iov_base == NULL) {
250                 goto fail;
251         }
252         iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
253                                   talloc_get_size(iov[1].iov_base));
254
255         /* and my name */
256
257         iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
258                                       calling->name_type);
259         if (iov[2].iov_base == NULL) {
260                 goto fail;
261         }
262         iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
263                                   talloc_get_size(iov[2].iov_base));
264
265         /* Deliberately corrupt the name len (first byte) */
266         *((uint8_t *)iov[2].iov_base) = 100;
267
268         /* send a session request (RFC 1002) */
269         /* setup the packet length
270          * Remove four bytes from the length count, since the length
271          * field in the NBT Session Service header counts the number
272          * of bytes which follow.  The cli_send_smb() function knows
273          * about this and accounts for those four bytes.
274          * CRH.
275          */
276
277         _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
278         SCVAL(len_buf,0,0x81);
279
280         len = write_data_iov(fd, iov, 3);
281         if (len == -1) {
282                 goto fail;
283         }
284
285         ev = event_context_init(frame);
286         if (ev == NULL) {
287                 goto fail;
288         }
289         req = read_smb_send(frame, ev, fd);
290         if (req == NULL) {
291                 goto fail;
292         }
293         if (!tevent_req_poll(req, ev)) {
294                 goto fail;
295         }
296         len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
297         if (len == -1) {
298                 errno = err;
299                 goto fail;
300         }
301         TALLOC_FREE(ev);
302
303         message_type = CVAL(inbuf, 0);
304         if (message_type != 0x83) {
305                 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
306                           message_type);
307                 goto fail;
308         }
309
310         if (smb_len(inbuf) != 1) {
311                 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
312                           (int)smb_len(inbuf));
313                 goto fail;
314         }
315
316         error = CVAL(inbuf, 4);
317         if (error !=  0x82) {
318                 d_fprintf(stderr, "Expected error 0x82, got %d\n",
319                           (int)error);
320                 goto fail;
321         }
322
323         ret = true;
324 fail:
325         TALLOC_FREE(frame);
326         return ret;
327 }
328
329 /* Insert a NULL at the first separator of the given path and return a pointer
330  * to the remainder of the string.
331  */
332 static char *
333 terminate_path_at_separator(char * path)
334 {
335         char * p;
336
337         if (!path) {
338                 return NULL;
339         }
340
341         if ((p = strchr_m(path, '/'))) {
342                 *p = '\0';
343                 return p + 1;
344         }
345
346         if ((p = strchr_m(path, '\\'))) {
347                 *p = '\0';
348                 return p + 1;
349         }
350
351         /* No separator. */
352         return NULL;
353 }
354
355 /*
356   parse a //server/share type UNC name
357 */
358 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
359                       char **hostname, char **sharename)
360 {
361         char *p;
362
363         *hostname = *sharename = NULL;
364
365         if (strncmp(unc_name, "\\\\", 2) &&
366             strncmp(unc_name, "//", 2)) {
367                 return False;
368         }
369
370         *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
371         p = terminate_path_at_separator(*hostname);
372
373         if (p && *p) {
374                 *sharename = talloc_strdup(mem_ctx, p);
375                 terminate_path_at_separator(*sharename);
376         }
377
378         if (*hostname && *sharename) {
379                 return True;
380         }
381
382         TALLOC_FREE(*hostname);
383         TALLOC_FREE(*sharename);
384         return False;
385 }
386
387 static bool torture_open_connection_share(struct cli_state **c,
388                                    const char *hostname, 
389                                    const char *sharename)
390 {
391         int flags = 0;
392         NTSTATUS status;
393
394         if (use_kerberos)
395                 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
396         if (use_oplocks)
397                 flags |= CLI_FULL_CONNECTION_OPLOCKS;
398         if (use_level_II_oplocks)
399                 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
400
401         status = cli_full_connection(c, myname,
402                                      hostname, NULL, port_to_use, 
403                                      sharename, "?????", 
404                                      username, workgroup, 
405                                      password, flags, signing_state);
406         if (!NT_STATUS_IS_OK(status)) {
407                 printf("failed to open share connection: //%s/%s port:%d - %s\n",
408                         hostname, sharename, port_to_use, nt_errstr(status));
409                 return False;
410         }
411
412         cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
413
414         if (do_encrypt) {
415                 return force_cli_encryption(*c,
416                                         sharename);
417         }
418         return True;
419 }
420
421 bool torture_open_connection(struct cli_state **c, int conn_index)
422 {
423         char **unc_list = NULL;
424         int num_unc_names = 0;
425         bool result;
426
427         if (use_multishare_conn==True) {
428                 char *h, *s;
429                 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
430                 if (!unc_list || num_unc_names <= 0) {
431                         printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
432                         exit(1);
433                 }
434
435                 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
436                                       NULL, &h, &s)) {
437                         printf("Failed to parse UNC name %s\n",
438                                unc_list[conn_index % num_unc_names]);
439                         TALLOC_FREE(unc_list);
440                         exit(1);
441                 }
442
443                 result = torture_open_connection_share(c, h, s);
444
445                 /* h, s were copied earlier */
446                 TALLOC_FREE(unc_list);
447                 return result;
448         }
449
450         return torture_open_connection_share(c, host, share);
451 }
452
453 bool torture_init_connection(struct cli_state **pcli)
454 {
455         struct cli_state *cli;
456
457         cli = open_nbt_connection();
458         if (cli == NULL) {
459                 return false;
460         }
461
462         *pcli = cli;
463         return true;
464 }
465
466 bool torture_cli_session_setup2(struct cli_state *cli, uint16 *new_vuid)
467 {
468         uint16_t old_vuid = cli_state_get_uid(cli);
469         fstring old_user_name;
470         size_t passlen = strlen(password);
471         NTSTATUS status;
472         bool ret;
473
474         fstrcpy(old_user_name, cli->user_name);
475         cli_state_set_uid(cli, 0);
476         ret = NT_STATUS_IS_OK(cli_session_setup(cli, username,
477                                                 password, passlen,
478                                                 password, passlen,
479                                                 workgroup));
480         *new_vuid = cli_state_get_uid(cli);
481         cli_state_set_uid(cli, old_vuid);
482         status = cli_set_username(cli, old_user_name);
483         if (!NT_STATUS_IS_OK(status)) {
484                 return false;
485         }
486         return ret;
487 }
488
489
490 bool torture_close_connection(struct cli_state *c)
491 {
492         bool ret = True;
493         NTSTATUS status;
494
495         status = cli_tdis(c);
496         if (!NT_STATUS_IS_OK(status)) {
497                 printf("tdis failed (%s)\n", nt_errstr(status));
498                 ret = False;
499         }
500
501         cli_shutdown(c);
502
503         return ret;
504 }
505
506
507 /* check if the server produced the expected dos or nt error code */
508 static bool check_both_error(int line, NTSTATUS status,
509                              uint8 eclass, uint32 ecode, NTSTATUS nterr)
510 {
511         if (NT_STATUS_IS_DOS(status)) {
512                 uint8 cclass;
513                 uint32 num;
514
515                 /* Check DOS error */
516                 cclass = NT_STATUS_DOS_CLASS(status);
517                 num = NT_STATUS_DOS_CODE(status);
518
519                 if (eclass != cclass || ecode != num) {
520                         printf("unexpected error code class=%d code=%d\n",
521                                (int)cclass, (int)num);
522                         printf(" expected %d/%d %s (line=%d)\n",
523                                (int)eclass, (int)ecode, nt_errstr(nterr), line);
524                         return false;
525                 }
526         } else {
527                 /* Check NT error */
528                 if (!NT_STATUS_EQUAL(nterr, status)) {
529                         printf("unexpected error code %s\n",
530                                 nt_errstr(status));
531                         printf(" expected %s (line=%d)\n",
532                                 nt_errstr(nterr), line);
533                         return false;
534                 }
535         }
536
537         return true;
538 }
539
540
541 /* check if the server produced the expected error code */
542 static bool check_error(int line, NTSTATUS status,
543                         uint8 eclass, uint32 ecode, NTSTATUS nterr)
544 {
545         if (NT_STATUS_IS_DOS(status)) {
546                 uint8 cclass;
547                 uint32 num;
548
549                 /* Check DOS error */
550
551                 cclass = NT_STATUS_DOS_CLASS(status);
552                 num = NT_STATUS_DOS_CODE(status);
553
554                 if (eclass != cclass || ecode != num) {
555                         printf("unexpected error code class=%d code=%d\n", 
556                                (int)cclass, (int)num);
557                         printf(" expected %d/%d %s (line=%d)\n", 
558                                (int)eclass, (int)ecode, nt_errstr(nterr),
559                                line);
560                         return False;
561                 }
562
563         } else {
564                 /* Check NT error */
565
566                 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
567                         printf("unexpected error code %s\n",
568                                nt_errstr(status));
569                         printf(" expected %s (line=%d)\n", nt_errstr(nterr),
570                                line);
571                         return False;
572                 }
573         }
574
575         return True;
576 }
577
578
579 static bool wait_lock(struct cli_state *c, int fnum, uint32 offset, uint32 len)
580 {
581         NTSTATUS status;
582
583         status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
584
585         while (!NT_STATUS_IS_OK(status)) {
586                 if (!check_both_error(__LINE__, status, ERRDOS,
587                                       ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
588                         return false;
589                 }
590
591                 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
592         }
593
594         return true;
595 }
596
597
598 static bool rw_torture(struct cli_state *c)
599 {
600         const char *lockfname = "\\torture.lck";
601         fstring fname;
602         uint16_t fnum;
603         uint16_t fnum2;
604         pid_t pid2, pid = getpid();
605         int i, j;
606         char buf[1024];
607         bool correct = True;
608         size_t nread = 0;
609         NTSTATUS status;
610
611         memset(buf, '\0', sizeof(buf));
612
613         status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL, 
614                          DENY_NONE, &fnum2);
615         if (!NT_STATUS_IS_OK(status)) {
616                 status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
617         }
618         if (!NT_STATUS_IS_OK(status)) {
619                 printf("open of %s failed (%s)\n",
620                        lockfname, nt_errstr(status));
621                 return False;
622         }
623
624         for (i=0;i<torture_numops;i++) {
625                 unsigned n = (unsigned)sys_random()%10;
626
627                 if (i % 10 == 0) {
628                         printf("%d\r", i); fflush(stdout);
629                 }
630                 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
631
632                 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
633                         return False;
634                 }
635
636                 status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
637                                   DENY_ALL, &fnum);
638                 if (!NT_STATUS_IS_OK(status)) {
639                         printf("open failed (%s)\n", nt_errstr(status));
640                         correct = False;
641                         break;
642                 }
643
644                 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
645                                       sizeof(pid), NULL);
646                 if (!NT_STATUS_IS_OK(status)) {
647                         printf("write failed (%s)\n", nt_errstr(status));
648                         correct = False;
649                 }
650
651                 for (j=0;j<50;j++) {
652                         status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
653                                               sizeof(pid)+(j*sizeof(buf)),
654                                               sizeof(buf), NULL);
655                         if (!NT_STATUS_IS_OK(status)) {
656                                 printf("write failed (%s)\n",
657                                        nt_errstr(status));
658                                 correct = False;
659                         }
660                 }
661
662                 pid2 = 0;
663
664                 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
665                                   &nread);
666                 if (!NT_STATUS_IS_OK(status)) {
667                         printf("read failed (%s)\n", nt_errstr(status));
668                         correct = false;
669                 } else if (nread != sizeof(pid)) {
670                         printf("read/write compare failed: "
671                                "recv %ld req %ld\n", (unsigned long)nread,
672                                (unsigned long)sizeof(pid));
673                         correct = false;
674                 }
675
676                 if (pid2 != pid) {
677                         printf("data corruption!\n");
678                         correct = False;
679                 }
680
681                 status = cli_close(c, fnum);
682                 if (!NT_STATUS_IS_OK(status)) {
683                         printf("close failed (%s)\n", nt_errstr(status));
684                         correct = False;
685                 }
686
687                 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
688                 if (!NT_STATUS_IS_OK(status)) {
689                         printf("unlink failed (%s)\n", nt_errstr(status));
690                         correct = False;
691                 }
692
693                 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
694                 if (!NT_STATUS_IS_OK(status)) {
695                         printf("unlock failed (%s)\n", nt_errstr(status));
696                         correct = False;
697                 }
698         }
699
700         cli_close(c, fnum2);
701         cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
702
703         printf("%d\n", i);
704
705         return correct;
706 }
707
708 static bool run_torture(int dummy)
709 {
710         struct cli_state *cli;
711         bool ret;
712
713         cli = current_cli;
714
715         cli_sockopt(cli, sockops);
716
717         ret = rw_torture(cli);
718
719         if (!torture_close_connection(cli)) {
720                 ret = False;
721         }
722
723         return ret;
724 }
725
726 static bool rw_torture3(struct cli_state *c, char *lockfname)
727 {
728         uint16_t fnum = (uint16_t)-1;
729         unsigned int i = 0;
730         char buf[131072];
731         char buf_rd[131072];
732         unsigned count;
733         unsigned countprev = 0;
734         size_t sent = 0;
735         bool correct = True;
736         NTSTATUS status = NT_STATUS_OK;
737
738         srandom(1);
739         for (i = 0; i < sizeof(buf); i += sizeof(uint32))
740         {
741                 SIVAL(buf, i, sys_random());
742         }
743
744         if (procnum == 0)
745         {
746                 status = cli_unlink(
747                         c, lockfname,
748                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
749                 if (!NT_STATUS_IS_OK(status)) {
750                         printf("unlink failed (%s) (normal, this file should "
751                                "not exist)\n", nt_errstr(status));
752                 }
753
754                 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
755                                   DENY_NONE, &fnum);
756                 if (!NT_STATUS_IS_OK(status)) {
757                         printf("first open read/write of %s failed (%s)\n",
758                                         lockfname, nt_errstr(status));
759                         return False;
760                 }
761         }
762         else
763         {
764                 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
765                 {
766                         status = cli_openx(c, lockfname, O_RDONLY, 
767                                          DENY_NONE, &fnum);
768                         if (!NT_STATUS_IS_OK(status)) {
769                                 break;
770                         }
771                         smb_msleep(10);
772                 }
773                 if (!NT_STATUS_IS_OK(status)) {
774                         printf("second open read-only of %s failed (%s)\n",
775                                         lockfname, nt_errstr(status));
776                         return False;
777                 }
778         }
779
780         i = 0;
781         for (count = 0; count < sizeof(buf); count += sent)
782         {
783                 if (count >= countprev) {
784                         printf("%d %8d\r", i, count);
785                         fflush(stdout);
786                         i++;
787                         countprev += (sizeof(buf) / 20);
788                 }
789
790                 if (procnum == 0)
791                 {
792                         sent = ((unsigned)sys_random()%(20))+ 1;
793                         if (sent > sizeof(buf) - count)
794                         {
795                                 sent = sizeof(buf) - count;
796                         }
797
798                         status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
799                                               count, sent, NULL);
800                         if (!NT_STATUS_IS_OK(status)) {
801                                 printf("write failed (%s)\n",
802                                        nt_errstr(status));
803                                 correct = False;
804                         }
805                 }
806                 else
807                 {
808                         status = cli_read(c, fnum, buf_rd+count, count,
809                                           sizeof(buf)-count, &sent);
810                         if(!NT_STATUS_IS_OK(status)) {
811                                 printf("read failed offset:%d size:%ld (%s)\n",
812                                        count, (unsigned long)sizeof(buf)-count,
813                                        nt_errstr(status));
814                                 correct = False;
815                                 sent = 0;
816                         } else if (sent > 0) {
817                                 if (memcmp(buf_rd+count, buf+count, sent) != 0)
818                                 {
819                                         printf("read/write compare failed\n");
820                                         printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
821                                         correct = False;
822                                         break;
823                                 }
824                         }
825                 }
826
827         }
828
829         status = cli_close(c, fnum);
830         if (!NT_STATUS_IS_OK(status)) {
831                 printf("close failed (%s)\n", nt_errstr(status));
832                 correct = False;
833         }
834
835         return correct;
836 }
837
838 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
839 {
840         const char *lockfname = "\\torture2.lck";
841         uint16_t fnum1;
842         uint16_t fnum2;
843         int i;
844         char buf[131072];
845         char buf_rd[131072];
846         bool correct = True;
847         size_t bytes_read;
848         NTSTATUS status;
849
850         status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
851         if (!NT_STATUS_IS_OK(status)) {
852                 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
853         }
854
855         status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
856                           DENY_NONE, &fnum1);
857         if (!NT_STATUS_IS_OK(status)) {
858                 printf("first open read/write of %s failed (%s)\n",
859                                 lockfname, nt_errstr(status));
860                 return False;
861         }
862
863         status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
864         if (!NT_STATUS_IS_OK(status)) {
865                 printf("second open read-only of %s failed (%s)\n",
866                                 lockfname, nt_errstr(status));
867                 cli_close(c1, fnum1);
868                 return False;
869         }
870
871         for (i = 0; i < torture_numops; i++)
872         {
873                 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
874                 if (i % 10 == 0) {
875                         printf("%d\r", i); fflush(stdout);
876                 }
877
878                 generate_random_buffer((unsigned char *)buf, buf_size);
879
880                 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
881                                       buf_size, NULL);
882                 if (!NT_STATUS_IS_OK(status)) {
883                         printf("write failed (%s)\n", nt_errstr(status));
884                         correct = False;
885                         break;
886                 }
887
888                 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
889                 if(!NT_STATUS_IS_OK(status)) {
890                         printf("read failed (%s)\n", nt_errstr(status));
891                         correct = false;
892                         break;
893                 } else if (bytes_read != buf_size) {
894                         printf("read failed\n");
895                         printf("read %ld, expected %ld\n",
896                                (unsigned long)bytes_read,
897                                (unsigned long)buf_size); 
898                         correct = False;
899                         break;
900                 }
901
902                 if (memcmp(buf_rd, buf, buf_size) != 0)
903                 {
904                         printf("read/write compare failed\n");
905                         correct = False;
906                         break;
907                 }
908         }
909
910         status = cli_close(c2, fnum2);
911         if (!NT_STATUS_IS_OK(status)) {
912                 printf("close failed (%s)\n", nt_errstr(status));
913                 correct = False;
914         }
915
916         status = cli_close(c1, fnum1);
917         if (!NT_STATUS_IS_OK(status)) {
918                 printf("close failed (%s)\n", nt_errstr(status));
919                 correct = False;
920         }
921
922         status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
923         if (!NT_STATUS_IS_OK(status)) {
924                 printf("unlink failed (%s)\n", nt_errstr(status));
925                 correct = False;
926         }
927
928         return correct;
929 }
930
931 static bool run_readwritetest(int dummy)
932 {
933         struct cli_state *cli1, *cli2;
934         bool test1, test2 = False;
935
936         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
937                 return False;
938         }
939         cli_sockopt(cli1, sockops);
940         cli_sockopt(cli2, sockops);
941
942         printf("starting readwritetest\n");
943
944         test1 = rw_torture2(cli1, cli2);
945         printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
946
947         if (test1) {
948                 test2 = rw_torture2(cli1, cli1);
949                 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
950         }
951
952         if (!torture_close_connection(cli1)) {
953                 test1 = False;
954         }
955
956         if (!torture_close_connection(cli2)) {
957                 test2 = False;
958         }
959
960         return (test1 && test2);
961 }
962
963 static bool run_readwritemulti(int dummy)
964 {
965         struct cli_state *cli;
966         bool test;
967
968         cli = current_cli;
969
970         cli_sockopt(cli, sockops);
971
972         printf("run_readwritemulti: fname %s\n", randomfname);
973         test = rw_torture3(cli, randomfname);
974
975         if (!torture_close_connection(cli)) {
976                 test = False;
977         }
978
979         return test;
980 }
981
982 static bool run_readwritelarge_internal(void)
983 {
984         static struct cli_state *cli1;
985         uint16_t fnum1;
986         const char *lockfname = "\\large.dat";
987         off_t fsize;
988         char buf[126*1024];
989         bool correct = True;
990         NTSTATUS status;
991
992         if (!torture_open_connection(&cli1, 0)) {
993                 return False;
994         }
995         cli_sockopt(cli1, sockops);
996         memset(buf,'\0',sizeof(buf));
997
998         printf("starting readwritelarge_internal\n");
999
1000         cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1001
1002         status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1003                           DENY_NONE, &fnum1);
1004         if (!NT_STATUS_IS_OK(status)) {
1005                 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1006                 return False;
1007         }
1008
1009         cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
1010
1011         status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1012                                      NULL, NULL, NULL);
1013         if (!NT_STATUS_IS_OK(status)) {
1014                 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1015                 correct = False;
1016         }
1017
1018         if (fsize == sizeof(buf))
1019                 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
1020                        (unsigned long)fsize);
1021         else {
1022                 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
1023                        (unsigned long)fsize);
1024                 correct = False;
1025         }
1026
1027         status = cli_close(cli1, fnum1);
1028         if (!NT_STATUS_IS_OK(status)) {
1029                 printf("close failed (%s)\n", nt_errstr(status));
1030                 correct = False;
1031         }
1032
1033         status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1034         if (!NT_STATUS_IS_OK(status)) {
1035                 printf("unlink failed (%s)\n", nt_errstr(status));
1036                 correct = False;
1037         }
1038
1039         status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1040                           DENY_NONE, &fnum1);
1041         if (!NT_STATUS_IS_OK(status)) {
1042                 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1043                 return False;
1044         }
1045
1046         cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1047
1048         status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1049                                      NULL, NULL, NULL);
1050         if (!NT_STATUS_IS_OK(status)) {
1051                 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1052                 correct = False;
1053         }
1054
1055         if (fsize == sizeof(buf))
1056                 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1057                        (unsigned long)fsize);
1058         else {
1059                 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1060                        (unsigned long)fsize);
1061                 correct = False;
1062         }
1063
1064 #if 0
1065         /* ToDo - set allocation. JRA */
1066         if(!cli_set_allocation_size(cli1, fnum1, 0)) {
1067                 printf("set allocation size to zero failed (%s)\n", cli_errstr(&cli1));
1068                 return False;
1069         }
1070         if (!cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL, NULL,
1071                                  NULL, NULL)) {
1072                 printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
1073                 correct = False;
1074         }
1075         if (fsize != 0)
1076                 printf("readwritelarge test 3 (truncate test) succeeded (size = %x)\n", fsize);
1077 #endif
1078
1079         status = cli_close(cli1, fnum1);
1080         if (!NT_STATUS_IS_OK(status)) {
1081                 printf("close failed (%s)\n", nt_errstr(status));
1082                 correct = False;
1083         }
1084
1085         if (!torture_close_connection(cli1)) {
1086                 correct = False;
1087         }
1088         return correct;
1089 }
1090
1091 static bool run_readwritelarge(int dummy)
1092 {
1093         return run_readwritelarge_internal();
1094 }
1095
1096 static bool run_readwritelarge_signtest(int dummy)
1097 {
1098         bool ret;
1099         signing_state = SMB_SIGNING_REQUIRED;
1100         ret = run_readwritelarge_internal();
1101         signing_state = SMB_SIGNING_DEFAULT;
1102         return ret;
1103 }
1104
1105 int line_count = 0;
1106 int nbio_id;
1107
1108 #define ival(s) strtol(s, NULL, 0)
1109
1110 /* run a test that simulates an approximate netbench client load */
1111 static bool run_netbench(int client)
1112 {
1113         struct cli_state *cli;
1114         int i;
1115         char line[1024];
1116         char cname[20];
1117         FILE *f;
1118         const char *params[20];
1119         bool correct = True;
1120
1121         cli = current_cli;
1122
1123         nbio_id = client;
1124
1125         cli_sockopt(cli, sockops);
1126
1127         nb_setup(cli);
1128
1129         slprintf(cname,sizeof(cname)-1, "client%d", client);
1130
1131         f = fopen(client_txt, "r");
1132
1133         if (!f) {
1134                 perror(client_txt);
1135                 return False;
1136         }
1137
1138         while (fgets(line, sizeof(line)-1, f)) {
1139                 char *saveptr;
1140                 line_count++;
1141
1142                 line[strlen(line)-1] = 0;
1143
1144                 /* printf("[%d] %s\n", line_count, line); */
1145
1146                 all_string_sub(line,"client1", cname, sizeof(line));
1147
1148                 /* parse the command parameters */
1149                 params[0] = strtok_r(line, " ", &saveptr);
1150                 i = 0;
1151                 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1152
1153                 params[i] = "";
1154
1155                 if (i < 2) continue;
1156
1157                 if (!strncmp(params[0],"SMB", 3)) {
1158                         printf("ERROR: You are using a dbench 1 load file\n");
1159                         exit(1);
1160                 }
1161
1162                 if (!strcmp(params[0],"NTCreateX")) {
1163                         nb_createx(params[1], ival(params[2]), ival(params[3]), 
1164                                    ival(params[4]));
1165                 } else if (!strcmp(params[0],"Close")) {
1166                         nb_close(ival(params[1]));
1167                 } else if (!strcmp(params[0],"Rename")) {
1168                         nb_rename(params[1], params[2]);
1169                 } else if (!strcmp(params[0],"Unlink")) {
1170                         nb_unlink(params[1]);
1171                 } else if (!strcmp(params[0],"Deltree")) {
1172                         nb_deltree(params[1]);
1173                 } else if (!strcmp(params[0],"Rmdir")) {
1174                         nb_rmdir(params[1]);
1175                 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1176                         nb_qpathinfo(params[1]);
1177                 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1178                         nb_qfileinfo(ival(params[1]));
1179                 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1180                         nb_qfsinfo(ival(params[1]));
1181                 } else if (!strcmp(params[0],"FIND_FIRST")) {
1182                         nb_findfirst(params[1]);
1183                 } else if (!strcmp(params[0],"WriteX")) {
1184                         nb_writex(ival(params[1]), 
1185                                   ival(params[2]), ival(params[3]), ival(params[4]));
1186                 } else if (!strcmp(params[0],"ReadX")) {
1187                         nb_readx(ival(params[1]), 
1188                                   ival(params[2]), ival(params[3]), ival(params[4]));
1189                 } else if (!strcmp(params[0],"Flush")) {
1190                         nb_flush(ival(params[1]));
1191                 } else {
1192                         printf("Unknown operation %s\n", params[0]);
1193                         exit(1);
1194                 }
1195         }
1196         fclose(f);
1197
1198         nb_cleanup();
1199
1200         if (!torture_close_connection(cli)) {
1201                 correct = False;
1202         }
1203
1204         return correct;
1205 }
1206
1207
1208 /* run a test that simulates an approximate netbench client load */
1209 static bool run_nbench(int dummy)
1210 {
1211         double t;
1212         bool correct = True;
1213
1214         nbio_shmem(nprocs);
1215
1216         nbio_id = -1;
1217
1218         signal(SIGALRM, nb_alarm);
1219         alarm(1);
1220         t = create_procs(run_netbench, &correct);
1221         alarm(0);
1222
1223         printf("\nThroughput %g MB/sec\n", 
1224                1.0e-6 * nbio_total() / t);
1225         return correct;
1226 }
1227
1228
1229 /*
1230   This test checks for two things:
1231
1232   1) correct support for retaining locks over a close (ie. the server
1233      must not use posix semantics)
1234   2) support for lock timeouts
1235  */
1236 static bool run_locktest1(int dummy)
1237 {
1238         struct cli_state *cli1, *cli2;
1239         const char *fname = "\\lockt1.lck";
1240         uint16_t fnum1, fnum2, fnum3;
1241         time_t t1, t2;
1242         unsigned lock_timeout;
1243         NTSTATUS status;
1244
1245         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1246                 return False;
1247         }
1248         cli_sockopt(cli1, sockops);
1249         cli_sockopt(cli2, sockops);
1250
1251         printf("starting locktest1\n");
1252
1253         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1254
1255         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1256                           &fnum1);
1257         if (!NT_STATUS_IS_OK(status)) {
1258                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1259                 return False;
1260         }
1261
1262         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1263         if (!NT_STATUS_IS_OK(status)) {
1264                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1265                 return False;
1266         }
1267
1268         status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1269         if (!NT_STATUS_IS_OK(status)) {
1270                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1271                 return False;
1272         }
1273
1274         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1275         if (!NT_STATUS_IS_OK(status)) {
1276                 printf("lock1 failed (%s)\n", nt_errstr(status));
1277                 return false;
1278         }
1279
1280         status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1281         if (NT_STATUS_IS_OK(status)) {
1282                 printf("lock2 succeeded! This is a locking bug\n");
1283                 return false;
1284         } else {
1285                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1286                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1287                         return false;
1288                 }
1289         }
1290
1291         lock_timeout = (1 + (random() % 20));
1292         printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1293         t1 = time(NULL);
1294         status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1295         if (NT_STATUS_IS_OK(status)) {
1296                 printf("lock3 succeeded! This is a locking bug\n");
1297                 return false;
1298         } else {
1299                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1300                                       NT_STATUS_FILE_LOCK_CONFLICT)) {
1301                         return false;
1302                 }
1303         }
1304         t2 = time(NULL);
1305
1306         if (ABS(t2 - t1) < lock_timeout-1) {
1307                 printf("error: This server appears not to support timed lock requests\n");
1308         }
1309
1310         printf("server slept for %u seconds for a %u second timeout\n",
1311                (unsigned int)(t2-t1), lock_timeout);
1312
1313         status = cli_close(cli1, fnum2);
1314         if (!NT_STATUS_IS_OK(status)) {
1315                 printf("close1 failed (%s)\n", nt_errstr(status));
1316                 return False;
1317         }
1318
1319         status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1320         if (NT_STATUS_IS_OK(status)) {
1321                 printf("lock4 succeeded! This is a locking bug\n");
1322                 return false;
1323         } else {
1324                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1325                                       NT_STATUS_FILE_LOCK_CONFLICT)) {
1326                         return false;
1327                 }
1328         }
1329
1330         status = cli_close(cli1, fnum1);
1331         if (!NT_STATUS_IS_OK(status)) {
1332                 printf("close2 failed (%s)\n", nt_errstr(status));
1333                 return False;
1334         }
1335
1336         status = cli_close(cli2, fnum3);
1337         if (!NT_STATUS_IS_OK(status)) {
1338                 printf("close3 failed (%s)\n", nt_errstr(status));
1339                 return False;
1340         }
1341
1342         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1343         if (!NT_STATUS_IS_OK(status)) {
1344                 printf("unlink failed (%s)\n", nt_errstr(status));
1345                 return False;
1346         }
1347
1348
1349         if (!torture_close_connection(cli1)) {
1350                 return False;
1351         }
1352
1353         if (!torture_close_connection(cli2)) {
1354                 return False;
1355         }
1356
1357         printf("Passed locktest1\n");
1358         return True;
1359 }
1360
1361 /*
1362   this checks to see if a secondary tconx can use open files from an
1363   earlier tconx
1364  */
1365 static bool run_tcon_test(int dummy)
1366 {
1367         static struct cli_state *cli;
1368         const char *fname = "\\tcontest.tmp";
1369         uint16 fnum1;
1370         uint16 cnum1, cnum2, cnum3;
1371         uint16 vuid1, vuid2;
1372         char buf[4];
1373         bool ret = True;
1374         NTSTATUS status;
1375
1376         memset(buf, '\0', sizeof(buf));
1377
1378         if (!torture_open_connection(&cli, 0)) {
1379                 return False;
1380         }
1381         cli_sockopt(cli, sockops);
1382
1383         printf("starting tcontest\n");
1384
1385         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1386
1387         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1388         if (!NT_STATUS_IS_OK(status)) {
1389                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1390                 return False;
1391         }
1392
1393         cnum1 = cli_state_get_tid(cli);
1394         vuid1 = cli_state_get_uid(cli);
1395
1396         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1397         if (!NT_STATUS_IS_OK(status)) {
1398                 printf("initial write failed (%s)", nt_errstr(status));
1399                 return False;
1400         }
1401
1402         status = cli_tree_connect(cli, share, "?????",
1403                                   password, strlen(password)+1);
1404         if (!NT_STATUS_IS_OK(status)) {
1405                 printf("%s refused 2nd tree connect (%s)\n", host,
1406                        nt_errstr(status));
1407                 cli_shutdown(cli);
1408                 return False;
1409         }
1410
1411         cnum2 = cli_state_get_tid(cli);
1412         cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1413         vuid2 = cli_state_get_uid(cli) + 1;
1414
1415         /* try a write with the wrong tid */
1416         cli_state_set_tid(cli, cnum2);
1417
1418         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1419         if (NT_STATUS_IS_OK(status)) {
1420                 printf("* server allows write with wrong TID\n");
1421                 ret = False;
1422         } else {
1423                 printf("server fails write with wrong TID : %s\n",
1424                        nt_errstr(status));
1425         }
1426
1427
1428         /* try a write with an invalid tid */
1429         cli_state_set_tid(cli, cnum3);
1430
1431         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1432         if (NT_STATUS_IS_OK(status)) {
1433                 printf("* server allows write with invalid TID\n");
1434                 ret = False;
1435         } else {
1436                 printf("server fails write with invalid TID : %s\n",
1437                        nt_errstr(status));
1438         }
1439
1440         /* try a write with an invalid vuid */
1441         cli_state_set_uid(cli, vuid2);
1442         cli_state_set_tid(cli, cnum1);
1443
1444         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1445         if (NT_STATUS_IS_OK(status)) {
1446                 printf("* server allows write with invalid VUID\n");
1447                 ret = False;
1448         } else {
1449                 printf("server fails write with invalid VUID : %s\n",
1450                        nt_errstr(status));
1451         }
1452
1453         cli_state_set_tid(cli, cnum1);
1454         cli_state_set_uid(cli, vuid1);
1455
1456         status = cli_close(cli, fnum1);
1457         if (!NT_STATUS_IS_OK(status)) {
1458                 printf("close failed (%s)\n", nt_errstr(status));
1459                 return False;
1460         }
1461
1462         cli_state_set_tid(cli, cnum2);
1463
1464         status = cli_tdis(cli);
1465         if (!NT_STATUS_IS_OK(status)) {
1466                 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1467                 return False;
1468         }
1469
1470         cli_state_set_tid(cli, cnum1);
1471
1472         if (!torture_close_connection(cli)) {
1473                 return False;
1474         }
1475
1476         return ret;
1477 }
1478
1479
1480 /*
1481  checks for old style tcon support
1482  */
1483 static bool run_tcon2_test(int dummy)
1484 {
1485         static struct cli_state *cli;
1486         uint16 cnum, max_xmit;
1487         char *service;
1488         NTSTATUS status;
1489
1490         if (!torture_open_connection(&cli, 0)) {
1491                 return False;
1492         }
1493         cli_sockopt(cli, sockops);
1494
1495         printf("starting tcon2 test\n");
1496
1497         if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1498                 return false;
1499         }
1500
1501         status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1502
1503         SAFE_FREE(service);
1504
1505         if (!NT_STATUS_IS_OK(status)) {
1506                 printf("tcon2 failed : %s\n", nt_errstr(status));
1507         } else {
1508                 printf("tcon OK : max_xmit=%d cnum=%d\n",
1509                        (int)max_xmit, (int)cnum);
1510         }
1511
1512         if (!torture_close_connection(cli)) {
1513                 return False;
1514         }
1515
1516         printf("Passed tcon2 test\n");
1517         return True;
1518 }
1519
1520 static bool tcon_devtest(struct cli_state *cli,
1521                          const char *myshare, const char *devtype,
1522                          const char *return_devtype,
1523                          NTSTATUS expected_error)
1524 {
1525         NTSTATUS status;
1526         bool ret;
1527
1528         status = cli_tree_connect(cli, myshare, devtype,
1529                                   password, strlen(password)+1);
1530
1531         if (NT_STATUS_IS_OK(expected_error)) {
1532                 if (NT_STATUS_IS_OK(status)) {
1533                         if (strcmp(cli->dev, return_devtype) == 0) {
1534                                 ret = True;
1535                         } else { 
1536                                 printf("tconX to share %s with type %s "
1537                                        "succeeded but returned the wrong "
1538                                        "device type (got [%s] but should have got [%s])\n",
1539                                        myshare, devtype, cli->dev, return_devtype);
1540                                 ret = False;
1541                         }
1542                 } else {
1543                         printf("tconX to share %s with type %s "
1544                                "should have succeeded but failed\n",
1545                                myshare, devtype);
1546                         ret = False;
1547                 }
1548                 cli_tdis(cli);
1549         } else {
1550                 if (NT_STATUS_IS_OK(status)) {
1551                         printf("tconx to share %s with type %s "
1552                                "should have failed but succeeded\n",
1553                                myshare, devtype);
1554                         ret = False;
1555                 } else {
1556                         if (NT_STATUS_EQUAL(status, expected_error)) {
1557                                 ret = True;
1558                         } else {
1559                                 printf("Returned unexpected error\n");
1560                                 ret = False;
1561                         }
1562                 }
1563         }
1564         return ret;
1565 }
1566
1567 /*
1568  checks for correct tconX support
1569  */
1570 static bool run_tcon_devtype_test(int dummy)
1571 {
1572         static struct cli_state *cli1 = NULL;
1573         int flags = 0;
1574         NTSTATUS status;
1575         bool ret = True;
1576
1577         status = cli_full_connection(&cli1, myname,
1578                                      host, NULL, port_to_use,
1579                                      NULL, NULL,
1580                                      username, workgroup,
1581                                      password, flags, signing_state);
1582
1583         if (!NT_STATUS_IS_OK(status)) {
1584                 printf("could not open connection\n");
1585                 return False;
1586         }
1587
1588         if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1589                 ret = False;
1590
1591         if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1592                 ret = False;
1593
1594         if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1595                 ret = False;
1596
1597         if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1598                 ret = False;
1599
1600         if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1601                 ret = False;
1602
1603         if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1604                 ret = False;
1605
1606         if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1607                 ret = False;
1608
1609         if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1610                 ret = False;
1611
1612         if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1613                 ret = False;
1614
1615         if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1616                 ret = False;
1617
1618         cli_shutdown(cli1);
1619
1620         if (ret)
1621                 printf("Passed tcondevtest\n");
1622
1623         return ret;
1624 }
1625
1626
1627 /*
1628   This test checks that 
1629
1630   1) the server supports multiple locking contexts on the one SMB
1631   connection, distinguished by PID.  
1632
1633   2) the server correctly fails overlapping locks made by the same PID (this
1634      goes against POSIX behaviour, which is why it is tricky to implement)
1635
1636   3) the server denies unlock requests by an incorrect client PID
1637 */
1638 static bool run_locktest2(int dummy)
1639 {
1640         static struct cli_state *cli;
1641         const char *fname = "\\lockt2.lck";
1642         uint16_t fnum1, fnum2, fnum3;
1643         bool correct = True;
1644         NTSTATUS status;
1645
1646         if (!torture_open_connection(&cli, 0)) {
1647                 return False;
1648         }
1649
1650         cli_sockopt(cli, sockops);
1651
1652         printf("starting locktest2\n");
1653
1654         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1655
1656         cli_setpid(cli, 1);
1657
1658         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1659         if (!NT_STATUS_IS_OK(status)) {
1660                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1661                 return False;
1662         }
1663
1664         status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1665         if (!NT_STATUS_IS_OK(status)) {
1666                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1667                 return False;
1668         }
1669
1670         cli_setpid(cli, 2);
1671
1672         status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1673         if (!NT_STATUS_IS_OK(status)) {
1674                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1675                 return False;
1676         }
1677
1678         cli_setpid(cli, 1);
1679
1680         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1681         if (!NT_STATUS_IS_OK(status)) {
1682                 printf("lock1 failed (%s)\n", nt_errstr(status));
1683                 return false;
1684         }
1685
1686         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1687         if (NT_STATUS_IS_OK(status)) {
1688                 printf("WRITE lock1 succeeded! This is a locking bug\n");
1689                 correct = false;
1690         } else {
1691                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1692                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1693                         return false;
1694                 }
1695         }
1696
1697         status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1698         if (NT_STATUS_IS_OK(status)) {
1699                 printf("WRITE lock2 succeeded! This is a locking bug\n");
1700                 correct = false;
1701         } else {
1702                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1703                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1704                         return false;
1705                 }
1706         }
1707
1708         status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1709         if (NT_STATUS_IS_OK(status)) {
1710                 printf("READ lock2 succeeded! This is a locking bug\n");
1711                 correct = false;
1712         } else {
1713                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1714                                  NT_STATUS_FILE_LOCK_CONFLICT)) {
1715                         return false;
1716                 }
1717         }
1718
1719         status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1720         if (!NT_STATUS_IS_OK(status)) {
1721                 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1722         }
1723         cli_setpid(cli, 2);
1724         if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1725                 printf("unlock at 100 succeeded! This is a locking bug\n");
1726                 correct = False;
1727         }
1728
1729         status = cli_unlock(cli, fnum1, 0, 4);
1730         if (NT_STATUS_IS_OK(status)) {
1731                 printf("unlock1 succeeded! This is a locking bug\n");
1732                 correct = false;
1733         } else {
1734                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1735                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1736                         return false;
1737                 }
1738         }
1739
1740         status = cli_unlock(cli, fnum1, 0, 8);
1741         if (NT_STATUS_IS_OK(status)) {
1742                 printf("unlock2 succeeded! This is a locking bug\n");
1743                 correct = false;
1744         } else {
1745                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1746                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1747                         return false;
1748                 }
1749         }
1750
1751         status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1752         if (NT_STATUS_IS_OK(status)) {
1753                 printf("lock3 succeeded! This is a locking bug\n");
1754                 correct = false;
1755         } else {
1756                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1757                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1758                         return false;
1759                 }
1760         }
1761
1762         cli_setpid(cli, 1);
1763
1764         status = cli_close(cli, fnum1);
1765         if (!NT_STATUS_IS_OK(status)) {
1766                 printf("close1 failed (%s)\n", nt_errstr(status));
1767                 return False;
1768         }
1769
1770         status = cli_close(cli, fnum2);
1771         if (!NT_STATUS_IS_OK(status)) {
1772                 printf("close2 failed (%s)\n", nt_errstr(status));
1773                 return False;
1774         }
1775
1776         status = cli_close(cli, fnum3);
1777         if (!NT_STATUS_IS_OK(status)) {
1778                 printf("close3 failed (%s)\n", nt_errstr(status));
1779                 return False;
1780         }
1781
1782         if (!torture_close_connection(cli)) {
1783                 correct = False;
1784         }
1785
1786         printf("locktest2 finished\n");
1787
1788         return correct;
1789 }
1790
1791
1792 /*
1793   This test checks that 
1794
1795   1) the server supports the full offset range in lock requests
1796 */
1797 static bool run_locktest3(int dummy)
1798 {
1799         static struct cli_state *cli1, *cli2;
1800         const char *fname = "\\lockt3.lck";
1801         uint16_t fnum1, fnum2;
1802         int i;
1803         uint32 offset;
1804         bool correct = True;
1805         NTSTATUS status;
1806
1807 #define NEXT_OFFSET offset += (~(uint32)0) / torture_numops
1808
1809         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1810                 return False;
1811         }
1812         cli_sockopt(cli1, sockops);
1813         cli_sockopt(cli2, sockops);
1814
1815         printf("starting locktest3\n");
1816
1817         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1818
1819         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1820                          &fnum1);
1821         if (!NT_STATUS_IS_OK(status)) {
1822                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1823                 return False;
1824         }
1825
1826         status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1827         if (!NT_STATUS_IS_OK(status)) {
1828                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1829                 return False;
1830         }
1831
1832         for (offset=i=0;i<torture_numops;i++) {
1833                 NEXT_OFFSET;
1834
1835                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1836                 if (!NT_STATUS_IS_OK(status)) {
1837                         printf("lock1 %d failed (%s)\n", 
1838                                i,
1839                                nt_errstr(status));
1840                         return False;
1841                 }
1842
1843                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1844                 if (!NT_STATUS_IS_OK(status)) {
1845                         printf("lock2 %d failed (%s)\n", 
1846                                i,
1847                                nt_errstr(status));
1848                         return False;
1849                 }
1850         }
1851
1852         for (offset=i=0;i<torture_numops;i++) {
1853                 NEXT_OFFSET;
1854
1855                 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1856                 if (NT_STATUS_IS_OK(status)) {
1857                         printf("error: lock1 %d succeeded!\n", i);
1858                         return False;
1859                 }
1860
1861                 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1862                 if (NT_STATUS_IS_OK(status)) {
1863                         printf("error: lock2 %d succeeded!\n", i);
1864                         return False;
1865                 }
1866
1867                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1868                 if (NT_STATUS_IS_OK(status)) {
1869                         printf("error: lock3 %d succeeded!\n", i);
1870                         return False;
1871                 }
1872
1873                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1874                 if (NT_STATUS_IS_OK(status)) {
1875                         printf("error: lock4 %d succeeded!\n", i);
1876                         return False;
1877                 }
1878         }
1879
1880         for (offset=i=0;i<torture_numops;i++) {
1881                 NEXT_OFFSET;
1882
1883                 status = cli_unlock(cli1, fnum1, offset-1, 1);
1884                 if (!NT_STATUS_IS_OK(status)) {
1885                         printf("unlock1 %d failed (%s)\n", 
1886                                i,
1887                                nt_errstr(status));
1888                         return False;
1889                 }
1890
1891                 status = cli_unlock(cli2, fnum2, offset-2, 1);
1892                 if (!NT_STATUS_IS_OK(status)) {
1893                         printf("unlock2 %d failed (%s)\n", 
1894                                i,
1895                                nt_errstr(status));
1896                         return False;
1897                 }
1898         }
1899
1900         status = cli_close(cli1, fnum1);
1901         if (!NT_STATUS_IS_OK(status)) {
1902                 printf("close1 failed (%s)\n", nt_errstr(status));
1903                 return False;
1904         }
1905
1906         status = cli_close(cli2, fnum2);
1907         if (!NT_STATUS_IS_OK(status)) {
1908                 printf("close2 failed (%s)\n", nt_errstr(status));
1909                 return False;
1910         }
1911
1912         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1913         if (!NT_STATUS_IS_OK(status)) {
1914                 printf("unlink failed (%s)\n", nt_errstr(status));
1915                 return False;
1916         }
1917
1918         if (!torture_close_connection(cli1)) {
1919                 correct = False;
1920         }
1921
1922         if (!torture_close_connection(cli2)) {
1923                 correct = False;
1924         }
1925
1926         printf("finished locktest3\n");
1927
1928         return correct;
1929 }
1930
1931 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
1932                            char *buf, off_t offset, size_t size,
1933                            size_t *nread, size_t expect)
1934 {
1935         NTSTATUS status;
1936         size_t l_nread;
1937
1938         status = cli_read(cli, fnum, buf, offset, size, &l_nread);
1939
1940         if(!NT_STATUS_IS_OK(status)) {
1941                 return false;
1942         } else if (l_nread != expect) {
1943                 return false;
1944         }
1945
1946         if (nread) {
1947                 *nread = l_nread;
1948         }
1949
1950         return true;
1951 }
1952
1953 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1954         printf("** "); correct = False; \
1955         }
1956
1957 /*
1958   looks at overlapping locks
1959 */
1960 static bool run_locktest4(int dummy)
1961 {
1962         static struct cli_state *cli1, *cli2;
1963         const char *fname = "\\lockt4.lck";
1964         uint16_t fnum1, fnum2, f;
1965         bool ret;
1966         char buf[1000];
1967         bool correct = True;
1968         NTSTATUS status;
1969
1970         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1971                 return False;
1972         }
1973
1974         cli_sockopt(cli1, sockops);
1975         cli_sockopt(cli2, sockops);
1976
1977         printf("starting locktest4\n");
1978
1979         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1980
1981         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1982         cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1983
1984         memset(buf, 0, sizeof(buf));
1985
1986         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
1987                               NULL);
1988         if (!NT_STATUS_IS_OK(status)) {
1989                 printf("Failed to create file: %s\n", nt_errstr(status));
1990                 correct = False;
1991                 goto fail;
1992         }
1993
1994         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1995               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
1996         EXPECTED(ret, False);
1997         printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1998
1999         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
2000               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
2001         EXPECTED(ret, True);
2002         printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
2003
2004         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
2005               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
2006         EXPECTED(ret, False);
2007         printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
2008
2009         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
2010               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
2011         EXPECTED(ret, True);
2012         printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
2013
2014         ret = (cli_setpid(cli1, 1),
2015               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
2016               (cli_setpid(cli1, 2),
2017               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
2018         EXPECTED(ret, False);
2019         printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
2020
2021         ret = (cli_setpid(cli1, 1),
2022               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
2023               (cli_setpid(cli1, 2),
2024               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
2025         EXPECTED(ret, True);
2026         printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
2027
2028         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
2029               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
2030         EXPECTED(ret, True);
2031         printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
2032
2033         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
2034               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
2035         EXPECTED(ret, False);
2036         printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
2037
2038         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
2039               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
2040         EXPECTED(ret, False);
2041         printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
2042
2043         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
2044               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2045         EXPECTED(ret, True);
2046         printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2047
2048         ret = (cli_setpid(cli1, 1),
2049              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2050              (cli_setpid(cli1, 2),
2051              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2052         EXPECTED(ret, False);
2053         printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2054
2055         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2056               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2057               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2058         EXPECTED(ret, False);
2059         printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2060
2061
2062         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2063               test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2064         EXPECTED(ret, False);
2065         printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2066
2067         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2068         ret = NT_STATUS_IS_OK(status);
2069         if (ret) {
2070                 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2071                                       NULL);
2072                 ret = NT_STATUS_IS_OK(status);
2073         }
2074         EXPECTED(ret, False);
2075         printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2076
2077
2078         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2079               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2080               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2081               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2082         EXPECTED(ret, True);
2083         printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2084
2085
2086         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2087               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2088               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2089               test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2090               !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2091                                              150, 4, NULL))) &&
2092               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2093         EXPECTED(ret, True);
2094         printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2095
2096         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2097               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2098               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2099                                            160, 4, NULL)) &&
2100               test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2101         EXPECTED(ret, True);
2102         printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2103
2104         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2105               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2106               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2107                                            170, 4, NULL)) &&
2108               test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2109         EXPECTED(ret, True);
2110         printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2111
2112         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2113               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2114               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2115               !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2116                                             190, 4, NULL)) &&
2117               test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2118         EXPECTED(ret, True);
2119         printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2120
2121         cli_close(cli1, fnum1);
2122         cli_close(cli2, fnum2);
2123         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2124         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2125         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2126               NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2127               NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2128               NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2129               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2130         cli_close(cli1, f);
2131         cli_close(cli1, fnum1);
2132         EXPECTED(ret, True);
2133         printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2134
2135  fail:
2136         cli_close(cli1, fnum1);
2137         cli_close(cli2, fnum2);
2138         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2139         torture_close_connection(cli1);
2140         torture_close_connection(cli2);
2141
2142         printf("finished locktest4\n");
2143         return correct;
2144 }
2145
2146 /*
2147   looks at lock upgrade/downgrade.
2148 */
2149 static bool run_locktest5(int dummy)
2150 {
2151         static struct cli_state *cli1, *cli2;
2152         const char *fname = "\\lockt5.lck";
2153         uint16_t fnum1, fnum2, fnum3;
2154         bool ret;
2155         char buf[1000];
2156         bool correct = True;
2157         NTSTATUS status;
2158
2159         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2160                 return False;
2161         }
2162
2163         cli_sockopt(cli1, sockops);
2164         cli_sockopt(cli2, sockops);
2165
2166         printf("starting locktest5\n");
2167
2168         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2169
2170         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2171         cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2172         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2173
2174         memset(buf, 0, sizeof(buf));
2175
2176         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2177                               NULL);
2178         if (!NT_STATUS_IS_OK(status)) {
2179                 printf("Failed to create file: %s\n", nt_errstr(status));
2180                 correct = False;
2181                 goto fail;
2182         }
2183
2184         /* Check for NT bug... */
2185         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2186               NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2187         cli_close(cli1, fnum1);
2188         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2189         status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2190         ret = NT_STATUS_IS_OK(status);
2191         EXPECTED(ret, True);
2192         printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2193         cli_close(cli1, fnum1);
2194         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2195         cli_unlock(cli1, fnum3, 0, 1);
2196
2197         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2198               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2199         EXPECTED(ret, True);
2200         printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2201
2202         status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2203         ret = NT_STATUS_IS_OK(status);
2204         EXPECTED(ret, False);
2205
2206         printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2207
2208         /* Unlock the process 2 lock. */
2209         cli_unlock(cli2, fnum2, 0, 4);
2210
2211         status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2212         ret = NT_STATUS_IS_OK(status);
2213         EXPECTED(ret, False);
2214
2215         printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
2216
2217         /* Unlock the process 1 fnum3 lock. */
2218         cli_unlock(cli1, fnum3, 0, 4);
2219
2220         /* Stack 2 more locks here. */
2221         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2222               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2223
2224         EXPECTED(ret, True);
2225         printf("the same process %s stack read locks\n", ret?"can":"cannot");
2226
2227         /* Unlock the first process lock, then check this was the WRITE lock that was
2228                 removed. */
2229
2230         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2231               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2232
2233         EXPECTED(ret, True);
2234         printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2235
2236         /* Unlock the process 2 lock. */
2237         cli_unlock(cli2, fnum2, 0, 4);
2238
2239         /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2240
2241         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2242                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2243                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2244
2245         EXPECTED(ret, True);
2246         printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot"); 
2247
2248         /* Ensure the next unlock fails. */
2249         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2250         EXPECTED(ret, False);
2251         printf("the same process %s count the lock stack\n", !ret?"can":"cannot"); 
2252
2253         /* Ensure connection 2 can get a write lock. */
2254         status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2255         ret = NT_STATUS_IS_OK(status);
2256         EXPECTED(ret, True);
2257
2258         printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2259
2260
2261  fail:
2262         cli_close(cli1, fnum1);
2263         cli_close(cli2, fnum2);
2264         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2265         if (!torture_close_connection(cli1)) {
2266                 correct = False;
2267         }
2268         if (!torture_close_connection(cli2)) {
2269                 correct = False;
2270         }
2271
2272         printf("finished locktest5\n");
2273
2274         return correct;
2275 }
2276
2277 /*
2278   tries the unusual lockingX locktype bits
2279 */
2280 static bool run_locktest6(int dummy)
2281 {
2282         static struct cli_state *cli;
2283         const char *fname[1] = { "\\lock6.txt" };
2284         int i;
2285         uint16_t fnum;
2286         NTSTATUS status;
2287
2288         if (!torture_open_connection(&cli, 0)) {
2289                 return False;
2290         }
2291
2292         cli_sockopt(cli, sockops);
2293
2294         printf("starting locktest6\n");
2295
2296         for (i=0;i<1;i++) {
2297                 printf("Testing %s\n", fname[i]);
2298
2299                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2300
2301                 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2302                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2303                 cli_close(cli, fnum);
2304                 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2305
2306                 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2307                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2308                 cli_close(cli, fnum);
2309                 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2310
2311                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2312         }
2313
2314         torture_close_connection(cli);
2315
2316         printf("finished locktest6\n");
2317         return True;
2318 }
2319
2320 static bool run_locktest7(int dummy)
2321 {
2322         struct cli_state *cli1;
2323         const char *fname = "\\lockt7.lck";
2324         uint16_t fnum1;
2325         char buf[200];
2326         bool correct = False;
2327         size_t nread;
2328         NTSTATUS status;
2329
2330         if (!torture_open_connection(&cli1, 0)) {
2331                 return False;
2332         }
2333
2334         cli_sockopt(cli1, sockops);
2335
2336         printf("starting locktest7\n");
2337
2338         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2339
2340         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2341
2342         memset(buf, 0, sizeof(buf));
2343
2344         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2345                               NULL);
2346         if (!NT_STATUS_IS_OK(status)) {
2347                 printf("Failed to create file: %s\n", nt_errstr(status));
2348                 goto fail;
2349         }
2350
2351         cli_setpid(cli1, 1);
2352
2353         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2354         if (!NT_STATUS_IS_OK(status)) {
2355                 printf("Unable to apply read lock on range 130:4, "
2356                        "error was %s\n", nt_errstr(status));
2357                 goto fail;
2358         } else {
2359                 printf("pid1 successfully locked range 130:4 for READ\n");
2360         }
2361
2362         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2363         if (!NT_STATUS_IS_OK(status)) {
2364                 printf("pid1 unable to read the range 130:4, error was %s\n",
2365                       nt_errstr(status));
2366                 goto fail;
2367         } else if (nread != 4) {
2368                 printf("pid1 unable to read the range 130:4, "
2369                        "recv %ld req %d\n", (unsigned long)nread, 4);
2370                 goto fail;
2371         } else {
2372                 printf("pid1 successfully read the range 130:4\n");
2373         }
2374
2375         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2376         if (!NT_STATUS_IS_OK(status)) {
2377                 printf("pid1 unable to write to the range 130:4, error was "
2378                        "%s\n", nt_errstr(status));
2379                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2380                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2381                         goto fail;
2382                 }
2383         } else {
2384                 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2385                 goto fail;
2386         }
2387
2388         cli_setpid(cli1, 2);
2389
2390         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2391         if (!NT_STATUS_IS_OK(status)) {
2392                 printf("pid2 unable to read the range 130:4, error was %s\n",
2393                       nt_errstr(status));
2394                 goto fail;
2395         } else if (nread != 4) {
2396                 printf("pid2 unable to read the range 130:4, "
2397                        "recv %ld req %d\n", (unsigned long)nread, 4);
2398                 goto fail;
2399         } else {
2400                 printf("pid2 successfully read the range 130:4\n");
2401         }
2402
2403         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2404         if (!NT_STATUS_IS_OK(status)) {
2405                 printf("pid2 unable to write to the range 130:4, error was "
2406                        "%s\n", nt_errstr(status));
2407                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2408                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2409                         goto fail;
2410                 }
2411         } else {
2412                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2413                 goto fail;
2414         }
2415
2416         cli_setpid(cli1, 1);
2417         cli_unlock(cli1, fnum1, 130, 4);
2418
2419         status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2420         if (!NT_STATUS_IS_OK(status)) {
2421                 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2422                 goto fail;
2423         } else {
2424                 printf("pid1 successfully locked range 130:4 for WRITE\n");
2425         }
2426
2427         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2428         if (!NT_STATUS_IS_OK(status)) {
2429                 printf("pid1 unable to read the range 130:4, error was %s\n",
2430                       nt_errstr(status));
2431                 goto fail;
2432         } else if (nread != 4) {
2433                 printf("pid1 unable to read the range 130:4, "
2434                        "recv %ld req %d\n", (unsigned long)nread, 4);
2435                 goto fail;
2436         } else {
2437                 printf("pid1 successfully read the range 130:4\n");
2438         }
2439
2440         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2441         if (!NT_STATUS_IS_OK(status)) {
2442                 printf("pid1 unable to write to the range 130:4, error was "
2443                        "%s\n", nt_errstr(status));
2444                 goto fail;
2445         } else {
2446                 printf("pid1 successfully wrote to the range 130:4\n");
2447         }
2448
2449         cli_setpid(cli1, 2);
2450
2451         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2452         if (!NT_STATUS_IS_OK(status)) {
2453                 printf("pid2 unable to read the range 130:4, error was "
2454                        "%s\n", nt_errstr(status));
2455                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2456                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2457                         goto fail;
2458                 }
2459         } else {
2460                 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2461                        (unsigned long)nread);
2462                 goto fail;
2463         }
2464
2465         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2466         if (!NT_STATUS_IS_OK(status)) {
2467                 printf("pid2 unable to write to the range 130:4, error was "
2468                        "%s\n", nt_errstr(status));
2469                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2470                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2471                         goto fail;
2472                 }
2473         } else {
2474                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2475                 goto fail;
2476         }
2477
2478         cli_unlock(cli1, fnum1, 130, 0);
2479         correct = True;
2480
2481 fail:
2482         cli_close(cli1, fnum1);
2483         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2484         torture_close_connection(cli1);
2485
2486         printf("finished locktest7\n");
2487         return correct;
2488 }
2489
2490 /*
2491  * This demonstrates a problem with our use of GPFS share modes: A file
2492  * descriptor sitting in the pending close queue holding a GPFS share mode
2493  * blocks opening a file another time. Happens with Word 2007 temp files.
2494  * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2495  * open is denied with NT_STATUS_SHARING_VIOLATION.
2496  */
2497
2498 static bool run_locktest8(int dummy)
2499 {
2500         struct cli_state *cli1;
2501         const char *fname = "\\lockt8.lck";
2502         uint16_t fnum1, fnum2;
2503         char buf[200];
2504         bool correct = False;
2505         NTSTATUS status;
2506
2507         if (!torture_open_connection(&cli1, 0)) {
2508                 return False;
2509         }
2510
2511         cli_sockopt(cli1, sockops);
2512
2513         printf("starting locktest8\n");
2514
2515         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2516
2517         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2518                           &fnum1);
2519         if (!NT_STATUS_IS_OK(status)) {
2520                 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2521                 return false;
2522         }
2523
2524         memset(buf, 0, sizeof(buf));
2525
2526         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2527         if (!NT_STATUS_IS_OK(status)) {
2528                 d_fprintf(stderr, "cli_openx second time returned %s\n",
2529                           nt_errstr(status));
2530                 goto fail;
2531         }
2532
2533         status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2534         if (!NT_STATUS_IS_OK(status)) {
2535                 printf("Unable to apply read lock on range 1:1, error was "
2536                        "%s\n", nt_errstr(status));
2537                 goto fail;
2538         }
2539
2540         status = cli_close(cli1, fnum1);
2541         if (!NT_STATUS_IS_OK(status)) {
2542                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2543                 goto fail;
2544         }
2545
2546         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2547         if (!NT_STATUS_IS_OK(status)) {
2548                 d_fprintf(stderr, "cli_openx third time returned %s\n",
2549                           nt_errstr(status));
2550                 goto fail;
2551         }
2552
2553         correct = true;
2554
2555 fail:
2556         cli_close(cli1, fnum1);
2557         cli_close(cli1, fnum2);
2558         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2559         torture_close_connection(cli1);
2560
2561         printf("finished locktest8\n");
2562         return correct;
2563 }
2564
2565 /*
2566  * This test is designed to be run in conjunction with
2567  * external NFS or POSIX locks taken in the filesystem.
2568  * It checks that the smbd server will block until the
2569  * lock is released and then acquire it. JRA.
2570  */
2571
2572 static bool got_alarm;
2573 static struct cli_state *alarm_cli;
2574
2575 static void alarm_handler(int dummy)
2576 {
2577         got_alarm = True;
2578 }
2579
2580 static void alarm_handler_parent(int dummy)
2581 {
2582         cli_state_disconnect(alarm_cli);
2583 }
2584
2585 static void do_local_lock(int read_fd, int write_fd)
2586 {
2587         int fd;
2588         char c = '\0';
2589         struct flock lock;
2590         const char *local_pathname = NULL;
2591         int ret;
2592
2593         local_pathname = talloc_asprintf(talloc_tos(),
2594                         "%s/lockt9.lck", local_path);
2595         if (!local_pathname) {
2596                 printf("child: alloc fail\n");
2597                 exit(1);
2598         }
2599
2600         unlink(local_pathname);
2601         fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2602         if (fd == -1) {
2603                 printf("child: open of %s failed %s.\n",
2604                         local_pathname, strerror(errno));
2605                 exit(1);
2606         }
2607
2608         /* Now take a fcntl lock. */
2609         lock.l_type = F_WRLCK;
2610         lock.l_whence = SEEK_SET;
2611         lock.l_start = 0;
2612         lock.l_len = 4;
2613         lock.l_pid = getpid();
2614
2615         ret = fcntl(fd,F_SETLK,&lock);
2616         if (ret == -1) {
2617                 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2618                         local_pathname, strerror(errno));
2619                 exit(1);
2620         } else {
2621                 printf("child: got lock 0:4 on file %s.\n",
2622                         local_pathname );
2623                 fflush(stdout);
2624         }
2625
2626         CatchSignal(SIGALRM, alarm_handler);
2627         alarm(5);
2628         /* Signal the parent. */
2629         if (write(write_fd, &c, 1) != 1) {
2630                 printf("child: start signal fail %s.\n",
2631                         strerror(errno));
2632                 exit(1);
2633         }
2634         alarm(0);
2635
2636         alarm(10);
2637         /* Wait for the parent to be ready. */
2638         if (read(read_fd, &c, 1) != 1) {
2639                 printf("child: reply signal fail %s.\n",
2640                         strerror(errno));
2641                 exit(1);
2642         }
2643         alarm(0);
2644
2645         sleep(5);
2646         close(fd);
2647         printf("child: released lock 0:4 on file %s.\n",
2648                 local_pathname );
2649         fflush(stdout);
2650         exit(0);
2651 }
2652
2653 static bool run_locktest9(int dummy)
2654 {
2655         struct cli_state *cli1;
2656         const char *fname = "\\lockt9.lck";
2657         uint16_t fnum;
2658         bool correct = False;
2659         int pipe_in[2], pipe_out[2];
2660         pid_t child_pid;
2661         char c = '\0';
2662         int ret;
2663         struct timeval start;
2664         double seconds;
2665         NTSTATUS status;
2666
2667         printf("starting locktest9\n");
2668
2669         if (local_path == NULL) {
2670                 d_fprintf(stderr, "locktest9 must be given a local path via -l <localpath>\n");
2671                 return false;
2672         }
2673
2674         if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2675                 return false;
2676         }
2677
2678         child_pid = fork();
2679         if (child_pid == -1) {
2680                 return false;
2681         }
2682
2683         if (child_pid == 0) {
2684                 /* Child. */
2685                 do_local_lock(pipe_out[0], pipe_in[1]);
2686                 exit(0);
2687         }
2688
2689         close(pipe_out[0]);
2690         close(pipe_in[1]);
2691         pipe_out[0] = -1;
2692         pipe_in[1] = -1;
2693
2694         /* Parent. */
2695         ret = read(pipe_in[0], &c, 1);
2696         if (ret != 1) {
2697                 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2698                         strerror(errno));
2699                 return false;
2700         }
2701
2702         if (!torture_open_connection(&cli1, 0)) {
2703                 return false;
2704         }
2705
2706         cli_sockopt(cli1, sockops);
2707
2708         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE,
2709                           &fnum);
2710         if (!NT_STATUS_IS_OK(status)) {
2711                 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2712                 return false;
2713         }
2714
2715         /* Ensure the child has the lock. */
2716         status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2717         if (NT_STATUS_IS_OK(status)) {
2718                 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2719                 goto fail;
2720         } else {
2721                 d_printf("Child has the lock.\n");
2722         }
2723
2724         /* Tell the child to wait 5 seconds then exit. */
2725         ret = write(pipe_out[1], &c, 1);
2726         if (ret != 1) {
2727                 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2728                         strerror(errno));
2729                 goto fail;
2730         }
2731
2732         /* Wait 20 seconds for the lock. */
2733         alarm_cli = cli1;
2734         CatchSignal(SIGALRM, alarm_handler_parent);
2735         alarm(20);
2736
2737         start = timeval_current();
2738
2739         status = cli_lock32(cli1, fnum, 0, 4, -1, WRITE_LOCK);
2740         if (!NT_STATUS_IS_OK(status)) {
2741                 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2742                        "%s\n", nt_errstr(status));
2743                 goto fail_nofd;
2744         }
2745         alarm(0);
2746
2747         seconds = timeval_elapsed(&start);
2748
2749         printf("Parent got the lock after %.2f seconds.\n",
2750                 seconds);
2751
2752         status = cli_close(cli1, fnum);
2753         if (!NT_STATUS_IS_OK(status)) {
2754                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2755                 goto fail;
2756         }
2757
2758         correct = true;
2759
2760 fail:
2761         cli_close(cli1, fnum);
2762         torture_close_connection(cli1);
2763
2764 fail_nofd:
2765
2766         printf("finished locktest9\n");
2767         return correct;
2768 }
2769
2770 /*
2771 test whether fnums and tids open on one VC are available on another (a major
2772 security hole)
2773 */
2774 static bool run_fdpasstest(int dummy)
2775 {
2776         struct cli_state *cli1, *cli2;
2777         const char *fname = "\\fdpass.tst";
2778         uint16_t fnum1;
2779         char buf[1024];
2780         NTSTATUS status;
2781
2782         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2783                 return False;
2784         }
2785         cli_sockopt(cli1, sockops);
2786         cli_sockopt(cli2, sockops);
2787
2788         printf("starting fdpasstest\n");
2789
2790         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2791
2792         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
2793                           &fnum1);
2794         if (!NT_STATUS_IS_OK(status)) {
2795                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2796                 return False;
2797         }
2798
2799         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
2800                               13, NULL);
2801         if (!NT_STATUS_IS_OK(status)) {
2802                 printf("write failed (%s)\n", nt_errstr(status));
2803                 return False;
2804         }
2805
2806         cli_state_set_uid(cli2, cli_state_get_uid(cli1));
2807         cli_state_set_tid(cli2, cli_state_get_tid(cli1));
2808         cli_setpid(cli2, cli_getpid(cli1));
2809
2810         if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
2811                 printf("read succeeded! nasty security hole [%s]\n", buf);
2812                 return false;
2813         }
2814
2815         cli_close(cli1, fnum1);
2816         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2817
2818         torture_close_connection(cli1);
2819         torture_close_connection(cli2);
2820
2821         printf("finished fdpasstest\n");
2822         return True;
2823 }
2824
2825 static bool run_fdsesstest(int dummy)
2826 {
2827         struct cli_state *cli;
2828         uint16 new_vuid;
2829         uint16 saved_vuid;
2830         uint16 new_cnum;
2831         uint16 saved_cnum;
2832         const char *fname = "\\fdsess.tst";
2833         const char *fname1 = "\\fdsess1.tst";
2834         uint16_t fnum1;
2835         uint16_t fnum2;
2836         char buf[1024];
2837         bool ret = True;
2838         NTSTATUS status;
2839
2840         if (!torture_open_connection(&cli, 0))
2841                 return False;
2842         cli_sockopt(cli, sockops);
2843
2844         if (!torture_cli_session_setup2(cli, &new_vuid))
2845                 return False;
2846
2847         saved_cnum = cli_state_get_tid(cli);
2848         if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", "", 1)))
2849                 return False;
2850         new_cnum = cli_state_get_tid(cli);
2851         cli_state_set_tid(cli, saved_cnum);
2852
2853         printf("starting fdsesstest\n");
2854
2855         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2856         cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2857
2858         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2859         if (!NT_STATUS_IS_OK(status)) {
2860                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2861                 return False;
2862         }
2863
2864         status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
2865                               NULL);
2866         if (!NT_STATUS_IS_OK(status)) {
2867                 printf("write failed (%s)\n", nt_errstr(status));
2868                 return False;
2869         }
2870
2871         saved_vuid = cli_state_get_uid(cli);
2872         cli_state_set_uid(cli, new_vuid);
2873
2874         if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2875                 printf("read succeeded with different vuid! "
2876                        "nasty security hole [%s]\n", buf);
2877                 ret = false;
2878         }
2879         /* Try to open a file with different vuid, samba cnum. */
2880         if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
2881                 printf("create with different vuid, same cnum succeeded.\n");
2882                 cli_close(cli, fnum2);
2883                 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2884         } else {
2885                 printf("create with different vuid, same cnum failed.\n");
2886                 printf("This will cause problems with service clients.\n");
2887                 ret = False;
2888         }
2889
2890         cli_state_set_uid(cli, saved_vuid);
2891
2892         /* Try with same vuid, different cnum. */
2893         cli_state_set_tid(cli, new_cnum);
2894
2895         if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2896                 printf("read succeeded with different cnum![%s]\n", buf);
2897                 ret = false;
2898         }
2899
2900         cli_state_set_tid(cli, saved_cnum);
2901         cli_close(cli, fnum1);
2902         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2903
2904         torture_close_connection(cli);
2905
2906         printf("finished fdsesstest\n");
2907         return ret;
2908 }
2909
2910 /*
2911   This test checks that 
2912
2913   1) the server does not allow an unlink on a file that is open
2914 */
2915 static bool run_unlinktest(int dummy)
2916 {
2917         struct cli_state *cli;
2918         const char *fname = "\\unlink.tst";
2919         uint16_t fnum;
2920         bool correct = True;
2921         NTSTATUS status;
2922
2923         if (!torture_open_connection(&cli, 0)) {
2924                 return False;
2925         }
2926
2927         cli_sockopt(cli, sockops);
2928
2929         printf("starting unlink test\n");
2930
2931         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2932
2933         cli_setpid(cli, 1);
2934
2935         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2936         if (!NT_STATUS_IS_OK(status)) {
2937                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2938                 return False;
2939         }
2940
2941         status = cli_unlink(cli, fname,
2942                             FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2943         if (NT_STATUS_IS_OK(status)) {
2944                 printf("error: server allowed unlink on an open file\n");
2945                 correct = False;
2946         } else {
2947                 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
2948                                       NT_STATUS_SHARING_VIOLATION);
2949         }
2950
2951         cli_close(cli, fnum);
2952         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2953
2954         if (!torture_close_connection(cli)) {
2955                 correct = False;
2956         }
2957
2958         printf("unlink test finished\n");
2959
2960         return correct;
2961 }
2962
2963
2964 /*
2965 test how many open files this server supports on the one socket
2966 */
2967 static bool run_maxfidtest(int dummy)
2968 {
2969         struct cli_state *cli;
2970         fstring fname;
2971         uint16_t fnums[0x11000];
2972         int i;
2973         int retries=4;
2974         bool correct = True;
2975         NTSTATUS status;
2976
2977         cli = current_cli;
2978
2979         if (retries <= 0) {
2980                 printf("failed to connect\n");
2981                 return False;
2982         }
2983
2984         cli_sockopt(cli, sockops);
2985
2986         for (i=0; i<0x11000; i++) {
2987                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2988                 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
2989                                   &fnums[i]);
2990                 if (!NT_STATUS_IS_OK(status)) {
2991                         printf("open of %s failed (%s)\n", 
2992                                fname, nt_errstr(status));
2993                         printf("maximum fnum is %d\n", i);
2994                         break;
2995                 }
2996                 printf("%6d\r", i);
2997         }
2998         printf("%6d\n", i);
2999         i--;
3000
3001         printf("cleaning up\n");
3002         for (;i>=0;i--) {
3003                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3004                 cli_close(cli, fnums[i]);
3005
3006                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3007                 if (!NT_STATUS_IS_OK(status)) {
3008                         printf("unlink of %s failed (%s)\n", 
3009                                fname, nt_errstr(status));
3010                         correct = False;
3011                 }
3012                 printf("%6d\r", i);
3013         }
3014         printf("%6d\n", 0);
3015
3016         printf("maxfid test finished\n");
3017         if (!torture_close_connection(cli)) {
3018                 correct = False;
3019         }
3020         return correct;
3021 }
3022
3023 /* generate a random buffer */
3024 static void rand_buf(char *buf, int len)
3025 {
3026         while (len--) {
3027                 *buf = (char)sys_random();
3028                 buf++;
3029         }
3030 }
3031
3032 /* send smb negprot commands, not reading the response */
3033 static bool run_negprot_nowait(int dummy)
3034 {
3035         struct tevent_context *ev;
3036         int i;
3037         struct cli_state *cli;
3038         bool correct = True;
3039
3040         printf("starting negprot nowait test\n");
3041
3042         ev = tevent_context_init(talloc_tos());
3043         if (ev == NULL) {
3044                 return false;
3045         }
3046
3047         if (!(cli = open_nbt_connection())) {
3048                 TALLOC_FREE(ev);
3049                 return False;
3050         }
3051
3052         for (i=0;i<50000;i++) {
3053                 struct tevent_req *req;
3054
3055                 req = cli_negprot_send(ev, ev, cli, PROTOCOL_NT1);
3056                 if (req == NULL) {
3057                         TALLOC_FREE(ev);
3058                         return false;
3059                 }
3060                 if (!tevent_req_poll(req, ev)) {
3061                         d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3062                                   strerror(errno));
3063                         TALLOC_FREE(ev);
3064                         return false;
3065                 }
3066                 TALLOC_FREE(req);
3067         }
3068
3069         if (torture_close_connection(cli)) {
3070                 correct = False;
3071         }
3072
3073         printf("finished negprot nowait test\n");
3074
3075         return correct;
3076 }
3077
3078 /* send smb negprot commands, not reading the response */
3079 static bool run_bad_nbt_session(int dummy)
3080 {
3081         struct nmb_name called, calling;
3082         struct sockaddr_storage ss;
3083         NTSTATUS status;
3084         int fd;
3085         bool ret;
3086
3087         printf("starting bad nbt session test\n");
3088
3089         make_nmb_name(&calling, myname, 0x0);
3090         make_nmb_name(&called , host, 0x20);
3091
3092         if (!resolve_name(host, &ss, 0x20, true)) {
3093                 d_fprintf(stderr, "Could not resolve name %s\n", host);
3094                 return false;
3095         }
3096
3097         status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
3098         if (!NT_STATUS_IS_OK(status)) {
3099                 d_fprintf(stderr, "open_socket_out failed: %s\n",
3100                           nt_errstr(status));
3101                 return false;
3102         }
3103
3104         ret = cli_bad_session_request(fd, &calling, &called);
3105         close(fd);
3106         if (!ret) {
3107                 d_fprintf(stderr, "open_socket_out failed: %s\n",
3108                           nt_errstr(status));
3109                 return false;
3110         }
3111
3112         printf("finished bad nbt session test\n");
3113         return true;
3114 }
3115
3116 /* send random IPC commands */
3117 static bool run_randomipc(int dummy)
3118 {
3119         char *rparam = NULL;
3120         char *rdata = NULL;
3121         unsigned int rdrcnt,rprcnt;
3122         char param[1024];
3123         int api, param_len, i;
3124         struct cli_state *cli;
3125         bool correct = True;
3126         int count = 50000;
3127
3128         printf("starting random ipc test\n");
3129
3130         if (!torture_open_connection(&cli, 0)) {
3131                 return False;
3132         }
3133
3134         for (i=0;i<count;i++) {
3135                 api = sys_random() % 500;
3136                 param_len = (sys_random() % 64);
3137
3138                 rand_buf(param, param_len);
3139
3140                 SSVAL(param,0,api); 
3141
3142                 cli_api(cli, 
3143                         param, param_len, 8,  
3144                         NULL, 0, BUFFER_SIZE, 
3145                         &rparam, &rprcnt,     
3146                         &rdata, &rdrcnt);
3147                 if (i % 100 == 0) {
3148                         printf("%d/%d\r", i,count);
3149                 }
3150         }
3151         printf("%d/%d\n", i, count);
3152
3153         if (!torture_close_connection(cli)) {
3154                 correct = False;
3155         }
3156
3157         printf("finished random ipc test\n");
3158
3159         return correct;
3160 }
3161
3162
3163
3164 static void browse_callback(const char *sname, uint32 stype, 
3165                             const char *comment, void *state)
3166 {
3167         printf("\t%20.20s %08x %s\n", sname, stype, comment);
3168 }
3169
3170
3171
3172 /*
3173   This test checks the browse list code
3174
3175 */
3176 static bool run_browsetest(int dummy)
3177 {
3178         static struct cli_state *cli;
3179         bool correct = True;
3180
3181         printf("starting browse test\n");
3182
3183         if (!torture_open_connection(&cli, 0)) {
3184                 return False;
3185         }
3186
3187         printf("domain list:\n");
3188         cli_NetServerEnum(cli, cli->server_domain, 
3189                           SV_TYPE_DOMAIN_ENUM,
3190                           browse_callback, NULL);
3191
3192         printf("machine list:\n");
3193         cli_NetServerEnum(cli, cli->server_domain, 
3194                           SV_TYPE_ALL,
3195                           browse_callback, NULL);
3196
3197         if (!torture_close_connection(cli)) {
3198                 correct = False;
3199         }
3200
3201         printf("browse test finished\n");
3202
3203         return correct;
3204
3205 }
3206
3207
3208 /*
3209   This checks how the getatr calls works
3210 */
3211 static bool run_attrtest(int dummy)
3212 {
3213         struct cli_state *cli;
3214         uint16_t fnum;
3215         time_t t, t2;
3216         const char *fname = "\\attrib123456789.tst";
3217         bool correct = True;
3218         NTSTATUS status;
3219
3220         printf("starting attrib test\n");
3221
3222         if (!torture_open_connection(&cli, 0)) {
3223                 return False;
3224         }
3225
3226         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3227         cli_openx(cli, fname, 
3228                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3229         cli_close(cli, fnum);
3230
3231         status = cli_getatr(cli, fname, NULL, NULL, &t);
3232         if (!NT_STATUS_IS_OK(status)) {
3233                 printf("getatr failed (%s)\n", nt_errstr(status));
3234                 correct = False;
3235         }
3236
3237         if (abs(t - time(NULL)) > 60*60*24*10) {
3238                 printf("ERROR: SMBgetatr bug. time is %s",
3239                        ctime(&t));
3240                 t = time(NULL);
3241                 correct = True;
3242         }
3243
3244         t2 = t-60*60*24; /* 1 day ago */
3245
3246         status = cli_setatr(cli, fname, 0, t2);
3247         if (!NT_STATUS_IS_OK(status)) {
3248                 printf("setatr failed (%s)\n", nt_errstr(status));
3249                 correct = True;
3250         }
3251
3252         status = cli_getatr(cli, fname, NULL, NULL, &t);
3253         if (!NT_STATUS_IS_OK(status)) {
3254                 printf("getatr failed (%s)\n", nt_errstr(status));
3255                 correct = True;
3256         }
3257
3258         if (t != t2) {
3259                 printf("ERROR: getatr/setatr bug. times are\n%s",
3260                        ctime(&t));
3261                 printf("%s", ctime(&t2));
3262                 correct = True;
3263         }
3264
3265         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3266
3267         if (!torture_close_connection(cli)) {
3268                 correct = False;
3269         }
3270
3271         printf("attrib test finished\n");
3272
3273         return correct;
3274 }
3275
3276
3277 /*
3278   This checks a couple of trans2 calls
3279 */
3280 static bool run_trans2test(int dummy)
3281 {
3282         struct cli_state *cli;
3283         uint16_t fnum;
3284         off_t size;
3285         time_t c_time, a_time, m_time;
3286         struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
3287         const char *fname = "\\trans2.tst";
3288         const char *dname = "\\trans2";
3289         const char *fname2 = "\\trans2\\trans2.tst";
3290         char *pname;
3291         bool correct = True;
3292         NTSTATUS status;
3293         uint32_t fs_attr;
3294
3295         printf("starting trans2 test\n");
3296
3297         if (!torture_open_connection(&cli, 0)) {
3298                 return False;
3299         }
3300
3301         status = cli_get_fs_attr_info(cli, &fs_attr);
3302         if (!NT_STATUS_IS_OK(status)) {
3303                 printf("ERROR: cli_get_fs_attr_info returned %s\n",
3304                        nt_errstr(status));
3305                 correct = false;
3306         }
3307
3308         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3309         cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3310         status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
3311                                      &a_time_ts, &w_time_ts, &m_time_ts, NULL);
3312         if (!NT_STATUS_IS_OK(status)) {
3313                 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
3314                 correct = False;
3315         }
3316
3317         status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
3318         if (!NT_STATUS_IS_OK(status)) {
3319                 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
3320                 correct = False;
3321         }
3322
3323         if (strcmp(pname, fname)) {
3324                 printf("qfilename gave different name? [%s] [%s]\n",
3325                        fname, pname);
3326                 correct = False;
3327         }
3328
3329         cli_close(cli, fnum);
3330
3331         sleep(2);
3332
3333         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3334         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
3335                           &fnum);
3336         if (!NT_STATUS_IS_OK(status)) {
3337                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3338                 return False;
3339         }
3340         cli_close(cli, fnum);
3341
3342         status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
3343                                 NULL);
3344         if (!NT_STATUS_IS_OK(status)) {
3345                 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
3346                 correct = False;
3347         } else {
3348                 time_t t = time(NULL);
3349
3350                 if (c_time != m_time) {
3351                         printf("create time=%s", ctime(&c_time));
3352                         printf("modify time=%s", ctime(&m_time));
3353                         printf("This system appears to have sticky create times\n");
3354                 }
3355                 if ((abs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
3356                         printf("access time=%s", ctime(&a_time));
3357                         printf("This system appears to set a midnight access time\n");
3358                         correct = False;
3359                 }
3360
3361                 if (abs(m_time - t) > 60*60*24*7) {
3362                         printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
3363                         correct = False;
3364                 }
3365         }
3366
3367
3368         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3369         cli_openx(cli, fname, 
3370                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3371         cli_close(cli, fnum);
3372         status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
3373                                 &m_time_ts, &size, NULL, NULL);
3374         if (!NT_STATUS_IS_OK(status)) {
3375                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3376                 correct = False;
3377         } else {
3378                 if (w_time_ts.tv_sec < 60*60*24*2) {
3379                         printf("write time=%s", ctime(&w_time_ts.tv_sec));
3380                         printf("This system appears to set a initial 0 write time\n");
3381                         correct = False;
3382                 }
3383         }
3384
3385         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3386
3387
3388         /* check if the server updates the directory modification time
3389            when creating a new file */
3390         status = cli_mkdir(cli, dname);
3391         if (!NT_STATUS_IS_OK(status)) {
3392                 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
3393                 correct = False;
3394         }
3395         sleep(3);
3396         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3397                                 &w_time_ts, &m_time_ts, &size, NULL, NULL);
3398         if (!NT_STATUS_IS_OK(status)) {
3399                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3400                 correct = False;
3401         }
3402
3403         cli_openx(cli, fname2, 
3404                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3405         cli_writeall(cli, fnum,  0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
3406         cli_close(cli, fnum);
3407         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3408                                 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
3409         if (!NT_STATUS_IS_OK(status)) {
3410                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3411                 correct = False;
3412         } else {
3413                 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
3414                     == 0) {
3415                         printf("This system does not update directory modification times\n");
3416                         correct = False;
3417                 }
3418         }
3419         cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3420         cli_rmdir(cli, dname);
3421
3422         if (!torture_close_connection(cli)) {
3423                 correct = False;
3424         }
3425
3426         printf("trans2 test finished\n");
3427
3428         return correct;
3429 }
3430
3431 /*
3432   This checks new W2K calls.
3433 */
3434
3435 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
3436 {
3437         uint8_t *buf = NULL;
3438         uint32 len;
3439         NTSTATUS status;
3440
3441         status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
3442                                CLI_BUFFER_SIZE, NULL, &buf, &len);
3443         if (!NT_STATUS_IS_OK(status)) {
3444                 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
3445                        nt_errstr(status));
3446         } else {
3447                 printf("qfileinfo: level %d, len = %u\n", level, len);
3448                 dump_data(0, (uint8 *)buf, len);
3449                 printf("\n");
3450         }
3451         TALLOC_FREE(buf);
3452         return status;
3453 }
3454
3455 static bool run_w2ktest(int dummy)
3456 {
3457         struct cli_state *cli;
3458         uint16_t fnum;
3459         const char *fname = "\\w2ktest\\w2k.tst";
3460         int level;
3461         bool correct = True;
3462
3463         printf("starting w2k test\n");
3464
3465         if (!torture_open_connection(&cli, 0)) {
3466                 return False;
3467         }
3468
3469         cli_openx(cli, fname, 
3470                         O_RDWR | O_CREAT , DENY_NONE, &fnum);
3471
3472         for (level = 1004; level < 1040; level++) {
3473                 new_trans(cli, fnum, level);
3474         }
3475
3476         cli_close(cli, fnum);
3477
3478         if (!torture_close_connection(cli)) {
3479                 correct = False;
3480         }
3481
3482         printf("w2k test finished\n");
3483
3484         return correct;
3485 }
3486
3487
3488 /*
3489   this is a harness for some oplock tests
3490  */
3491 static bool run_oplock1(int dummy)
3492 {
3493         struct cli_state *cli1;
3494         const char *fname = "\\lockt1.lck";
3495         uint16_t fnum1;
3496         bool correct = True;
3497         NTSTATUS status;
3498
3499         printf("starting oplock test 1\n");
3500
3501         if (!torture_open_connection(&cli1, 0)) {
3502                 return False;
3503         }
3504
3505         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3506
3507         cli_sockopt(cli1, sockops);
3508
3509         cli1->use_oplocks = True;
3510
3511         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3512                           &fnum1);
3513         if (!NT_STATUS_IS_OK(status)) {
3514                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3515                 return False;
3516         }
3517
3518         cli1->use_oplocks = False;
3519
3520         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3521         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3522
3523         status = cli_close(cli1, fnum1);
3524         if (!NT_STATUS_IS_OK(status)) {
3525                 printf("close2 failed (%s)\n", nt_errstr(status));
3526                 return False;
3527         }
3528
3529         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3530         if (!NT_STATUS_IS_OK(status)) {
3531                 printf("unlink failed (%s)\n", nt_errstr(status));
3532                 return False;
3533         }
3534
3535         if (!torture_close_connection(cli1)) {
3536                 correct = False;
3537         }
3538
3539         printf("finished oplock test 1\n");
3540
3541         return correct;
3542 }
3543
3544 static bool run_oplock2(int dummy)
3545 {
3546         struct cli_state *cli1, *cli2;
3547         const char *fname = "\\lockt2.lck";
3548         uint16_t fnum1, fnum2;
3549         int saved_use_oplocks = use_oplocks;
3550         char buf[4];
3551         bool correct = True;
3552         volatile bool *shared_correct;
3553         size_t nread;
3554         NTSTATUS status;
3555
3556         shared_correct = (volatile bool *)shm_setup(sizeof(bool));
3557         *shared_correct = True;
3558
3559         use_level_II_oplocks = True;
3560         use_oplocks = True;
3561
3562         printf("starting oplock test 2\n");
3563
3564         if (!torture_open_connection(&cli1, 0)) {
3565                 use_level_II_oplocks = False;
3566                 use_oplocks = saved_use_oplocks;
3567                 return False;
3568         }
3569
3570         if (!torture_open_connection(&cli2, 1)) {
3571                 use_level_II_oplocks = False;
3572                 use_oplocks = saved_use_oplocks;
3573                 return False;
3574         }
3575
3576         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3577
3578         cli_sockopt(cli1, sockops);
3579         cli_sockopt(cli2, sockops);
3580
3581         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3582                           &fnum1);
3583         if (!NT_STATUS_IS_OK(status)) {
3584                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3585                 return False;
3586         }
3587
3588         /* Don't need the globals any more. */
3589         use_level_II_oplocks = False;
3590         use_oplocks = saved_use_oplocks;
3591
3592         if (fork() == 0) {
3593                 /* Child code */
3594                 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
3595                 if (!NT_STATUS_IS_OK(status)) {
3596                         printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
3597                         *shared_correct = False;
3598                         exit(0);
3599                 }
3600
3601                 sleep(2);
3602
3603                 status = cli_close(cli2, fnum2);
3604                 if (!NT_STATUS_IS_OK(status)) {
3605                         printf("close2 failed (%s)\n", nt_errstr(status));
3606                         *shared_correct = False;
3607                 }
3608
3609                 exit(0);
3610         }
3611
3612         sleep(2);
3613
3614         /* Ensure cli1 processes the break. Empty file should always return 0
3615          * bytes.  */
3616         status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
3617         if (!NT_STATUS_IS_OK(status)) {
3618                 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
3619                 correct = false;
3620         } else if (nread != 0) {
3621                 printf("read on empty fnum1 failed. recv %ld expected %d\n",
3622                       (unsigned long)nread, 0);
3623                 correct = false;
3624         }
3625
3626         /* Should now be at level II. */
3627         /* Test if sending a write locks causes a break to none. */
3628         status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
3629         if (!NT_STATUS_IS_OK(status)) {
3630                 printf("lock failed (%s)\n", nt_errstr(status));
3631                 correct = False;
3632         }
3633
3634         cli_unlock(cli1, fnum1, 0, 4);
3635
3636         sleep(2);
3637
3638         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
3639         if (!NT_STATUS_IS_OK(status)) {
3640                 printf("lock failed (%s)\n", nt_errstr(status));
3641                 correct = False;
3642         }
3643
3644         cli_unlock(cli1, fnum1, 0, 4);
3645
3646         sleep(2);
3647
3648         cli_read(cli1, fnum1, buf, 0, 4, NULL);
3649
3650         status = cli_close(cli1, fnum1);
3651         if (!NT_STATUS_IS_OK(status)) {
3652                 printf("close1 failed (%s)\n", nt_errstr(status));
3653                 correct = False;
3654         }
3655
3656         sleep(4);
3657
3658         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3659         if (!NT_STATUS_IS_OK(status)) {
3660                 printf("unlink failed (%s)\n", nt_errstr(status));
3661                 correct = False;
3662         }
3663
3664         if (!torture_close_connection(cli1)) {
3665                 correct = False;
3666         }
3667
3668         if (!*shared_correct) {
3669                 correct = False;
3670         }
3671
3672         printf("finished oplock test 2\n");
3673
3674         return correct;
3675 }
3676
3677 struct oplock4_state {
3678         struct tevent_context *ev;
3679         struct cli_state *cli;
3680         bool *got_break;
3681         uint16_t *fnum2;
3682 };
3683
3684 static void oplock4_got_break(struct tevent_req *req);
3685 static void oplock4_got_open(struct tevent_req *req);
3686
3687 static bool run_oplock4(int dummy)
3688 {
3689         struct tevent_context *ev;
3690         struct cli_state *cli1, *cli2;
3691         struct tevent_req *oplock_req, *open_req;
3692         const char *fname = "\\lockt4.lck";
3693         const char *fname_ln = "\\lockt4_ln.lck";
3694         uint16_t fnum1, fnum2;
3695         int saved_use_oplocks = use_oplocks;
3696         NTSTATUS status;
3697         bool correct = true;
3698
3699         bool got_break;
3700
3701         struct oplock4_state *state;
3702
3703         printf("starting oplock test 4\n");
3704
3705         if (!torture_open_connection(&cli1, 0)) {
3706                 use_level_II_oplocks = false;
3707                 use_oplocks = saved_use_oplocks;
3708                 return false;
3709         }
3710
3711         if (!torture_open_connection(&cli2, 1)) {
3712                 use_level_II_oplocks = false;
3713                 use_oplocks = saved_use_oplocks;
3714                 return false;
3715         }
3716
3717         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3718         cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3719
3720         cli_sockopt(cli1, sockops);
3721         cli_sockopt(cli2, sockops);
3722
3723         /* Create the file. */
3724         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3725                           &fnum1);
3726         if (!NT_STATUS_IS_OK(status)) {
3727                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3728                 return false;
3729         }
3730
3731         status = cli_close(cli1, fnum1);
3732         if (!NT_STATUS_IS_OK(status)) {
3733                 printf("close1 failed (%s)\n", nt_errstr(status));
3734                 return false;
3735         }
3736
3737         /* Now create a hardlink. */
3738         status = cli_nt_hardlink(cli1, fname, fname_ln);
3739         if (!NT_STATUS_IS_OK(status)) {
3740                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
3741                 return false;
3742         }
3743
3744         /* Prove that opening hardlinks cause deny modes to conflict. */
3745         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
3746         if (!NT_STATUS_IS_OK(status)) {
3747                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3748                 return false;
3749         }
3750
3751         status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
3752         if (NT_STATUS_IS_OK(status)) {
3753                 printf("open of %s succeeded - should fail with sharing violation.\n",
3754                         fname_ln);
3755                 return false;
3756         }
3757
3758         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3759                 printf("open of %s should fail with sharing violation. Got %s\n",
3760                         fname_ln, nt_errstr(status));
3761                 return false;
3762         }
3763
3764         status = cli_close(cli1, fnum1);
3765         if (!NT_STATUS_IS_OK(status)) {
3766                 printf("close1 failed (%s)\n", nt_errstr(status));
3767                 return false;
3768         }
3769
3770         cli1->use_oplocks = true;
3771         cli2->use_oplocks = true;
3772
3773         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3774         if (!NT_STATUS_IS_OK(status)) {
3775                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3776                 return false;
3777         }
3778
3779         ev = tevent_context_init(talloc_tos());
3780         if (ev == NULL) {
3781                 printf("tevent_context_init failed\n");
3782                 return false;
3783         }
3784
3785         state = talloc(ev, struct oplock4_state);
3786         if (state == NULL) {
3787                 printf("talloc failed\n");
3788                 return false;
3789         }
3790         state->ev = ev;
3791         state->cli = cli1;
3792         state->got_break = &got_break;
3793         state->fnum2 = &fnum2;
3794
3795         oplock_req = cli_smb_oplock_break_waiter_send(
3796                 talloc_tos(), ev, cli1);
3797         if (oplock_req == NULL) {
3798                 printf("cli_smb_oplock_break_waiter_send failed\n");
3799                 return false;
3800         }
3801         tevent_req_set_callback(oplock_req, oplock4_got_break, state);
3802
3803         open_req = cli_openx_send(
3804                 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
3805         if (open_req == NULL) {
3806                 printf("cli_openx_send failed\n");
3807                 return false;
3808         }
3809         tevent_req_set_callback(open_req, oplock4_got_open, state);
3810
3811         got_break = false;
3812         fnum2 = 0xffff;
3813
3814         while (!got_break || fnum2 == 0xffff) {
3815                 int ret;
3816                 ret = tevent_loop_once(ev);
3817                 if (ret == -1) {
3818                         printf("tevent_loop_once failed: %s\n",
3819                                strerror(errno));
3820                         return false;
3821                 }
3822         }
3823
3824         status = cli_close(cli2, fnum2);
3825         if (!NT_STATUS_IS_OK(status)) {
3826                 printf("close2 failed (%s)\n", nt_errstr(status));
3827                 correct = false;
3828         }
3829
3830         status = cli_close(cli1, fnum1);
3831         if (!NT_STATUS_IS_OK(status)) {
3832                 printf("close1 failed (%s)\n", nt_errstr(status));
3833                 correct = false;
3834         }
3835
3836         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3837         if (!NT_STATUS_IS_OK(status)) {
3838                 printf("unlink failed (%s)\n", nt_errstr(status));
3839                 correct = false;
3840         }
3841
3842         status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3843         if (!NT_STATUS_IS_OK(status)) {
3844                 printf("unlink failed (%s)\n", nt_errstr(status));
3845                 correct = false;
3846         }
3847
3848         if (!torture_close_connection(cli1)) {
3849                 correct = false;
3850         }
3851
3852         if (!got_break) {
3853                 correct = false;
3854         }
3855
3856         printf("finished oplock test 4\n");
3857
3858         return correct;
3859 }
3860
3861 static void oplock4_got_break(struct tevent_req *req)
3862 {
3863         struct oplock4_state *state = tevent_req_callback_data(
3864                 req, struct oplock4_state);
3865         uint16_t fnum;
3866         uint8_t level;
3867         NTSTATUS status;
3868
3869         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
3870         TALLOC_FREE(req);
3871         if (!NT_STATUS_IS_OK(status)) {
3872                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
3873                        nt_errstr(status));
3874                 return;
3875         }
3876         *state->got_break = true;
3877
3878         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
3879                                   NO_OPLOCK);
3880         if (req == NULL) {
3881                 printf("cli_oplock_ack_send failed\n");
3882                 return;
3883         }
3884 }
3885
3886 static void oplock4_got_open(struct tevent_req *req)
3887 {
3888         struct oplock4_state *state = tevent_req_callback_data(
3889                 req, struct oplock4_state);
3890         NTSTATUS status;
3891
3892         status = cli_openx_recv(req, state->fnum2);
3893         if (!NT_STATUS_IS_OK(status)) {
3894                 printf("cli_openx_recv returned %s\n", nt_errstr(status));
3895                 *state->fnum2 = 0xffff;
3896         }
3897 }
3898
3899 /*
3900   Test delete on close semantics.
3901  */
3902 static bool run_deletetest(int dummy)
3903 {
3904         struct cli_state *cli1 = NULL;
3905         struct cli_state *cli2 = NULL;
3906         const char *fname = "\\delete.file";
3907         uint16_t fnum1 = (uint16_t)-1;
3908         uint16_t fnum2 = (uint16_t)-1;
3909         bool correct = True;
3910         NTSTATUS status;
3911
3912         printf("starting delete test\n");
3913
3914         if (!torture_open_connection(&cli1, 0)) {
3915                 return False;
3916         }
3917
3918         cli_sockopt(cli1, sockops);
3919
3920         /* Test 1 - this should delete the file on close. */
3921
3922         cli_setatr(cli1, fname, 0, 0);
3923         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3924
3925         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
3926                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
3927                               FILE_DELETE_ON_CLOSE, 0, &fnum1);
3928         if (!NT_STATUS_IS_OK(status)) {
3929                 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
3930                 correct = False;
3931                 goto fail;
3932         }
3933
3934         status = cli_close(cli1, fnum1);
3935         if (!NT_STATUS_IS_OK(status)) {
3936                 printf("[1] close failed (%s)\n", nt_errstr(status));
3937                 correct = False;
3938                 goto fail;
3939         }
3940
3941         if (NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1))) {
3942                 printf("[1] open of %s succeeded (should fail)\n", fname);
3943                 correct = False;
3944                 goto fail;
3945         }
3946
3947         printf("first delete on close test succeeded.\n");
3948
3949         /* Test 2 - this should delete the file on close. */
3950
3951         cli_setatr(cli1, fname, 0, 0);
3952         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3953
3954         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3955                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
3956                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
3957         if (!NT_STATUS_IS_OK(status)) {
3958                 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
3959                 correct = False;
3960                 goto fail;
3961         }
3962
3963         status = cli_nt_delete_on_close(cli1, fnum1, true);
3964         if (!NT_STATUS_IS_OK(status)) {
3965                 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
3966                 correct = False;
3967                 goto fail;
3968         }
3969
3970         status = cli_close(cli1, fnum1);
3971         if (!NT_STATUS_IS_OK(status)) {
3972                 printf("[2] close failed (%s)\n", nt_errstr(status));
3973                 correct = False;
3974                 goto fail;
3975         }
3976
3977         if (NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3978                 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
3979                 status = cli_close(cli1, fnum1);
3980                 if (!NT_STATUS_IS_OK(status)) {
3981                         printf("[2] close failed (%s)\n", nt_errstr(status));
3982                         correct = False;
3983                         goto fail;
3984                 }
3985                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3986         } else
3987                 printf("second delete on close test succeeded.\n");
3988
3989         /* Test 3 - ... */
3990         cli_setatr(cli1, fname, 0, 0);
3991         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3992
3993         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3994                               FILE_ATTRIBUTE_NORMAL,
3995                               FILE_SHARE_READ|FILE_SHARE_WRITE,
3996                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
3997         if (!NT_STATUS_IS_OK(status)) {
3998                 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
3999                 correct = False;
4000                 goto fail;
4001         }
4002
4003         /* This should fail with a sharing violation - open for delete is only compatible
4004            with SHARE_DELETE. */
4005
4006         if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4007                         FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, 0, &fnum2))) {
4008                 printf("[3] open  - 2 of %s succeeded - should have failed.\n", fname);
4009                 correct = False;
4010                 goto fail;
4011         }
4012
4013         /* This should succeed. */
4014         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4015                              FILE_ATTRIBUTE_NORMAL,
4016                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4017                              FILE_OPEN, 0, 0, &fnum2);
4018         if (!NT_STATUS_IS_OK(status)) {
4019                 printf("[3] open  - 2 of %s failed (%s)\n", fname, nt_errstr(status));
4020                 correct = False;
4021                 goto fail;
4022         }
4023
4024         status = cli_nt_delete_on_close(cli1, fnum1, true);
4025         if (!NT_STATUS_IS_OK(status)) {
4026                 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
4027                 correct = False;
4028                 goto fail;
4029         }
4030
4031         status = cli_close(cli1, fnum1);
4032         if (!NT_STATUS_IS_OK(status)) {
4033                 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
4034                 correct = False;
4035                 goto fail;
4036         }
4037
4038         status = cli_close(cli1, fnum2);
4039         if (!NT_STATUS_IS_OK(status)) {
4040                 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
4041                 correct = False;
4042                 goto fail;
4043         }
4044
4045         /* This should fail - file should no longer be there. */
4046
4047         if (NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
4048                 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
4049                 status = cli_close(cli1, fnum1);
4050                 if (!NT_STATUS_IS_OK(status)) {
4051                         printf("[3] close failed (%s)\n", nt_errstr(status));
4052                 }
4053                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4054                 correct = False;
4055                 goto fail;
4056         } else
4057                 printf("third delete on close test succeeded.\n");
4058
4059         /* Test 4 ... */
4060         cli_setatr(cli1, fname, 0, 0);
4061         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4062
4063         status = cli_ntcreate(cli1, fname, 0,
4064                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4065                               FILE_ATTRIBUTE_NORMAL,
4066                               FILE_SHARE_READ|FILE_SHARE_WRITE,
4067                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4068         if (!NT_STATUS_IS_OK(status)) {
4069                 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
4070                 correct = False;
4071                 goto fail;
4072         }
4073
4074         /* This should succeed. */
4075         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4076                              FILE_ATTRIBUTE_NORMAL,
4077                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4078                              FILE_OPEN, 0, 0, &fnum2);
4079         if (!NT_STATUS_IS_OK(status)) {
4080                 printf("[4] open  - 2 of %s failed (%s)\n", fname, nt_errstr(status));
4081                 correct = False;
4082                 goto fail;
4083         }
4084
4085         status = cli_close(cli1, fnum2);
4086         if (!NT_STATUS_IS_OK(status)) {
4087                 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
4088                 correct = False;
4089                 goto fail;
4090         }
4091
4092         status = cli_nt_delete_on_close(cli1, fnum1, true);
4093         if (!NT_STATUS_IS_OK(status)) {
4094                 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
4095                 correct = False;
4096                 goto fail;
4097         }
4098
4099         /* This should fail - no more opens once delete on close set. */
4100         if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4101                                    FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4102                                    FILE_OPEN, 0, 0, &fnum2))) {
4103                 printf("[4] open  - 3 of %s succeeded ! Should have failed.\n", fname );
4104                 correct = False;
4105                 goto fail;
4106         } else
4107                 printf("fourth delete on close test succeeded.\n");
4108
4109         status = cli_close(cli1, fnum1);
4110         if (!NT_STATUS_IS_OK(status)) {
4111                 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
4112                 correct = False;
4113                 goto fail;
4114         }
4115
4116         /* Test 5 ... */
4117         cli_setatr(cli1, fname, 0, 0);
4118         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4119
4120         status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
4121         if (!NT_STATUS_IS_OK(status)) {
4122                 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4123                 correct = False;
4124                 goto fail;
4125         }
4126
4127         /* This should fail - only allowed on NT opens with DELETE access. */
4128
4129         if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4130                 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
4131                 correct = False;
4132                 goto fail;
4133         }
4134
4135         status = cli_close(cli1, fnum1);
4136         if (!NT_STATUS_IS_OK(status)) {
4137                 printf("[5] close - 2 failed (%s)\n", nt_errstr(status));
4138                 correct = False;
4139                 goto fail;
4140         }
4141
4142         printf("fifth delete on close test succeeded.\n");
4143
4144         /* Test 6 ... */
4145         cli_setatr(cli1, fname, 0, 0);
4146         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4147
4148         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4149                              FILE_ATTRIBUTE_NORMAL,
4150                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4151                              FILE_OVERWRITE_IF, 0, 0, &fnum1);
4152         if (!NT_STATUS_IS_OK(status)) {
4153                 printf("[6] open of %s failed (%s)\n", fname,
4154                        nt_errstr(status));
4155                 correct = False;
4156                 goto fail;
4157         }
4158
4159         /* This should fail - only allowed on NT opens with DELETE access. */
4160
4161         if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4162                 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
4163                 correct = False;
4164                 goto fail;
4165         }
4166
4167         status = cli_close(cli1, fnum1);
4168         if (!NT_STATUS_IS_OK(status)) {
4169                 printf("[6] close - 2 failed (%s)\n", nt_errstr(status));
4170                 correct = False;
4171                 goto fail;
4172         }
4173
4174         printf("sixth delete on close test succeeded.\n");
4175
4176         /* Test 7 ... */
4177         cli_setatr(cli1, fname, 0, 0);
4178         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4179
4180         status = cli_ntcreate(cli1, fname, 0,
4181                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4182                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
4183                               0, 0, &fnum1);
4184         if (!NT_STATUS_IS_OK(status)) {
4185                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4186                 correct = False;
4187                 goto fail;
4188         }
4189
4190         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4191                 printf("[7] setting delete_on_close on file failed !\n");
4192                 correct = False;
4193                 goto fail;
4194         }
4195
4196         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, false))) {
4197                 printf("[7] unsetting delete_on_close on file failed !\n");
4198                 correct = False;
4199                 goto fail;
4200         }
4201
4202         status = cli_close(cli1, fnum1);
4203         if (!NT_STATUS_IS_OK(status)) {
4204                 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4205                 correct = False;
4206                 goto fail;
4207         }
4208
4209         /* This next open should succeed - we reset the flag. */
4210         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4211         if (!NT_STATUS_IS_OK(status)) {
4212                 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4213                 correct = False;
4214                 goto fail;
4215         }
4216
4217         status = cli_close(cli1, fnum1);
4218         if (!NT_STATUS_IS_OK(status)) {
4219                 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4220                 correct = False;
4221                 goto fail;
4222         }
4223
4224         printf("seventh delete on close test succeeded.\n");
4225
4226         /* Test 7 ... */
4227         cli_setatr(cli1, fname, 0, 0);
4228         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4229
4230         if (!torture_open_connection(&cli2, 1)) {
4231                 printf("[8] failed to open second connection.\n");
4232                 correct = False;
4233                 goto fail;
4234         }
4235
4236         cli_sockopt(cli1, sockops);
4237
4238         status = cli_ntcreate(cli1, fname, 0,
4239                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4240                              FILE_ATTRIBUTE_NORMAL,
4241                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4242                              FILE_OVERWRITE_IF, 0, 0, &fnum1);
4243         if (!NT_STATUS_IS_OK(status)) {
4244                 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4245                 correct = False;
4246                 goto fail;
4247         }
4248
4249         status = cli_ntcreate(cli2, fname, 0,
4250                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4251                              FILE_ATTRIBUTE_NORMAL,
4252                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4253                              FILE_OPEN, 0, 0, &fnum2);
4254         if (!NT_STATUS_IS_OK(status)) {
4255                 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4256                 correct = False;
4257                 goto fail;
4258         }
4259
4260         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4261                 printf("[8] setting delete_on_close on file failed !\n");
4262                 correct = False;
4263                 goto fail;
4264         }
4265
4266         status = cli_close(cli1, fnum1);
4267         if (!NT_STATUS_IS_OK(status)) {
4268                 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
4269                 correct = False;
4270                 goto fail;
4271         }
4272
4273         status = cli_close(cli2, fnum2);
4274         if (!NT_STATUS_IS_OK(status)) {
4275                 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
4276                 correct = False;
4277                 goto fail;
4278         }
4279
4280         /* This should fail.. */
4281         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4282         if (NT_STATUS_IS_OK(status)) {
4283                 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
4284                 goto fail;
4285                 correct = False;
4286         } else
4287                 printf("eighth delete on close test succeeded.\n");
4288
4289         /* This should fail - we need to set DELETE_ACCESS. */
4290         if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0,FILE_READ_DATA|FILE_WRITE_DATA,
4291                                    FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE, 0, &fnum1))) {
4292                 printf("[9] open of %s succeeded should have failed!\n", fname);
4293                 correct = False;
4294                 goto fail;
4295         }
4296
4297         printf("ninth delete on close test succeeded.\n");
4298
4299         status = cli_ntcreate(cli1, fname, 0,
4300                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4301                              FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4302                              FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
4303                              0, &fnum1);
4304         if (!NT_STATUS_IS_OK(status)) {
4305                 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
4306                 correct = False;
4307                 goto fail;
4308         }
4309
4310         /* This should delete the file. */
4311         status = cli_close(cli1, fnum1);
4312         if (!NT_STATUS_IS_OK(status)) {
4313                 printf("[10] close failed (%s)\n", nt_errstr(status));
4314                 correct = False;
4315                 goto fail;
4316         }
4317
4318         /* This should fail.. */
4319         if (NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
4320                 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
4321                 goto fail;
4322                 correct = False;
4323         } else
4324                 printf("tenth delete on close test succeeded.\n");
4325
4326         cli_setatr(cli1, fname, 0, 0);
4327         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4328
4329         /* What error do we get when attempting to open a read-only file with
4330            delete access ? */
4331
4332         /* Create a readonly file. */
4333         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4334                               FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
4335                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4336         if (!NT_STATUS_IS_OK(status)) {
4337                 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
4338                 correct = False;
4339                 goto fail;
4340         }
4341
4342         status = cli_close(cli1, fnum1);
4343         if (!NT_STATUS_IS_OK(status)) {
4344                 printf("[11] close failed (%s)\n", nt_errstr(status));
4345                 correct = False;
4346                 goto fail;
4347         }
4348
4349         /* Now try open for delete access. */
4350         status = cli_ntcreate(cli1, fname, 0,
4351                              FILE_READ_ATTRIBUTES|DELETE_ACCESS,
4352                              0,
4353                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4354                              FILE_OVERWRITE_IF, 0, 0, &fnum1);
4355         if (NT_STATUS_IS_OK(status)) {
4356                 printf("[11] open of %s succeeded should have been denied with ACCESS_DENIED!\n", fname);
4357                 cli_close(cli1, fnum1);
4358                 goto fail;
4359                 correct = False;
4360         } else {
4361                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
4362                         printf("[11] open of %s should have been denied with ACCESS_DENIED! Got error %s\n", fname, nt_errstr(status));
4363                         goto fail;
4364                         correct = False;
4365                 } else {
4366                         printf("eleventh delete on close test succeeded.\n");
4367                 }
4368         }
4369
4370         printf("finished delete test\n");
4371
4372   fail:
4373         /* FIXME: This will crash if we aborted before cli2 got
4374          * intialized, because these functions don't handle
4375          * uninitialized connections. */
4376
4377         if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
4378         if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
4379         cli_setatr(cli1, fname, 0, 0);
4380         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4381
4382         if (cli1 && !torture_close_connection(cli1)) {
4383                 correct = False;
4384         }
4385         if (cli2 && !torture_close_connection(cli2)) {
4386                 correct = False;
4387         }
4388         return correct;
4389 }
4390
4391 static bool run_deletetest_ln(int dummy)
4392 {
4393         struct cli_state *cli;
4394         const char *fname = "\\delete1";
4395         const char *fname_ln = "\\delete1_ln";
4396         uint16_t fnum;
4397         uint16_t fnum1;
4398         NTSTATUS status;
4399         bool correct = true;
4400         time_t t;
4401
4402         printf("starting deletetest-ln\n");
4403
4404         if (!torture_open_connection(&cli, 0)) {
4405                 return false;
4406         }
4407
4408         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4409         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4410
4411         cli_sockopt(cli, sockops);
4412
4413         /* Create the file. */
4414         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
4415         if (!NT_STATUS_IS_OK(status)) {
4416                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4417                 return false;
4418         }
4419
4420         status = cli_close(cli, fnum);
4421         if (!NT_STATUS_IS_OK(status)) {
4422                 printf("close1 failed (%s)\n", nt_errstr(status));
4423                 return false;
4424         }
4425
4426         /* Now create a hardlink. */
4427         status = cli_nt_hardlink(cli, fname, fname_ln);
4428         if (!NT_STATUS_IS_OK(status)) {
4429                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4430                 return false;
4431         }
4432
4433         /* Open the original file. */
4434         status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
4435                         FILE_ATTRIBUTE_NORMAL,
4436                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4437                         FILE_OPEN_IF, 0, 0, &fnum);
4438         if (!NT_STATUS_IS_OK(status)) {
4439                 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
4440                 return false;
4441         }
4442
4443         /* Unlink the hard link path. */
4444         status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
4445                         FILE_ATTRIBUTE_NORMAL,
4446                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4447                         FILE_OPEN_IF, 0, 0, &fnum1);
4448         if (!NT_STATUS_IS_OK(status)) {
4449                 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
4450                 return false;
4451         }
4452         status = cli_nt_delete_on_close(cli, fnum1, true);
4453         if (!NT_STATUS_IS_OK(status)) {
4454                 d_printf("(%s) failed to set delete_on_close %s: %s\n",
4455                         __location__, fname_ln, nt_errstr(status));
4456                 return false;
4457         }
4458
4459         status = cli_close(cli, fnum1);
4460         if (!NT_STATUS_IS_OK(status)) {
4461                 printf("close %s failed (%s)\n",
4462                         fname_ln, nt_errstr(status));
4463                 return false;
4464         }
4465
4466         status = cli_close(cli, fnum);
4467         if (!NT_STATUS_IS_OK(status)) {
4468                 printf("close %s failed (%s)\n",
4469                         fname, nt_errstr(status));
4470                 return false;
4471         }
4472
4473         /* Ensure the original file is still there. */
4474         status = cli_getatr(cli, fname, NULL, NULL, &t);
4475         if (!NT_STATUS_IS_OK(status)) {
4476                 printf("%s getatr on file %s failed (%s)\n",
4477                         __location__,
4478                         fname,
4479                         nt_errstr(status));
4480                 correct = False;
4481         }
4482
4483         /* Ensure the link path is gone. */
4484         status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
4485         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4486                 printf("%s, getatr for file %s returned wrong error code %s "
4487                         "- should have been deleted\n",
4488                         __location__,
4489                         fname_ln, nt_errstr(status));
4490                 correct = False;
4491         }
4492
4493         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4494         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4495
4496         if (!torture_close_connection(cli)) {
4497                 correct = false;
4498         }
4499
4500         printf("finished deletetest-ln\n");
4501
4502         return correct;
4503 }
4504
4505 /*
4506   print out server properties
4507  */
4508 static bool run_properties(int dummy)
4509 {
4510         struct cli_state *cli;
4511         bool correct = True;
4512
4513         printf("starting properties test\n");
4514
4515         ZERO_STRUCT(cli);
4516
4517         if (!torture_open_connection(&cli, 0)) {
4518                 return False;
4519         }
4520
4521         cli_sockopt(cli, sockops);
4522
4523         d_printf("Capabilities 0x%08x\n", cli_state_capabilities(cli));
4524
4525         if (!torture_close_connection(cli)) {
4526                 correct = False;
4527         }
4528
4529         return correct;
4530 }
4531
4532
4533
4534 /* FIRST_DESIRED_ACCESS   0xf019f */
4535 #define FIRST_DESIRED_ACCESS   FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
4536                                FILE_READ_EA|                           /* 0xf */ \
4537                                FILE_WRITE_EA|FILE_READ_ATTRIBUTES|     /* 0x90 */ \
4538                                FILE_WRITE_ATTRIBUTES|                  /* 0x100 */ \
4539                                DELETE_ACCESS|READ_CONTROL_ACCESS|\
4540                                WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS     /* 0xf0000 */
4541 /* SECOND_DESIRED_ACCESS  0xe0080 */
4542 #define SECOND_DESIRED_ACCESS  FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
4543                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4544                                WRITE_OWNER_ACCESS                      /* 0xe0000 */
4545
4546 #if 0
4547 #define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
4548                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4549                                FILE_READ_DATA|\
4550                                WRITE_OWNER_ACCESS                      /* */
4551 #endif
4552
4553 /*
4554   Test ntcreate calls made by xcopy
4555  */
4556 static bool run_xcopy(int dummy)
4557 {
4558         static struct cli_state *cli1;
4559         const char *fname = "\\test.txt";
4560         bool correct = True;
4561         uint16_t fnum1, fnum2;
4562         NTSTATUS status;
4563
4564         printf("starting xcopy test\n");
4565
4566         if (!torture_open_connection(&cli1, 0)) {
4567                 return False;
4568         }
4569
4570         status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
4571                               FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
4572                               FILE_OVERWRITE_IF, 0x4044, 0, &fnum1);
4573         if (!NT_STATUS_IS_OK(status)) {
4574                 printf("First open failed - %s\n", nt_errstr(status));
4575                 return False;
4576         }
4577
4578         status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
4579                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4580                              FILE_OPEN, 0x200000, 0, &fnum2);
4581         if (!NT_STATUS_IS_OK(status)) {
4582                 printf("second open failed - %s\n", nt_errstr(status));
4583                 return False;
4584         }
4585
4586         if (!torture_close_connection(cli1)) {
4587                 correct = False;
4588         }
4589
4590         return correct;
4591 }
4592
4593 /*
4594   Test rename on files open with share delete and no share delete.
4595  */
4596 static bool run_rename(int dummy)
4597 {
4598         static struct cli_state *cli1;
4599         const char *fname = "\\test.txt";
4600         const char *fname1 = "\\test1.txt";
4601         bool correct = True;
4602         uint16_t fnum1;
4603         uint16_t attr;
4604         NTSTATUS status;
4605
4606         printf("starting rename test\n");
4607
4608         if (!torture_open_connection(&cli1, 0)) {
4609                 return False;
4610         }
4611
4612         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4613         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4614
4615         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4616                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
4617                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4618         if (!NT_STATUS_IS_OK(status)) {
4619                 printf("First open failed - %s\n", nt_errstr(status));
4620                 return False;
4621         }
4622
4623         status = cli_rename(cli1, fname, fname1);
4624         if (!NT_STATUS_IS_OK(status)) {
4625                 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
4626         } else {
4627                 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
4628                 correct = False;
4629         }
4630
4631         status = cli_close(cli1, fnum1);
4632         if (!NT_STATUS_IS_OK(status)) {
4633                 printf("close - 1 failed (%s)\n", nt_errstr(status));
4634                 return False;
4635         }
4636
4637         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4638         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4639         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4640 #if 0
4641                               FILE_SHARE_DELETE|FILE_SHARE_NONE,
4642 #else
4643                               FILE_SHARE_DELETE|FILE_SHARE_READ,
4644 #endif
4645                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4646         if (!NT_STATUS_IS_OK(status)) {
4647                 printf("Second open failed - %s\n", nt_errstr(status));
4648                 return False;
4649         }
4650
4651         status = cli_rename(cli1, fname, fname1);
4652         if (!NT_STATUS_IS_OK(status)) {
4653                 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
4654                 correct = False;
4655         } else {
4656                 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
4657         }
4658
4659         status = cli_close(cli1, fnum1);
4660         if (!NT_STATUS_IS_OK(status)) {
4661                 printf("close - 2 failed (%s)\n", nt_errstr(status));
4662                 return False;
4663         }
4664
4665         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4666         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4667
4668         status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
4669                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4670                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4671         if (!NT_STATUS_IS_OK(status)) {
4672                 printf("Third open failed - %s\n", nt_errstr(status));
4673                 return False;
4674         }
4675
4676
4677 #if 0
4678   {
4679         uint16_t fnum2;
4680
4681         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
4682                                    FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4683                 printf("Fourth open failed - %s\n", cli_errstr(cli1));
4684                 return False;
4685         }
4686         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum2, true))) {
4687                 printf("[8] setting delete_on_close on file failed !\n");
4688                 return False;
4689         }
4690
4691         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
4692                 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
4693                 return False;
4694         }
4695   }
4696 #endif
4697
4698         status = cli_rename(cli1, fname, fname1);
4699         if (!NT_STATUS_IS_OK(status)) {
4700                 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
4701                 correct = False;
4702         } else {
4703                 printf("Third rename succeeded (SHARE_NONE)\n");
4704         }
4705
4706         status = cli_close(cli1, fnum1);
4707         if (!NT_STATUS_IS_OK(status)) {
4708                 printf("close - 3 failed (%s)\n", nt_errstr(status));
4709                 return False;
4710         }
4711
4712         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4713         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4714
4715         /*----*/
4716
4717         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4718                               FILE_ATTRIBUTE_NORMAL,
4719                               FILE_SHARE_READ | FILE_SHARE_WRITE,
4720                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4721         if (!NT_STATUS_IS_OK(status)) {
4722                 printf("Fourth open failed - %s\n", nt_errstr(status));
4723                 return False;
4724         }
4725
4726         status = cli_rename(cli1, fname, fname1);
4727         if (!NT_STATUS_IS_OK(status)) {
4728                 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
4729         } else {
4730                 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
4731                 correct = False;
4732         }
4733
4734         status = cli_close(cli1, fnum1);
4735         if (!NT_STATUS_IS_OK(status)) {
4736                 printf("close - 4 failed (%s)\n", nt_errstr(status));
4737                 return False;
4738         }
4739
4740         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4741         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4742
4743         /*--*/
4744
4745         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4746                          FILE_ATTRIBUTE_NORMAL,
4747                          FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4748                          FILE_OVERWRITE_IF, 0, 0, &fnum1);
4749         if (!NT_STATUS_IS_OK(status)) {
4750                 printf("Fifth open failed - %s\n", nt_errstr(status));
4751                 return False;
4752         }
4753
4754         status = cli_rename(cli1, fname, fname1);
4755         if (!NT_STATUS_IS_OK(status)) {
4756                 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
4757                 correct = False;
4758         } else {
4759                 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
4760         }
4761
4762         /*
4763          * Now check if the first name still exists ...
4764          */
4765
4766         /* if (!NT_STATUS_OP(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4767                                    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4768           printf("Opening original file after rename of open file fails: %s\n",
4769               cli_errstr(cli1));
4770         }
4771         else {
4772           printf("Opening original file after rename of open file works ...\n");
4773           (void)cli_close(cli1, fnum2);
4774           } */
4775
4776         /*--*/
4777         status = cli_close(cli1, fnum1);
4778         if (!NT_STATUS_IS_OK(status)) {
4779                 printf("close - 5 failed (%s)\n", nt_errstr(status));
4780                 return False;
4781         }
4782
4783         /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
4784         status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
4785         if (!NT_STATUS_IS_OK(status)) {
4786                 printf("getatr on file %s failed - %s ! \n",
4787                         fname1, nt_errstr(status));
4788                 correct = False;
4789         } else {
4790                 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
4791                         printf("Renamed file %s has wrong attr 0x%x "
4792                                 "(should be 0x%x)\n",
4793                                 fname1,
4794                                 attr,
4795                                 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
4796                         correct = False;
4797                 } else {
4798                         printf("Renamed file %s has archive bit set\n", fname1);
4799                 }
4800         }
4801
4802         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4803         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4804
4805         if (!torture_close_connection(cli1)) {
4806                 correct = False;
4807         }
4808
4809         return correct;
4810 }
4811
4812 static bool run_pipe_number(int dummy)
4813 {
4814         struct cli_state *cli1;
4815         const char *pipe_name = "\\SPOOLSS";
4816         uint16_t fnum;
4817         int num_pipes = 0;
4818         NTSTATUS status;
4819
4820         printf("starting pipenumber test\n");
4821         if (!torture_open_connection(&cli1, 0)) {
4822                 return False;
4823         }
4824
4825         cli_sockopt(cli1, sockops);
4826         while(1) {
4827                 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
4828                                       FILE_ATTRIBUTE_NORMAL,
4829                                       FILE_SHARE_READ|FILE_SHARE_WRITE,
4830                                       FILE_OPEN_IF, 0, 0, &fnum);
4831                 if (!NT_STATUS_IS_OK(status)) {
4832                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
4833                         break;
4834                 }
4835                 num_pipes++;
4836                 printf("\r%6d", num_pipes);
4837         }
4838
4839         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
4840         torture_close_connection(cli1);
4841         return True;
4842 }
4843
4844 /*
4845   Test open mode returns on read-only files.
4846  */
4847 static bool run_opentest(int dummy)
4848 {
4849         static struct cli_state *cli1;
4850         static struct cli_state *cli2;
4851         const char *fname = "\\readonly.file";
4852         uint16_t fnum1, fnum2;
4853         char buf[20];
4854         off_t fsize;
4855         bool correct = True;
4856         char *tmp_path;
4857         NTSTATUS status;
4858
4859         printf("starting open test\n");
4860
4861         if (!torture_open_connection(&cli1, 0)) {
4862                 return False;
4863         }
4864
4865         cli_setatr(cli1, fname, 0, 0);
4866         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4867
4868         cli_sockopt(cli1, sockops);
4869
4870         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4871         if (!NT_STATUS_IS_OK(status)) {
4872                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4873                 return False;
4874         }
4875
4876         status = cli_close(cli1, fnum1);
4877         if (!NT_STATUS_IS_OK(status)) {
4878                 printf("close2 failed (%s)\n", nt_errstr(status));
4879                 return False;
4880         }
4881
4882         status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
4883         if (!NT_STATUS_IS_OK(status)) {
4884                 printf("cli_setatr failed (%s)\n", nt_errstr(status));
4885                 return False;
4886         }
4887
4888         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4889         if (!NT_STATUS_IS_OK(status)) {
4890                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4891                 return False;
4892         }
4893
4894         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
4895         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4896
4897         if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
4898                         NT_STATUS_ACCESS_DENIED)) {
4899                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
4900         }
4901
4902         printf("finished open test 1\n");
4903
4904         cli_close(cli1, fnum1);
4905
4906         /* Now try not readonly and ensure ERRbadshare is returned. */
4907
4908         cli_setatr(cli1, fname, 0, 0);
4909
4910         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4911         if (!NT_STATUS_IS_OK(status)) {
4912                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4913                 return False;
4914         }
4915
4916         /* This will fail - but the error should be ERRshare. */
4917         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4918
4919         if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
4920                         NT_STATUS_SHARING_VIOLATION)) {
4921                 printf("correct error code ERRDOS/ERRbadshare returned\n");
4922         }
4923
4924         status = cli_close(cli1, fnum1);
4925         if (!NT_STATUS_IS_OK(status)) {
4926                 printf("close2 failed (%s)\n", nt_errstr(status));
4927                 return False;
4928         }
4929
4930         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4931
4932         printf("finished open test 2\n");
4933
4934         /* Test truncate open disposition on file opened for read. */
4935         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4936         if (!NT_STATUS_IS_OK(status)) {
4937                 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
4938                 return False;
4939         }
4940
4941         /* write 20 bytes. */
4942
4943         memset(buf, '\0', 20);
4944
4945         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
4946         if (!NT_STATUS_IS_OK(status)) {
4947                 printf("write failed (%s)\n", nt_errstr(status));
4948                 correct = False;
4949         }
4950
4951         status = cli_close(cli1, fnum1);
4952         if (!NT_STATUS_IS_OK(status)) {
4953                 printf("(3) close1 failed (%s)\n", nt_errstr(status));
4954                 return False;
4955         }
4956
4957         /* Ensure size == 20. */
4958         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
4959         if (!NT_STATUS_IS_OK(status)) {
4960                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
4961                 return False;
4962         }
4963
4964         if (fsize != 20) {
4965                 printf("(3) file size != 20\n");
4966                 return False;
4967         }
4968
4969         /* Now test if we can truncate a file opened for readonly. */
4970         status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
4971         if (!NT_STATUS_IS_OK(status)) {
4972                 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
4973                 return False;
4974         }
4975
4976         status = cli_close(cli1, fnum1);
4977         if (!NT_STATUS_IS_OK(status)) {
4978                 printf("close2 failed (%s)\n", nt_errstr(status));
4979                 return False;
4980         }
4981
4982         /* Ensure size == 0. */
4983         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
4984         if (!NT_STATUS_IS_OK(status)) {
4985                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
4986                 return False;
4987         }
4988
4989         if (fsize != 0) {
4990                 printf("(3) file size != 0\n");
4991                 return False;
4992         }
4993         printf("finished open test 3\n");
4994
4995         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4996
4997         printf("Do ctemp tests\n");
4998         status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
4999         if (!NT_STATUS_IS_OK(status)) {
5000                 printf("ctemp failed (%s)\n", nt_errstr(status));
5001                 return False;
5002         }
5003
5004         printf("ctemp gave path %s\n", tmp_path);
5005         status = cli_close(cli1, fnum1);
5006         if (!NT_STATUS_IS_OK(status)) {
5007                 printf("close of temp failed (%s)\n", nt_errstr(status));
5008         }
5009
5010         status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5011         if (!NT_STATUS_IS_OK(status)) {
5012                 printf("unlink of temp failed (%s)\n", nt_errstr(status));
5013         }
5014
5015         /* Test the non-io opens... */
5016
5017         if (!torture_open_connection(&cli2, 1)) {
5018                 return False;
5019         }
5020
5021         cli_setatr(cli2, fname, 0, 0);
5022         cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5023
5024         cli_sockopt(cli2, sockops);
5025
5026         printf("TEST #1 testing 2 non-io opens (no delete)\n");
5027         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5028                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5029                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5030         if (!NT_STATUS_IS_OK(status)) {
5031                 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5032                 return False;
5033         }
5034
5035         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5036                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5037                               FILE_OPEN_IF, 0, 0, &fnum2);
5038         if (!NT_STATUS_IS_OK(status)) {
5039                 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5040                 return False;
5041         }
5042
5043         status = cli_close(cli1, fnum1);
5044         if (!NT_STATUS_IS_OK(status)) {
5045                 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5046                 return False;
5047         }
5048
5049         status = cli_close(cli2, fnum2);
5050         if (!NT_STATUS_IS_OK(status)) {
5051                 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5052                 return False;
5053         }
5054
5055         printf("non-io open test #1 passed.\n");
5056
5057         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5058
5059         printf("TEST #2 testing 2 non-io opens (first with delete)\n");
5060
5061         status = cli_ntcreate(cli1, fname, 0,
5062                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5063                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5064                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5065         if (!NT_STATUS_IS_OK(status)) {
5066                 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5067                 return False;
5068         }
5069
5070         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5071                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5072                               FILE_OPEN_IF, 0, 0, &fnum2);
5073         if (!NT_STATUS_IS_OK(status)) {
5074                 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5075                 return False;
5076         }
5077
5078         status = cli_close(cli1, fnum1);
5079         if (!NT_STATUS_IS_OK(status)) {
5080                 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5081                 return False;
5082         }
5083
5084         status = cli_close(cli2, fnum2);
5085         if (!NT_STATUS_IS_OK(status)) {
5086                 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5087                 return False;
5088         }
5089
5090         printf("non-io open test #2 passed.\n");
5091
5092         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5093
5094         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
5095
5096         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5097                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5098                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5099         if (!NT_STATUS_IS_OK(status)) {
5100                 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5101                 return False;
5102         }
5103
5104         status = cli_ntcreate(cli2, fname, 0,
5105                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5106                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5107                               FILE_OPEN_IF, 0, 0, &fnum2);
5108         if (!NT_STATUS_IS_OK(status)) {
5109                 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5110                 return False;
5111         }
5112
5113         status = cli_close(cli1, fnum1);
5114         if (!NT_STATUS_IS_OK(status)) {
5115                 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5116                 return False;
5117         }
5118
5119         status = cli_close(cli2, fnum2);
5120         if (!NT_STATUS_IS_OK(status)) {
5121                 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5122                 return False;
5123         }
5124
5125         printf("non-io open test #3 passed.\n");
5126
5127         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5128
5129         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
5130
5131         status = cli_ntcreate(cli1, fname, 0,
5132                                DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5133                                FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5134                                FILE_OVERWRITE_IF, 0, 0, &fnum1);
5135         if (!NT_STATUS_IS_OK(status)) {
5136                 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5137                 return False;
5138         }
5139
5140         status = cli_ntcreate(cli2, fname, 0,
5141                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5142                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5143                               FILE_OPEN_IF, 0, 0, &fnum2);
5144         if (NT_STATUS_IS_OK(status)) {
5145                 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5146                 return False;
5147         }
5148
5149         printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5150
5151         status = cli_close(cli1, fnum1);
5152         if (!NT_STATUS_IS_OK(status)) {
5153                 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5154                 return False;
5155         }
5156
5157         printf("non-io open test #4 passed.\n");
5158
5159         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5160
5161         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
5162
5163         status = cli_ntcreate(cli1, fname, 0,
5164                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5165                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5166                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5167         if (!NT_STATUS_IS_OK(status)) {
5168                 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5169                 return False;
5170         }
5171
5172         status = cli_ntcreate(cli2, fname, 0,
5173                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5174                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5175                               FILE_OPEN_IF, 0, 0, &fnum2);
5176         if (!NT_STATUS_IS_OK(status)) {
5177                 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5178                 return False;
5179         }
5180
5181         status = cli_close(cli1, fnum1);
5182         if (!NT_STATUS_IS_OK(status)) {
5183                 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5184                 return False;
5185         }
5186
5187         status = cli_close(cli2, fnum2);
5188         if (!NT_STATUS_IS_OK(status)) {
5189                 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5190                 return False;
5191         }
5192
5193         printf("non-io open test #5 passed.\n");
5194
5195         printf("TEST #6 testing 1 non-io open, one io open\n");
5196
5197         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5198
5199         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5200                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5201                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5202         if (!NT_STATUS_IS_OK(status)) {
5203                 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5204                 return False;
5205         }
5206
5207         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5208                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
5209                               FILE_OPEN_IF, 0, 0, &fnum2);
5210         if (!NT_STATUS_IS_OK(status)) {
5211                 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5212                 return False;
5213         }
5214
5215         status = cli_close(cli1, fnum1);
5216         if (!NT_STATUS_IS_OK(status)) {
5217                 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5218                 return False;
5219         }
5220
5221         status = cli_close(cli2, fnum2);
5222         if (!NT_STATUS_IS_OK(status)) {
5223                 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5224                 return False;
5225         }
5226
5227         printf("non-io open test #6 passed.\n");
5228
5229         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
5230
5231         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5232
5233         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5234                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5235                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5236         if (!NT_STATUS_IS_OK(status)) {
5237                 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5238                 return False;
5239         }
5240
5241         status = cli_ntcreate(cli2, fname, 0,
5242                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5243                               FILE_ATTRIBUTE_NORMAL,
5244                               FILE_SHARE_READ|FILE_SHARE_DELETE,
5245                               FILE_OPEN_IF, 0, 0, &fnum2);
5246         if (NT_STATUS_IS_OK(status)) {
5247                 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5248                 return False;
5249         }
5250
5251         printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5252
5253         status = cli_close(cli1, fnum1);
5254         if (!NT_STATUS_IS_OK(status)) {
5255                 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5256                 return False;
5257         }
5258
5259         printf("non-io open test #7 passed.\n");
5260
5261         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5262
5263         printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
5264         status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
5265                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5266                                 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5267         if (!NT_STATUS_IS_OK(status)) {
5268                 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
5269                 correct = false;
5270                 goto out;
5271         }
5272
5273         /* Write to ensure we have to update the file time. */
5274         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5275                               NULL);
5276         if (!NT_STATUS_IS_OK(status)) {
5277                 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
5278                 correct = false;
5279                 goto out;
5280         }
5281
5282         status = cli_close(cli1, fnum1);
5283         if (!NT_STATUS_IS_OK(status)) {
5284                 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
5285                 correct = false;
5286         }
5287
5288   out:
5289
5290         if (!torture_close_connection(cli1)) {
5291                 correct = False;
5292         }
5293         if (!torture_close_connection(cli2)) {
5294                 correct = False;
5295         }
5296
5297         return correct;
5298 }
5299
5300 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
5301 {
5302         uint16 major, minor;
5303         uint32 caplow, caphigh;
5304         NTSTATUS status;
5305
5306         if (!SERVER_HAS_UNIX_CIFS(cli)) {
5307                 printf("Server doesn't support UNIX CIFS extensions.\n");
5308                 return NT_STATUS_NOT_SUPPORTED;
5309         }
5310
5311         status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
5312                                              &caphigh);
5313         if (!NT_STATUS_IS_OK(status)) {
5314                 printf("Server didn't return UNIX CIFS extensions: %s\n",
5315                        nt_errstr(status));
5316                 return status;
5317         }
5318
5319         status = cli_set_unix_extensions_capabilities(cli, major, minor,
5320                                                       caplow, caphigh);
5321         if (!NT_STATUS_IS_OK(status)) {
5322                 printf("Server doesn't support setting UNIX CIFS extensions: "
5323                        "%s.\n", nt_errstr(status));
5324                 return status;
5325         }
5326
5327         return NT_STATUS_OK;
5328 }
5329
5330 /*
5331   Test POSIX open /mkdir calls.
5332  */
5333 static bool run_simple_posix_open_test(int dummy)
5334 {
5335         static struct cli_state *cli1;
5336         const char *fname = "posix:file";
5337         const char *hname = "posix:hlink";
5338         const char *sname = "posix:symlink";
5339         const char *dname = "posix:dir";
5340         char buf[10];
5341         char namebuf[11];
5342         uint16_t fnum1 = (uint16_t)-1;
5343         SMB_STRUCT_STAT sbuf;
5344         bool correct = false;
5345         NTSTATUS status;
5346         size_t nread;
5347
5348         printf("Starting simple POSIX open test\n");
5349
5350         if (!torture_open_connection(&cli1, 0)) {
5351                 return false;
5352         }
5353
5354         cli_sockopt(cli1, sockops);
5355
5356         status = torture_setup_unix_extensions(cli1);
5357         if (!NT_STATUS_IS_OK(status)) {
5358                 return false;
5359         }
5360
5361         cli_setatr(cli1, fname, 0, 0);
5362         cli_posix_unlink(cli1, fname);
5363         cli_setatr(cli1, dname, 0, 0);
5364         cli_posix_rmdir(cli1, dname);
5365         cli_setatr(cli1, hname, 0, 0);
5366         cli_posix_unlink(cli1, hname);
5367         cli_setatr(cli1, sname, 0, 0);
5368         cli_posix_unlink(cli1, sname);
5369
5370         /* Create a directory. */
5371         status = cli_posix_mkdir(cli1, dname, 0777);
5372         if (!NT_STATUS_IS_OK(status)) {
5373                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
5374                 goto out;
5375         }
5376
5377         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5378                                 0600, &fnum1);
5379         if (!NT_STATUS_IS_OK(status)) {
5380                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5381                 goto out;
5382         }
5383
5384         /* Test ftruncate - set file size. */
5385         status = cli_ftruncate(cli1, fnum1, 1000);
5386         if (!NT_STATUS_IS_OK(status)) {
5387                 printf("ftruncate failed (%s)\n", nt_errstr(status));
5388                 goto out;
5389         }
5390
5391         /* Ensure st_size == 1000 */
5392         status = cli_posix_stat(cli1, fname, &sbuf);
5393         if (!NT_STATUS_IS_OK(status)) {
5394                 printf("stat failed (%s)\n", nt_errstr(status));
5395                 goto out;
5396         }
5397
5398         if (sbuf.st_ex_size != 1000) {
5399                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5400                 goto out;
5401         }
5402
5403         /* Test ftruncate - set file size back to zero. */
5404         status = cli_ftruncate(cli1, fnum1, 0);
5405         if (!NT_STATUS_IS_OK(status)) {
5406                 printf("ftruncate failed (%s)\n", nt_errstr(status));
5407                 goto out;
5408         }
5409
5410         status = cli_close(cli1, fnum1);
5411         if (!NT_STATUS_IS_OK(status)) {
5412                 printf("close failed (%s)\n", nt_errstr(status));
5413                 goto out;
5414         }
5415
5416         /* Now open the file again for read only. */
5417         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5418         if (!NT_STATUS_IS_OK(status)) {
5419                 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
5420                 goto out;
5421         }
5422
5423         /* Now unlink while open. */
5424         status = cli_posix_unlink(cli1, fname);
5425         if (!NT_STATUS_IS_OK(status)) {
5426                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5427                 goto out;
5428         }
5429
5430         status = cli_close(cli1, fnum1);
5431         if (!NT_STATUS_IS_OK(status)) {
5432                 printf("close(2) failed (%s)\n", nt_errstr(status));
5433                 goto out;
5434         }
5435
5436         /* Ensure the file has gone. */
5437         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5438         if (NT_STATUS_IS_OK(status)) {
5439                 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
5440                 goto out;
5441         }
5442
5443         /* Create again to test open with O_TRUNC. */
5444         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
5445         if (!NT_STATUS_IS_OK(status)) {
5446                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5447                 goto out;
5448         }
5449
5450         /* Test ftruncate - set file size. */
5451         status = cli_ftruncate(cli1, fnum1, 1000);
5452         if (!NT_STATUS_IS_OK(status)) {
5453                 printf("ftruncate failed (%s)\n", nt_errstr(status));
5454                 goto out;
5455         }
5456
5457         /* Ensure st_size == 1000 */
5458         status = cli_posix_stat(cli1, fname, &sbuf);
5459         if (!NT_STATUS_IS_OK(status)) {
5460                 printf("stat failed (%s)\n", nt_errstr(status));
5461                 goto out;
5462         }
5463
5464         if (sbuf.st_ex_size != 1000) {
5465                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5466                 goto out;
5467         }
5468
5469         status = cli_close(cli1, fnum1);
5470         if (!NT_STATUS_IS_OK(status)) {
5471                 printf("close(2) failed (%s)\n", nt_errstr(status));
5472                 goto out;
5473         }
5474
5475         /* Re-open with O_TRUNC. */
5476         status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
5477         if (!NT_STATUS_IS_OK(status)) {
5478                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5479                 goto out;
5480         }
5481
5482         /* Ensure st_size == 0 */
5483         status = cli_posix_stat(cli1, fname, &sbuf);
5484         if (!NT_STATUS_IS_OK(status)) {
5485                 printf("stat failed (%s)\n", nt_errstr(status));
5486                 goto out;
5487         }
5488
5489         if (sbuf.st_ex_size != 0) {
5490                 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
5491                 goto out;
5492         }
5493
5494         status = cli_close(cli1, fnum1);
5495         if (!NT_STATUS_IS_OK(status)) {
5496                 printf("close failed (%s)\n", nt_errstr(status));
5497                 goto out;
5498         }
5499
5500         status = cli_posix_unlink(cli1, fname);
5501         if (!NT_STATUS_IS_OK(status)) {
5502                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5503                 goto out;
5504         }
5505
5506         status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
5507         if (!NT_STATUS_IS_OK(status)) {
5508                 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
5509                         dname, nt_errstr(status));
5510                 goto out;
5511         }
5512
5513         cli_close(cli1, fnum1);
5514
5515         /* What happens when we try and POSIX open a directory for write ? */
5516         status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
5517         if (NT_STATUS_IS_OK(status)) {
5518                 printf("POSIX open of directory %s succeeded, should have failed.\n", fname);
5519                 goto out;
5520         } else {
5521                 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
5522                                 NT_STATUS_FILE_IS_A_DIRECTORY)) {
5523                         goto out;
5524                 }
5525         }
5526
5527         /* Create the file. */
5528         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5529                                 0600, &fnum1);
5530         if (!NT_STATUS_IS_OK(status)) {
5531                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5532                 goto out;
5533         }
5534
5535         /* Write some data into it. */
5536         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5537                               NULL);
5538         if (!NT_STATUS_IS_OK(status)) {
5539                 printf("cli_write failed: %s\n", nt_errstr(status));
5540                 goto out;
5541         }
5542
5543         cli_close(cli1, fnum1);
5544
5545         /* Now create a hardlink. */
5546         status = cli_posix_hardlink(cli1, fname, hname);
5547         if (!NT_STATUS_IS_OK(status)) {
5548                 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
5549                 goto out;
5550         }
5551
5552         /* Now create a symlink. */
5553         status = cli_posix_symlink(cli1, fname, sname);
5554         if (!NT_STATUS_IS_OK(status)) {
5555                 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
5556                 goto out;
5557         }
5558
5559         /* Open the hardlink for read. */
5560         status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
5561         if (!NT_STATUS_IS_OK(status)) {
5562                 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
5563                 goto out;
5564         }
5565
5566         status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
5567         if (!NT_STATUS_IS_OK(status)) {
5568                 printf("POSIX read of %s failed (%s)\n", hname,
5569                        nt_errstr(status));
5570                 goto out;
5571         } else if (nread != 10) {
5572                 printf("POSIX read of %s failed. Received %ld, expected %d\n",
5573                        hname, (unsigned long)nread, 10);
5574                 goto out;
5575         }
5576
5577         if (memcmp(buf, "TEST DATA\n", 10)) {
5578                 printf("invalid data read from hardlink\n");
5579                 goto out;
5580         }
5581
5582         /* Do a POSIX lock/unlock. */
5583         status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
5584         if (!NT_STATUS_IS_OK(status)) {
5585                 printf("POSIX lock failed %s\n", nt_errstr(status));
5586                 goto out;
5587         }
5588
5589         /* Punch a hole in the locked area. */
5590         status = cli_posix_unlock(cli1, fnum1, 10, 80);
5591         if (!NT_STATUS_IS_OK(status)) {
5592                 printf("POSIX unlock failed %s\n", nt_errstr(status));
5593                 goto out;
5594         }
5595
5596         cli_close(cli1, fnum1);
5597
5598         /* Open the symlink for read - this should fail. A POSIX
5599            client should not be doing opens on a symlink. */
5600         status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
5601         if (NT_STATUS_IS_OK(status)) {
5602                 printf("POSIX open of %s succeeded (should have failed)\n", sname);
5603                 goto out;
5604         } else {
5605                 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
5606                                 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
5607                         printf("POSIX open of %s should have failed "
5608                                 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
5609                                 "failed with %s instead.\n",
5610                                 sname, nt_errstr(status));
5611                         goto out;
5612                 }
5613         }
5614
5615         status = cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf));
5616         if (!NT_STATUS_IS_OK(status)) {
5617                 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
5618                 goto out;
5619         }
5620
5621         if (strcmp(namebuf, fname) != 0) {
5622                 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
5623                         sname, fname, namebuf);
5624                 goto out;
5625         }
5626
5627         status = cli_posix_rmdir(cli1, dname);
5628         if (!NT_STATUS_IS_OK(status)) {
5629                 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
5630                 goto out;
5631         }
5632
5633         printf("Simple POSIX open test passed\n");
5634         correct = true;
5635
5636   out:
5637
5638         if (fnum1 != (uint16_t)-1) {
5639                 cli_close(cli1, fnum1);
5640                 fnum1 = (uint16_t)-1;
5641         }
5642
5643         cli_setatr(cli1, sname, 0, 0);
5644         cli_posix_unlink(cli1, sname);
5645         cli_setatr(cli1, hname, 0, 0);
5646         cli_posix_unlink(cli1, hname);
5647         cli_setatr(cli1, fname, 0, 0);
5648         cli_posix_unlink(cli1, fname);
5649         cli_setatr(cli1, dname, 0, 0);
5650         cli_posix_rmdir(cli1, dname);
5651
5652         if (!torture_close_connection(cli1)) {
5653                 correct = false;
5654         }
5655
5656         return correct;
5657 }
5658
5659
5660 static uint32 open_attrs_table[] = {
5661                 FILE_ATTRIBUTE_NORMAL,
5662                 FILE_ATTRIBUTE_ARCHIVE,
5663                 FILE_ATTRIBUTE_READONLY,
5664                 FILE_ATTRIBUTE_HIDDEN,
5665                 FILE_ATTRIBUTE_SYSTEM,
5666
5667                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
5668                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
5669                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
5670                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5671                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5672                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5673
5674                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5675                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5676                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5677                 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
5678 };
5679
5680 struct trunc_open_results {
5681         unsigned int num;
5682         uint32 init_attr;
5683         uint32 trunc_attr;
5684         uint32 result_attr;
5685 };
5686
5687 static struct trunc_open_results attr_results[] = {
5688         { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5689         { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5690         { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5691         { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5692         { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5693         { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5694         { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5695         { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5696         { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5697         { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5698         { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5699         { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
5700         { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5701         { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5702         { 104, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5703         { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5704         { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5705         { 121, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
5706         { 170, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN },
5707         { 173, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM },
5708         { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5709         { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5710         { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5711         { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5712         { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5713         { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
5714 };
5715
5716 static bool run_openattrtest(int dummy)
5717 {
5718         static struct cli_state *cli1;
5719         const char *fname = "\\openattr.file";
5720         uint16_t fnum1;
5721         bool correct = True;
5722         uint16 attr;
5723         unsigned int i, j, k, l;
5724         NTSTATUS status;
5725
5726         printf("starting open attr test\n");
5727
5728         if (!torture_open_connection(&cli1, 0)) {
5729                 return False;
5730         }
5731
5732         cli_sockopt(cli1, sockops);
5733
5734         for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32); i++) {
5735                 cli_setatr(cli1, fname, 0, 0);
5736                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5737
5738                 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
5739                                        open_attrs_table[i], FILE_SHARE_NONE,
5740                                        FILE_OVERWRITE_IF, 0, 0, &fnum1);
5741                 if (!NT_STATUS_IS_OK(status)) {
5742                         printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5743                         return False;
5744                 }
5745
5746                 status = cli_close(cli1, fnum1);
5747                 if (!NT_STATUS_IS_OK(status)) {
5748                         printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5749                         return False;
5750                 }
5751
5752                 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32); j++) {
5753                         status = cli_ntcreate(cli1, fname, 0,
5754                                               FILE_READ_DATA|FILE_WRITE_DATA,
5755                                               open_attrs_table[j],
5756                                               FILE_SHARE_NONE, FILE_OVERWRITE,
5757                                               0, 0, &fnum1);
5758                         if (!NT_STATUS_IS_OK(status)) {
5759                                 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5760                                         if (attr_results[l].num == k) {
5761                                                 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
5762                                                                 k, open_attrs_table[i],
5763                                                                 open_attrs_table[j],
5764                                                                 fname, NT_STATUS_V(status), nt_errstr(status));
5765                                                 correct = False;
5766                                         }
5767                                 }
5768
5769                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5770                                         printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
5771                                                         k, open_attrs_table[i], open_attrs_table[j],
5772                                                         nt_errstr(status));
5773                                         correct = False;
5774                                 }
5775 #if 0
5776                                 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
5777 #endif
5778                                 k++;
5779                                 continue;
5780                         }
5781
5782                         status = cli_close(cli1, fnum1);
5783                         if (!NT_STATUS_IS_OK(status)) {
5784                                 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
5785                                 return False;
5786                         }
5787
5788                         status = cli_getatr(cli1, fname, &attr, NULL, NULL);
5789                         if (!NT_STATUS_IS_OK(status)) {
5790                                 printf("getatr(2) failed (%s)\n", nt_errstr(status));
5791                                 return False;
5792                         }
5793
5794 #if 0
5795                         printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
5796                                         k,  open_attrs_table[i],  open_attrs_table[j], attr );
5797 #endif
5798
5799                         for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5800                                 if (attr_results[l].num == k) {
5801                                         if (attr != attr_results[l].result_attr ||
5802                                                         open_attrs_table[i] != attr_results[l].init_attr ||
5803                                                         open_attrs_table[j] != attr_results[l].trunc_attr) {
5804                                                 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
5805                                                 open_attrs_table[i],
5806                                                 open_attrs_table[j],
5807                                                 (unsigned int)attr,
5808                                                 attr_results[l].result_attr);
5809                                                 correct = False;
5810                                         }
5811                                         break;
5812                                 }
5813                         }
5814                         k++;
5815                 }
5816         }
5817
5818         cli_setatr(cli1, fname, 0, 0);
5819         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5820
5821         printf("open attr test %s.\n", correct ? "passed" : "failed");
5822
5823         if (!torture_close_connection(cli1)) {
5824                 correct = False;
5825         }
5826         return correct;
5827 }
5828
5829 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
5830                     const char *name, void *state)
5831 {
5832         int *matched = (int *)state;
5833         if (matched != NULL) {
5834                 *matched += 1;
5835         }
5836         return NT_STATUS_OK;
5837 }
5838
5839 /*
5840   test directory listing speed
5841  */
5842 static bool run_dirtest(int dummy)
5843 {
5844         int i;
5845         static struct cli_state *cli;
5846         uint16_t fnum;
5847         struct timeval core_start;
5848         bool correct = True;
5849         int matched;
5850
5851         printf("starting directory test\n");
5852
5853         if (!torture_open_connection(&cli, 0)) {
5854                 return False;
5855         }
5856
5857         cli_sockopt(cli, sockops);
5858
5859         srandom(0);
5860         for (i=0;i<torture_numops;i++) {
5861                 fstring fname;
5862                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5863                 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
5864                         fprintf(stderr,"Failed to open %s\n", fname);
5865                         return False;
5866                 }
5867                 cli_close(cli, fnum);
5868         }
5869
5870         core_start = timeval_current();
5871
5872         matched = 0;
5873         cli_list(cli, "a*.*", 0, list_fn, &matched);
5874         printf("Matched %d\n", matched);
5875
5876         matched = 0;
5877         cli_list(cli, "b*.*", 0, list_fn, &matched);
5878         printf("Matched %d\n", matched);
5879
5880         matched = 0;
5881         cli_list(cli, "xyzabc", 0, list_fn, &matched);
5882         printf("Matched %d\n", matched);
5883
5884         printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
5885
5886         srandom(0);
5887         for (i=0;i<torture_numops;i++) {
5888                 fstring fname;
5889                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5890                 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5891         }
5892
5893         if (!torture_close_connection(cli)) {
5894                 correct = False;
5895         }
5896
5897         printf("finished dirtest\n");
5898
5899         return correct;
5900 }
5901
5902 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
5903                    void *state)
5904 {
5905         struct cli_state *pcli = (struct cli_state *)state;
5906         fstring fname;
5907         slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
5908
5909         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
5910                 return NT_STATUS_OK;
5911
5912         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
5913                 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
5914                         printf("del_fn: failed to rmdir %s\n,", fname );
5915         } else {
5916                 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
5917                         printf("del_fn: failed to unlink %s\n,", fname );
5918         }
5919         return NT_STATUS_OK;
5920 }
5921
5922
5923 /*
5924   sees what IOCTLs are supported
5925  */
5926 bool torture_ioctl_test(int dummy)
5927 {
5928         static struct cli_state *cli;
5929         uint16_t device, function;
5930         uint16_t fnum;
5931         const char *fname = "\\ioctl.dat";
5932         DATA_BLOB blob;
5933         NTSTATUS status;
5934
5935         if (!torture_open_connection(&cli, 0)) {
5936                 return False;
5937         }
5938
5939         printf("starting ioctl test\n");
5940
5941         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5942
5943         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5944         if (!NT_STATUS_IS_OK(status)) {
5945                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5946                 return False;
5947         }
5948
5949         status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
5950         printf("ioctl device info: %s\n", nt_errstr(status));
5951
5952         status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
5953         printf("ioctl job info: %s\n", nt_errstr(status));
5954
5955         for (device=0;device<0x100;device++) {
5956                 printf("ioctl test with device = 0x%x\n", device);
5957                 for (function=0;function<0x100;function++) {
5958                         uint32 code = (device<<16) | function;
5959
5960                         status = cli_raw_ioctl(cli, fnum, code, &blob);
5961
5962                         if (NT_STATUS_IS_OK(status)) {
5963                                 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
5964                                        (int)blob.length);
5965                                 data_blob_free(&blob);
5966                         }
5967                 }
5968         }
5969
5970         if (!torture_close_connection(cli)) {
5971                 return False;
5972         }
5973
5974         return True;
5975 }
5976
5977
5978 /*
5979   tries varients of chkpath
5980  */
5981 bool torture_chkpath_test(int dummy)
5982 {
5983         static struct cli_state *cli;
5984         uint16_t fnum;
5985         bool ret;
5986         NTSTATUS status;
5987
5988         if (!torture_open_connection(&cli, 0)) {
5989                 return False;
5990         }
5991
5992         printf("starting chkpath test\n");
5993
5994         /* cleanup from an old run */
5995         cli_rmdir(cli, "\\chkpath.dir\\dir2");
5996         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5997         cli_rmdir(cli, "\\chkpath.dir");
5998
5999         status = cli_mkdir(cli, "\\chkpath.dir");
6000         if (!NT_STATUS_IS_OK(status)) {
6001                 printf("mkdir1 failed : %s\n", nt_errstr(status));
6002                 return False;
6003         }
6004
6005         status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
6006         if (!NT_STATUS_IS_OK(status)) {
6007                 printf("mkdir2 failed : %s\n", nt_errstr(status));
6008                 return False;
6009         }
6010
6011         status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
6012                           DENY_NONE, &fnum);
6013         if (!NT_STATUS_IS_OK(status)) {
6014                 printf("open1 failed (%s)\n", nt_errstr(status));
6015                 return False;
6016         }
6017         cli_close(cli, fnum);
6018
6019         status = cli_chkpath(cli, "\\chkpath.dir");
6020         if (!NT_STATUS_IS_OK(status)) {
6021                 printf("chkpath1 failed: %s\n", nt_errstr(status));
6022                 ret = False;
6023         }
6024
6025         status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
6026         if (!NT_STATUS_IS_OK(status)) {
6027                 printf("chkpath2 failed: %s\n", nt_errstr(status));
6028                 ret = False;
6029         }
6030
6031         status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
6032         if (!NT_STATUS_IS_OK(status)) {
6033                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
6034                                   NT_STATUS_NOT_A_DIRECTORY);
6035         } else {
6036                 printf("* chkpath on a file should fail\n");
6037                 ret = False;
6038         }
6039
6040         status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
6041         if (!NT_STATUS_IS_OK(status)) {
6042                 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
6043                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
6044         } else {
6045                 printf("* chkpath on a non existant file should fail\n");
6046                 ret = False;
6047         }
6048
6049         status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
6050         if (!NT_STATUS_IS_OK(status)) {
6051                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
6052                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
6053         } else {
6054                 printf("* chkpath on a non existent component should fail\n");
6055                 ret = False;
6056         }
6057
6058         cli_rmdir(cli, "\\chkpath.dir\\dir2");
6059         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6060         cli_rmdir(cli, "\\chkpath.dir");
6061
6062         if (!torture_close_connection(cli)) {
6063                 return False;
6064         }
6065
6066         return ret;
6067 }
6068
6069 static bool run_eatest(int dummy)
6070 {
6071         static struct cli_state *cli;
6072         const char *fname = "\\eatest.txt";
6073         bool correct = True;
6074         uint16_t fnum;
6075         int i;
6076         size_t num_eas;
6077         struct ea_struct *ea_list = NULL;
6078         TALLOC_CTX *mem_ctx = talloc_init("eatest");
6079         NTSTATUS status;
6080
6081         printf("starting eatest\n");
6082
6083         if (!torture_open_connection(&cli, 0)) {
6084                 talloc_destroy(mem_ctx);
6085                 return False;
6086         }
6087
6088         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6089
6090         status = cli_ntcreate(cli, fname, 0,
6091                               FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6092                               FILE_SHARE_NONE, FILE_OVERWRITE_IF,
6093                               0x4044, 0, &fnum);
6094         if (!NT_STATUS_IS_OK(status)) {
6095                 printf("open failed - %s\n", nt_errstr(status));
6096                 talloc_destroy(mem_ctx);
6097                 return False;
6098         }
6099
6100         for (i = 0; i < 10; i++) {
6101                 fstring ea_name, ea_val;
6102
6103                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
6104                 memset(ea_val, (char)i+1, i+1);
6105                 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
6106                 if (!NT_STATUS_IS_OK(status)) {
6107                         printf("ea_set of name %s failed - %s\n", ea_name,
6108                                nt_errstr(status));
6109                         talloc_destroy(mem_ctx);
6110                         return False;
6111                 }
6112         }
6113
6114         cli_close(cli, fnum);
6115         for (i = 0; i < 10; i++) {
6116                 fstring ea_name, ea_val;
6117
6118                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
6119                 memset(ea_val, (char)i+1, i+1);
6120                 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
6121                 if (!NT_STATUS_IS_OK(status)) {
6122                         printf("ea_set of name %s failed - %s\n", ea_name,
6123                                nt_errstr(status));
6124                         talloc_destroy(mem_ctx);
6125                         return False;
6126                 }
6127         }
6128
6129         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6130         if (!NT_STATUS_IS_OK(status)) {
6131                 printf("ea_get list failed - %s\n", nt_errstr(status));
6132                 correct = False;
6133         }
6134
6135         printf("num_eas = %d\n", (int)num_eas);
6136
6137         if (num_eas != 20) {
6138                 printf("Should be 20 EA's stored... failing.\n");
6139                 correct = False;
6140         }
6141
6142         for (i = 0; i < num_eas; i++) {
6143                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6144                 dump_data(0, ea_list[i].value.data,
6145                           ea_list[i].value.length);
6146         }
6147
6148         /* Setting EA's to zero length deletes them. Test this */
6149         printf("Now deleting all EA's - case indepenent....\n");
6150
6151 #if 1
6152         cli_set_ea_path(cli, fname, "", "", 0);
6153 #else
6154         for (i = 0; i < 20; i++) {
6155                 fstring ea_name;
6156                 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
6157                 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
6158                 if (!NT_STATUS_IS_OK(status)) {
6159                         printf("ea_set of name %s failed - %s\n", ea_name,
6160                                nt_errstr(status));
6161                         talloc_destroy(mem_ctx);
6162                         return False;
6163                 }
6164         }
6165 #endif
6166
6167         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6168         if (!NT_STATUS_IS_OK(status)) {
6169                 printf("ea_get list failed - %s\n", nt_errstr(status));
6170                 correct = False;
6171         }
6172
6173         printf("num_eas = %d\n", (int)num_eas);
6174         for (i = 0; i < num_eas; i++) {
6175                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6176                 dump_data(0, ea_list[i].value.data,
6177                           ea_list[i].value.length);
6178         }
6179
6180         if (num_eas != 0) {
6181                 printf("deleting EA's failed.\n");
6182                 correct = False;
6183         }
6184
6185         /* Try and delete a non existant EA. */
6186         status = cli_set_ea_path(cli, fname, "foo", "", 0);
6187         if (!NT_STATUS_IS_OK(status)) {
6188                 printf("deleting non-existant EA 'foo' should succeed. %s\n",
6189                        nt_errstr(status));
6190                 correct = False;
6191         }
6192
6193         talloc_destroy(mem_ctx);
6194         if (!torture_close_connection(cli)) {
6195                 correct = False;
6196         }
6197
6198         return correct;
6199 }
6200
6201 static bool run_dirtest1(int dummy)
6202 {
6203         int i;
6204         static struct cli_state *cli;
6205         uint16_t fnum;
6206         int num_seen;
6207         bool correct = True;
6208
6209         printf("starting directory test\n");
6210
6211         if (!torture_open_connection(&cli, 0)) {
6212                 return False;
6213         }
6214
6215         cli_sockopt(cli, sockops);
6216
6217         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6218         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6219         cli_rmdir(cli, "\\LISTDIR");
6220         cli_mkdir(cli, "\\LISTDIR");
6221
6222         /* Create 1000 files and 1000 directories. */
6223         for (i=0;i<1000;i++) {
6224                 fstring fname;
6225                 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
6226                 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6227                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum))) {
6228                         fprintf(stderr,"Failed to open %s\n", fname);
6229                         return False;
6230                 }
6231                 cli_close(cli, fnum);
6232         }
6233         for (i=0;i<1000;i++) {
6234                 fstring fname;
6235                 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
6236                 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
6237                         fprintf(stderr,"Failed to open %s\n", fname);
6238                         return False;
6239                 }
6240         }
6241
6242         /* Now ensure that doing an old list sees both files and directories. */
6243         num_seen = 0;
6244         cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6245         printf("num_seen = %d\n", num_seen );
6246         /* We should see 100 files + 1000 directories + . and .. */
6247         if (num_seen != 2002)
6248                 correct = False;
6249
6250         /* Ensure if we have the "must have" bits we only see the
6251          * relevent entries.
6252          */
6253         num_seen = 0;
6254         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6255         printf("num_seen = %d\n", num_seen );
6256         if (num_seen != 1002)
6257                 correct = False;
6258
6259         num_seen = 0;
6260         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6261         printf("num_seen = %d\n", num_seen );
6262         if (num_seen != 1000)
6263                 correct = False;
6264
6265         /* Delete everything. */
6266         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6267         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6268         cli_rmdir(cli, "\\LISTDIR");
6269
6270 #if 0
6271         printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
6272         printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
6273         printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
6274 #endif
6275
6276         if (!torture_close_connection(cli)) {
6277                 correct = False;
6278         }
6279
6280         printf("finished dirtest1\n");
6281
6282         return correct;
6283 }
6284
6285 static bool run_error_map_extract(int dummy) {
6286
6287         static struct cli_state *c_dos;
6288         static struct cli_state *c_nt;
6289         NTSTATUS status;
6290
6291         uint32 error;
6292
6293         uint32 errnum;
6294         uint8 errclass;
6295
6296         NTSTATUS nt_status;
6297
6298         fstring user;
6299
6300         /* NT-Error connection */
6301
6302         disable_spnego = true;
6303         if (!(c_nt = open_nbt_connection())) {
6304                 disable_spnego = false;
6305                 return False;
6306         }
6307         disable_spnego = false;
6308
6309         status = cli_negprot(c_nt, PROTOCOL_NT1);
6310
6311         if (!NT_STATUS_IS_OK(status)) {
6312                 printf("%s rejected the NT-error negprot (%s)\n", host,
6313                        nt_errstr(status));
6314                 cli_shutdown(c_nt);
6315                 return False;
6316         }
6317
6318         status = cli_session_setup(c_nt, "", "", 0, "", 0, workgroup);
6319         if (!NT_STATUS_IS_OK(status)) {
6320                 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
6321                 return False;
6322         }
6323
6324         /* DOS-Error connection */
6325
6326         disable_spnego = true;
6327         force_dos_errors = true;
6328         if (!(c_dos = open_nbt_connection())) {
6329                 disable_spnego = false;
6330                 force_dos_errors = false;
6331                 return False;
6332         }
6333         disable_spnego = false;
6334         force_dos_errors = false;
6335
6336         status = cli_negprot(c_dos, PROTOCOL_NT1);
6337         if (!NT_STATUS_IS_OK(status)) {
6338                 printf("%s rejected the DOS-error negprot (%s)\n", host,
6339                        nt_errstr(status));
6340                 cli_shutdown(c_dos);
6341                 return False;
6342         }
6343
6344         status = cli_session_setup(c_dos, "", "", 0, "", 0, workgroup);
6345         if (!NT_STATUS_IS_OK(status)) {
6346                 printf("%s rejected the DOS-error initial session setup (%s)\n",
6347                         host, nt_errstr(status));
6348                 return False;
6349         }
6350
6351         c_nt->map_dos_errors = false;
6352         c_dos->map_dos_errors = false;
6353
6354         for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
6355                 fstr_sprintf(user, "%X", error);
6356
6357                 status = cli_session_setup(c_nt, user,
6358                                            password, strlen(password),
6359                                            password, strlen(password),
6360                                            workgroup);
6361                 if (NT_STATUS_IS_OK(status)) {
6362                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
6363                 }
6364
6365                 /* Case #1: 32-bit NT errors */
6366                 if (!NT_STATUS_IS_DOS(status)) {
6367                         nt_status = status;
6368                 } else {
6369                         printf("/** Dos error on NT connection! (%s) */\n", 
6370                                nt_errstr(status));
6371                         nt_status = NT_STATUS(0xc0000000);
6372                 }
6373
6374                 status = cli_session_setup(c_dos, user,
6375                                            password, strlen(password),
6376                                            password, strlen(password),
6377                                            workgroup);
6378                 if (NT_STATUS_IS_OK(status)) {
6379                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
6380                 }
6381
6382                 /* Case #1: 32-bit NT errors */
6383                 if (NT_STATUS_IS_DOS(status)) {
6384                         printf("/** NT error on DOS connection! (%s) */\n", 
6385                                nt_errstr(status));
6386                         errnum = errclass = 0;
6387                 } else {
6388                         errclass = NT_STATUS_DOS_CLASS(status);
6389                         errnum = NT_STATUS_DOS_CODE(status);
6390                 }
6391
6392                 if (NT_STATUS_V(nt_status) != error) { 
6393                         printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n", 
6394                                get_nt_error_c_code(talloc_tos(), NT_STATUS(error)), 
6395                                get_nt_error_c_code(talloc_tos(), nt_status));
6396                 }
6397
6398                 printf("\t{%s,\t%s,\t%s},\n", 
6399                        smb_dos_err_class(errclass), 
6400                        smb_dos_err_name(errclass, errnum), 
6401                        get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
6402         }
6403         return True;
6404 }
6405
6406 static bool run_sesssetup_bench(int dummy)
6407 {
6408         static struct cli_state *c;
6409         const char *fname = "\\file.dat";
6410         uint16_t fnum;
6411         NTSTATUS status;
6412         int i;
6413
6414         if (!torture_open_connection(&c, 0)) {
6415                 return false;
6416         }
6417
6418         status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6419                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6420                               FILE_DELETE_ON_CLOSE, 0, &fnum);
6421         if (!NT_STATUS_IS_OK(status)) {
6422                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
6423                 return false;
6424         }
6425
6426         for (i=0; i<torture_numops; i++) {
6427                 status = cli_session_setup(
6428                         c, username,
6429                         password, strlen(password),
6430                         password, strlen(password),
6431                         workgroup);
6432                 if (!NT_STATUS_IS_OK(status)) {
6433                         d_printf("(%s) cli_session_setup failed: %s\n",
6434                                  __location__, nt_errstr(status));
6435                         return false;
6436                 }
6437
6438                 d_printf("\r%d   ", (int)cli_state_get_uid(c));
6439
6440                 status = cli_ulogoff(c);
6441                 if (!NT_STATUS_IS_OK(status)) {
6442                         d_printf("(%s) cli_ulogoff failed: %s\n",
6443                                  __location__, nt_errstr(status));
6444                         return false;
6445                 }
6446         }
6447
6448         return true;
6449 }
6450
6451 static bool subst_test(const char *str, const char *user, const char *domain,
6452                        uid_t uid, gid_t gid, const char *expected)
6453 {
6454         char *subst;
6455         bool result = true;
6456
6457         subst = talloc_sub_specified(talloc_tos(), str, user, domain, uid, gid);
6458
6459         if (strcmp(subst, expected) != 0) {
6460                 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
6461                        "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
6462                        expected);
6463                 result = false;
6464         }
6465
6466         TALLOC_FREE(subst);
6467         return result;
6468 }
6469
6470 static void chain1_open_completion(struct tevent_req *req)
6471 {
6472         uint16_t fnum;
6473         NTSTATUS status;
6474         status = cli_openx_recv(req, &fnum);
6475         TALLOC_FREE(req);
6476
6477         d_printf("cli_openx_recv returned %s: %d\n",
6478                  nt_errstr(status),
6479                  NT_STATUS_IS_OK(status) ? fnum : -1);
6480 }
6481
6482 static void chain1_write_completion(struct tevent_req *req)
6483 {
6484         size_t written;
6485         NTSTATUS status;
6486         status = cli_write_andx_recv(req, &written);
6487         TALLOC_FREE(req);
6488
6489         d_printf("cli_write_andx_recv returned %s: %d\n",
6490                  nt_errstr(status),
6491                  NT_STATUS_IS_OK(status) ? (int)written : -1);
6492 }
6493
6494 static void chain1_close_completion(struct tevent_req *req)
6495 {
6496         NTSTATUS status;
6497         bool *done = (bool *)tevent_req_callback_data_void(req);
6498
6499         status = cli_close_recv(req);
6500         *done = true;
6501
6502         TALLOC_FREE(req);
6503
6504         d_printf("cli_close returned %s\n", nt_errstr(status));
6505 }
6506
6507 static bool run_chain1(int dummy)
6508 {
6509         struct cli_state *cli1;
6510         struct event_context *evt = event_context_init(NULL);
6511         struct tevent_req *reqs[3], *smbreqs[3];
6512         bool done = false;
6513         const char *str = "foobar";
6514         NTSTATUS status;
6515
6516         printf("starting chain1 test\n");
6517         if (!torture_open_connection(&cli1, 0)) {
6518                 return False;
6519         }
6520
6521         cli_sockopt(cli1, sockops);
6522
6523         reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, "\\test",
6524                                   O_CREAT|O_RDWR, 0, &smbreqs[0]);
6525         if (reqs[0] == NULL) return false;
6526         tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
6527
6528
6529         reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
6530                                         (const uint8_t *)str, 0, strlen(str)+1,
6531                                         smbreqs, 1, &smbreqs[1]);
6532         if (reqs[1] == NULL) return false;
6533         tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
6534
6535         reqs[2] = cli_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
6536         if (reqs[2] == NULL) return false;
6537         tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
6538
6539         status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
6540         if (!NT_STATUS_IS_OK(status)) {
6541                 return false;
6542         }
6543
6544         while (!done) {
6545                 tevent_loop_once(evt);
6546         }
6547
6548         torture_close_connection(cli1);
6549         return True;
6550 }
6551
6552 static void chain2_sesssetup_completion(struct tevent_req *req)
6553 {
6554         NTSTATUS status;
6555         status = cli_session_setup_guest_recv(req);
6556         d_printf("sesssetup returned %s\n", nt_errstr(status));
6557 }
6558
6559 static void chain2_tcon_completion(struct tevent_req *req)
6560 {
6561         bool *done = (bool *)tevent_req_callback_data_void(req);
6562         NTSTATUS status;
6563         status = cli_tcon_andx_recv(req);
6564         d_printf("tcon_and_x returned %s\n", nt_errstr(status));
6565         *done = true;
6566 }
6567
6568 static bool run_chain2(int dummy)
6569 {
6570         struct cli_state *cli1;
6571         struct event_context *evt = event_context_init(NULL);
6572         struct tevent_req *reqs[2], *smbreqs[2];
6573         bool done = false;
6574         NTSTATUS status;
6575
6576         printf("starting chain2 test\n");
6577         status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
6578                                       port_to_use, SMB_SIGNING_DEFAULT, 0);
6579         if (!NT_STATUS_IS_OK(status)) {
6580                 return False;
6581         }
6582
6583         cli_sockopt(cli1, sockops);
6584
6585         reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
6586                                                  &smbreqs[0]);
6587         if (reqs[0] == NULL) return false;
6588         tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
6589
6590         reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
6591                                        "?????", NULL, 0, &smbreqs[1]);
6592         if (reqs[1] == NULL) return false;
6593         tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
6594
6595         status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
6596         if (!NT_STATUS_IS_OK(status)) {
6597                 return false;
6598         }
6599
6600         while (!done) {
6601                 tevent_loop_once(evt);
6602         }
6603
6604         torture_close_connection(cli1);
6605         return True;
6606 }
6607
6608
6609 struct torture_createdel_state {
6610         struct tevent_context *ev;
6611         struct cli_state *cli;
6612 };
6613
6614 static void torture_createdel_created(struct tevent_req *subreq);
6615 static void torture_createdel_closed(struct tevent_req *subreq);
6616
6617 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
6618                                                  struct tevent_context *ev,
6619                                                  struct cli_state *cli,
6620                                                  const char *name)
6621 {
6622         struct tevent_req *req, *subreq;
6623         struct torture_createdel_state *state;
6624
6625         req = tevent_req_create(mem_ctx, &state,
6626                                 struct torture_createdel_state);
6627         if (req == NULL) {
6628                 return NULL;
6629         }
6630         state->ev = ev;
6631         state->cli = cli;
6632
6633         subreq = cli_ntcreate_send(
6634                 state, ev, cli, name, 0,
6635                 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
6636                 FILE_ATTRIBUTE_NORMAL,
6637                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6638                 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
6639
6640         if (tevent_req_nomem(subreq, req)) {
6641                 return tevent_req_post(req, ev);
6642         }
6643         tevent_req_set_callback(subreq, torture_createdel_created, req);
6644         return req;
6645 }
6646
6647 static void torture_createdel_created(struct tevent_req *subreq)
6648 {
6649         struct tevent_req *req = tevent_req_callback_data(
6650                 subreq, struct tevent_req);
6651         struct torture_createdel_state *state = tevent_req_data(
6652                 req, struct torture_createdel_state);
6653         NTSTATUS status;
6654         uint16_t fnum;
6655
6656         status = cli_ntcreate_recv(subreq, &fnum);
6657         TALLOC_FREE(subreq);
6658         if (!NT_STATUS_IS_OK(status)) {
6659                 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
6660                            nt_errstr(status)));
6661                 tevent_req_nterror(req, status);
6662                 return;
6663         }
6664
6665         subreq = cli_close_send(state, state->ev, state->cli, fnum);
6666         if (tevent_req_nomem(subreq, req)) {
6667                 return;
6668         }
6669         tevent_req_set_callback(subreq, torture_createdel_closed, req);
6670 }
6671
6672 static void torture_createdel_closed(struct tevent_req *subreq)
6673 {
6674         struct tevent_req *req = tevent_req_callback_data(
6675                 subreq, struct tevent_req);
6676         NTSTATUS status;
6677
6678         status = cli_close_recv(subreq);
6679         if (!NT_STATUS_IS_OK(status)) {
6680                 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
6681                 tevent_req_nterror(req, status);
6682                 return;
6683         }
6684         tevent_req_done(req);
6685 }
6686
6687 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
6688 {
6689         return tevent_req_simple_recv_ntstatus(req);
6690 }
6691
6692 struct torture_createdels_state {
6693         struct tevent_context *ev;
6694         struct cli_state *cli;
6695         const char *base_name;
6696         int sent;
6697         int received;
6698         int num_files;
6699         struct tevent_req **reqs;
6700 };
6701
6702 static void torture_createdels_done(struct tevent_req *subreq);
6703
6704 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
6705                                                   struct tevent_context *ev,
6706                                                   struct cli_state *cli,
6707                                                   const char *base_name,
6708                                                   int num_parallel,
6709                                                   int num_files)
6710 {
6711         struct tevent_req *req;
6712         struct torture_createdels_state *state;
6713         int i;
6714
6715         req = tevent_req_create(mem_ctx, &state,
6716                                 struct torture_createdels_state);
6717         if (req == NULL) {
6718                 return NULL;
6719         }
6720         state->ev = ev;
6721         state->cli = cli;
6722         state->base_name = talloc_strdup(state, base_name);
6723         if (tevent_req_nomem(state->base_name, req)) {
6724                 return tevent_req_post(req, ev);
6725         }
6726         state->num_files = MAX(num_parallel, num_files);
6727         state->sent = 0;
6728         state->received = 0;
6729
6730         state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
6731         if (tevent_req_nomem(state->reqs, req)) {
6732                 return tevent_req_post(req, ev);
6733         }
6734
6735         for (i=0; i<num_parallel; i++) {
6736                 char *name;
6737
6738                 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6739                                        state->sent);
6740                 if (tevent_req_nomem(name, req)) {
6741                         return tevent_req_post(req, ev);
6742                 }
6743                 state->reqs[i] = torture_createdel_send(
6744                         state->reqs, state->ev, state->cli, name);
6745                 if (tevent_req_nomem(state->reqs[i], req)) {
6746                         return tevent_req_post(req, ev);
6747                 }
6748                 name = talloc_move(state->reqs[i], &name);
6749                 tevent_req_set_callback(state->reqs[i],
6750                                         torture_createdels_done, req);
6751                 state->sent += 1;
6752         }
6753         return req;
6754 }
6755
6756 static void torture_createdels_done(struct tevent_req *subreq)
6757 {
6758         struct tevent_req *req = tevent_req_callback_data(
6759                 subreq, struct tevent_req);
6760         struct torture_createdels_state *state = tevent_req_data(
6761                 req, struct torture_createdels_state);
6762         size_t num_parallel = talloc_array_length(state->reqs);
6763         NTSTATUS status;
6764         char *name;
6765         int i;
6766
6767         status = torture_createdel_recv(subreq);
6768         if (!NT_STATUS_IS_OK(status)){
6769                 DEBUG(10, ("torture_createdel_recv returned %s\n",
6770                            nt_errstr(status)));
6771                 TALLOC_FREE(subreq);
6772                 tevent_req_nterror(req, status);
6773                 return;
6774         }
6775
6776         for (i=0; i<num_parallel; i++) {
6777                 if (subreq == state->reqs[i]) {
6778                         break;
6779                 }
6780         }
6781         if (i == num_parallel) {
6782                 DEBUG(10, ("received something we did not send\n"));
6783                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
6784                 return;
6785         }
6786         TALLOC_FREE(state->reqs[i]);
6787
6788         if (state->sent >= state->num_files) {
6789                 tevent_req_done(req);
6790                 return;
6791         }
6792
6793         name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6794                                state->sent);
6795         if (tevent_req_nomem(name, req)) {
6796                 return;
6797         }
6798         state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
6799                                                 state->cli, name);
6800         if (tevent_req_nomem(state->reqs[i], req)) {
6801                 return;
6802         }
6803         name = talloc_move(state->reqs[i], &name);
6804         tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
6805         state->sent += 1;
6806 }
6807
6808 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
6809 {
6810         return tevent_req_simple_recv_ntstatus(req);
6811 }
6812
6813 struct swallow_notify_state {
6814         struct tevent_context *ev;
6815         struct cli_state *cli;
6816         uint16_t fnum;
6817         uint32_t completion_filter;
6818         bool recursive;
6819         bool (*fn)(uint32_t action, const char *name, void *priv);
6820         void *priv;
6821 };
6822
6823 static void swallow_notify_done(struct tevent_req *subreq);
6824
6825 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
6826                                               struct tevent_context *ev,
6827                                               struct cli_state *cli,
6828                                               uint16_t fnum,
6829                                               uint32_t completion_filter,
6830                                               bool recursive,
6831                                               bool (*fn)(uint32_t action,
6832                                                          const char *name,
6833                                                          void *priv),
6834                                               void *priv)
6835 {
6836         struct tevent_req *req, *subreq;
6837         struct swallow_notify_state *state;
6838
6839         req = tevent_req_create(mem_ctx, &state,
6840                                 struct swallow_notify_state);
6841         if (req == NULL) {
6842                 return NULL;
6843         }
6844         state->ev = ev;
6845         state->cli = cli;
6846         state->fnum = fnum;
6847         state->completion_filter = completion_filter;
6848         state->recursive = recursive;
6849         state->fn = fn;
6850         state->priv = priv;
6851
6852         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6853                                  0xffff, state->completion_filter,
6854                                  state->recursive);
6855         if (tevent_req_nomem(subreq, req)) {
6856                 return tevent_req_post(req, ev);
6857         }
6858         tevent_req_set_callback(subreq, swallow_notify_done, req);
6859         return req;
6860 }
6861
6862 static void swallow_notify_done(struct tevent_req *subreq)
6863 {
6864         struct tevent_req *req = tevent_req_callback_data(
6865                 subreq, struct tevent_req);
6866         struct swallow_notify_state *state = tevent_req_data(
6867                 req, struct swallow_notify_state);
6868         NTSTATUS status;
6869         uint32_t i, num_changes;
6870         struct notify_change *changes;
6871
6872         status = cli_notify_recv(subreq, state, &num_changes, &changes);
6873         TALLOC_FREE(subreq);
6874         if (!NT_STATUS_IS_OK(status)) {
6875                 DEBUG(10, ("cli_notify_recv returned %s\n",
6876                            nt_errstr(status)));
6877                 tevent_req_nterror(req, status);
6878                 return;
6879         }
6880
6881         for (i=0; i<num_changes; i++) {
6882                 state->fn(changes[i].action, changes[i].name, state->priv);
6883         }
6884         TALLOC_FREE(changes);
6885
6886         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6887                                  0xffff, state->completion_filter,
6888                                  state->recursive);
6889         if (tevent_req_nomem(subreq, req)) {
6890                 return;
6891         }
6892         tevent_req_set_callback(subreq, swallow_notify_done, req);
6893 }
6894
6895 static bool print_notifies(uint32_t action, const char *name, void *priv)
6896 {
6897         if (DEBUGLEVEL > 5) {
6898                 d_printf("%d %s\n", (int)action, name);
6899         }
6900         return true;
6901 }
6902
6903 static void notify_bench_done(struct tevent_req *req)
6904 {
6905         int *num_finished = (int *)tevent_req_callback_data_void(req);
6906         *num_finished += 1;
6907 }
6908
6909 static bool run_notify_bench(int dummy)
6910 {
6911         const char *dname = "\\notify-bench";
6912         struct tevent_context *ev;
6913         NTSTATUS status;
6914         uint16_t dnum;
6915         struct tevent_req *req1;
6916         struct tevent_req *req2 = NULL;
6917         int i, num_unc_names;
6918         int num_finished = 0;
6919
6920         printf("starting notify-bench test\n");
6921
6922         if (use_multishare_conn) {
6923                 char **unc_list;
6924                 unc_list = file_lines_load(multishare_conn_fname,
6925                                            &num_unc_names, 0, NULL);
6926                 if (!unc_list || num_unc_names <= 0) {
6927                         d_printf("Failed to load unc names list from '%s'\n",
6928                                  multishare_conn_fname);
6929                         return false;
6930                 }
6931                 TALLOC_FREE(unc_list);
6932         } else {
6933                 num_unc_names = 1;
6934         }
6935
6936         ev = tevent_context_init(talloc_tos());
6937         if (ev == NULL) {
6938                 d_printf("tevent_context_init failed\n");
6939                 return false;
6940         }
6941
6942         for (i=0; i<num_unc_names; i++) {
6943                 struct cli_state *cli;
6944                 char *base_fname;
6945
6946                 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
6947                                              dname, i);
6948                 if (base_fname == NULL) {
6949                         return false;
6950                 }
6951
6952                 if (!torture_open_connection(&cli, i)) {
6953                         return false;
6954                 }
6955
6956                 status = cli_ntcreate(cli, dname, 0,
6957                                       MAXIMUM_ALLOWED_ACCESS,
6958                                       0, FILE_SHARE_READ|FILE_SHARE_WRITE|
6959                                       FILE_SHARE_DELETE,
6960                                       FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
6961                                       &dnum);
6962
6963                 if (!NT_STATUS_IS_OK(status)) {
6964                         d_printf("Could not create %s: %s\n", dname,
6965                                  nt_errstr(status));
6966                         return false;
6967                 }
6968
6969                 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
6970                                            FILE_NOTIFY_CHANGE_FILE_NAME |
6971                                            FILE_NOTIFY_CHANGE_DIR_NAME |
6972                                            FILE_NOTIFY_CHANGE_ATTRIBUTES |
6973                                            FILE_NOTIFY_CHANGE_LAST_WRITE,
6974                                            false, print_notifies, NULL);
6975                 if (req1 == NULL) {
6976                         d_printf("Could not create notify request\n");
6977                         return false;
6978                 }
6979
6980                 req2 = torture_createdels_send(talloc_tos(), ev, cli,
6981                                                base_fname, 10, torture_numops);
6982                 if (req2 == NULL) {
6983                         d_printf("Could not create createdels request\n");
6984                         return false;
6985                 }
6986                 TALLOC_FREE(base_fname);
6987
6988                 tevent_req_set_callback(req2, notify_bench_done,
6989                                         &num_finished);
6990         }
6991
6992         while (num_finished < num_unc_names) {
6993                 int ret;
6994                 ret = tevent_loop_once(ev);
6995                 if (ret != 0) {
6996                         d_printf("tevent_loop_once failed\n");
6997                         return false;
6998                 }
6999         }
7000
7001         if (!tevent_req_poll(req2, ev)) {
7002                 d_printf("tevent_req_poll failed\n");
7003         }
7004
7005         status = torture_createdels_recv(req2);
7006         d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
7007
7008         return true;
7009 }
7010
7011 static bool run_mangle1(int dummy)
7012 {
7013         struct cli_state *cli;
7014         const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
7015         uint16_t fnum;
7016         fstring alt_name;
7017         NTSTATUS status;
7018         time_t change_time, access_time, write_time;
7019         off_t size;
7020         uint16_t mode;
7021
7022         printf("starting mangle1 test\n");
7023         if (!torture_open_connection(&cli, 0)) {
7024                 return False;
7025         }
7026
7027         cli_sockopt(cli, sockops);
7028
7029         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
7030                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
7031                               0, 0, &fnum);
7032         if (!NT_STATUS_IS_OK(status)) {
7033                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
7034                 return false;
7035         }
7036         cli_close(cli, fnum);
7037
7038         status = cli_qpathinfo_alt_name(cli, fname, alt_name);
7039         if (!NT_STATUS_IS_OK(status)) {
7040                 d_printf("cli_qpathinfo_alt_name failed: %s\n",
7041                          nt_errstr(status));
7042                 return false;
7043         }
7044         d_printf("alt_name: %s\n", alt_name);
7045
7046         status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
7047         if (!NT_STATUS_IS_OK(status)) {
7048                 d_printf("cli_openx(%s) failed: %s\n", alt_name,
7049                          nt_errstr(status));
7050                 return false;
7051         }
7052         cli_close(cli, fnum);
7053
7054         status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
7055                                 &write_time, &size, &mode);
7056         if (!NT_STATUS_IS_OK(status)) {
7057                 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
7058                          nt_errstr(status));
7059                 return false;
7060         }
7061
7062         return true;
7063 }
7064
7065 static size_t null_source(uint8_t *buf, size_t n, void *priv)
7066 {
7067         size_t *to_pull = (size_t *)priv;
7068         size_t thistime = *to_pull;
7069
7070         thistime = MIN(thistime, n);
7071         if (thistime == 0) {
7072                 return 0;
7073         }
7074
7075         memset(buf, 0, thistime);
7076         *to_pull -= thistime;
7077         return thistime;
7078 }
7079
7080 static bool run_windows_write(int dummy)
7081 {
7082         struct cli_state *cli1;
7083         uint16_t fnum;
7084         int i;
7085         bool ret = false;
7086         const char *fname = "\\writetest.txt";
7087         struct timeval start_time;
7088         double seconds;
7089         double kbytes;
7090         NTSTATUS status;
7091
7092         printf("starting windows_write test\n");
7093         if (!torture_open_connection(&cli1, 0)) {
7094                 return False;
7095         }
7096
7097         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
7098         if (!NT_STATUS_IS_OK(status)) {
7099                 printf("open failed (%s)\n", nt_errstr(status));
7100                 return False;
7101         }
7102
7103         cli_sockopt(cli1, sockops);
7104
7105         start_time = timeval_current();
7106
7107         for (i=0; i<torture_numops; i++) {
7108                 uint8_t c = 0;
7109                 off_t start = i * torture_blocksize;
7110                 size_t to_pull = torture_blocksize - 1;
7111
7112                 status = cli_writeall(cli1, fnum, 0, &c,
7113                                       start + torture_blocksize - 1, 1, NULL);
7114                 if (!NT_STATUS_IS_OK(status)) {
7115                         printf("cli_write failed: %s\n", nt_errstr(status));
7116                         goto fail;
7117                 }
7118
7119                 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
7120                                   null_source, &to_pull);
7121                 if (!NT_STATUS_IS_OK(status)) {
7122                         printf("cli_push returned: %s\n", nt_errstr(status));
7123                         goto fail;
7124                 }
7125         }
7126
7127         seconds = timeval_elapsed(&start_time);
7128         kbytes = (double)torture_blocksize * torture_numops;
7129         kbytes /= 1024;
7130
7131         printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
7132                (double)seconds, (int)(kbytes/seconds));
7133
7134         ret = true;
7135  fail:
7136         cli_close(cli1, fnum);
7137         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7138         torture_close_connection(cli1);
7139         return ret;
7140 }
7141
7142 static bool run_cli_echo(int dummy)
7143 {
7144         struct cli_state *cli;
7145         NTSTATUS status;
7146
7147         printf("starting cli_echo test\n");
7148         if (!torture_open_connection(&cli, 0)) {
7149                 return false;
7150         }
7151         cli_sockopt(cli, sockops);
7152
7153         status = cli_echo(cli, 5, data_blob_const("hello", 5));
7154
7155         d_printf("cli_echo returned %s\n", nt_errstr(status));
7156
7157         torture_close_connection(cli);
7158         return NT_STATUS_IS_OK(status);
7159 }
7160
7161 static bool run_uid_regression_test(int dummy)
7162 {
7163         static struct cli_state *cli;
7164         int16_t old_vuid;
7165         int16_t old_cnum;
7166         bool correct = True;
7167         NTSTATUS status;
7168
7169         printf("starting uid regression test\n");
7170
7171         if (!torture_open_connection(&cli, 0)) {
7172                 return False;
7173         }
7174
7175         cli_sockopt(cli, sockops);
7176
7177         /* Ok - now save then logoff our current user. */
7178         old_vuid = cli_state_get_uid(cli);
7179
7180         status = cli_ulogoff(cli);
7181         if (!NT_STATUS_IS_OK(status)) {
7182                 d_printf("(%s) cli_ulogoff failed: %s\n",
7183                          __location__, nt_errstr(status));
7184                 correct = false;
7185                 goto out;
7186         }
7187
7188         cli_state_set_uid(cli, old_vuid);
7189
7190         /* Try an operation. */
7191         status = cli_mkdir(cli, "\\uid_reg_test");
7192         if (NT_STATUS_IS_OK(status)) {
7193                 d_printf("(%s) cli_mkdir succeeded\n",
7194                          __location__);
7195                 correct = false;
7196                 goto out;
7197         } else {
7198                 /* Should be bad uid. */
7199                 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
7200                                  NT_STATUS_USER_SESSION_DELETED)) {
7201                         correct = false;
7202                         goto out;
7203                 }
7204         }
7205
7206         old_cnum = cli_state_get_tid(cli);
7207
7208         /* Now try a SMBtdis with the invald vuid set to zero. */
7209         cli_state_set_uid(cli, 0);
7210
7211         /* This should succeed. */
7212         status = cli_tdis(cli);
7213
7214         if (NT_STATUS_IS_OK(status)) {
7215                 d_printf("First tdis with invalid vuid should succeed.\n");
7216         } else {
7217                 d_printf("First tdis failed (%s)\n", nt_errstr(status));
7218                 correct = false;
7219                 goto out;
7220         }
7221
7222         cli_state_set_uid(cli, old_vuid);
7223         cli_state_set_tid(cli, old_cnum);
7224
7225         /* This should fail. */
7226         status = cli_tdis(cli);
7227         if (NT_STATUS_IS_OK(status)) {
7228                 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
7229                 correct = false;
7230                 goto out;
7231         } else {
7232                 /* Should be bad tid. */
7233                 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
7234                                 NT_STATUS_NETWORK_NAME_DELETED)) {
7235                         correct = false;
7236                         goto out;
7237                 }
7238         }
7239
7240         cli_rmdir(cli, "\\uid_reg_test");
7241
7242   out:
7243
7244         cli_shutdown(cli);
7245         return correct;
7246 }
7247
7248
7249 static const char *illegal_chars = "*\\/?<>|\":";
7250 static char force_shortname_chars[] = " +,.[];=\177";
7251
7252 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
7253                              const char *mask, void *state)
7254 {
7255         struct cli_state *pcli = (struct cli_state *)state;
7256         fstring fname;
7257         NTSTATUS status = NT_STATUS_OK;
7258
7259         slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
7260
7261         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
7262                 return NT_STATUS_OK;
7263
7264         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
7265                 status = cli_rmdir(pcli, fname);
7266                 if (!NT_STATUS_IS_OK(status)) {
7267                         printf("del_fn: failed to rmdir %s\n,", fname );
7268                 }
7269         } else {
7270                 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7271                 if (!NT_STATUS_IS_OK(status)) {
7272                         printf("del_fn: failed to unlink %s\n,", fname );
7273                 }
7274         }
7275         return status;
7276 }
7277
7278 struct sn_state {
7279         int matched;
7280         int i;
7281         bool val;
7282 };
7283
7284 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
7285                               const char *name, void *state)
7286 {
7287         struct sn_state *s = (struct sn_state  *)state;
7288         int i = s->i;
7289
7290 #if 0
7291         printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
7292                 i, finfo->name, finfo->short_name);
7293 #endif
7294
7295         if (strchr(force_shortname_chars, i)) {
7296                 if (!finfo->short_name) {
7297                         /* Shortname not created when it should be. */
7298                         d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
7299                                 __location__, finfo->name, i);
7300                         s->val = true;
7301                 }
7302         } else if (finfo->short_name){
7303                 /* Shortname created when it should not be. */
7304                 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
7305                         __location__, finfo->short_name, finfo->name);
7306                 s->val = true;
7307         }
7308         s->matched += 1;
7309         return NT_STATUS_OK;
7310 }
7311
7312 static bool run_shortname_test(int dummy)
7313 {
7314         static struct cli_state *cli;
7315         bool correct = True;
7316         int i;
7317         struct sn_state s;
7318         char fname[40];
7319         NTSTATUS status;
7320
7321         printf("starting shortname test\n");
7322
7323         if (!torture_open_connection(&cli, 0)) {
7324                 return False;
7325         }
7326
7327         cli_sockopt(cli, sockops);
7328
7329         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7330         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7331         cli_rmdir(cli, "\\shortname");
7332
7333         status = cli_mkdir(cli, "\\shortname");
7334         if (!NT_STATUS_IS_OK(status)) {
7335                 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
7336                         __location__, nt_errstr(status));
7337                 correct = false;
7338                 goto out;
7339         }
7340
7341         if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
7342                 correct = false;
7343                 goto out;
7344         }
7345         if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
7346                 correct = false;
7347                 goto out;
7348         }
7349
7350         s.val = false;
7351
7352         for (i = 32; i < 128; i++) {
7353                 uint16_t fnum = (uint16_t)-1;
7354
7355                 s.i = i;
7356
7357                 if (strchr(illegal_chars, i)) {
7358                         continue;
7359                 }
7360                 fname[15] = i;
7361
7362                 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
7363                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum);
7364                 if (!NT_STATUS_IS_OK(status)) {
7365                         d_printf("(%s) cli_nt_create of %s failed: %s\n",
7366                                 __location__, fname, nt_errstr(status));
7367                         correct = false;
7368                         goto out;
7369                 }
7370                 cli_close(cli, fnum);
7371
7372                 s.matched = 0;
7373                 status = cli_list(cli, "\\shortname\\test*.*", 0,
7374                                   shortname_list_fn, &s);
7375                 if (s.matched != 1) {
7376                         d_printf("(%s) failed to list %s: %s\n",
7377                                 __location__, fname, nt_errstr(status));
7378                         correct = false;
7379                         goto out;
7380                 }
7381
7382                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7383                 if (!NT_STATUS_IS_OK(status)) {
7384                         d_printf("(%s) failed to delete %s: %s\n",
7385                                 __location__, fname, nt_errstr(status));
7386                         correct = false;
7387                         goto out;
7388                 }
7389
7390                 if (s.val) {
7391                         correct = false;
7392                         goto out;
7393                 }
7394         }
7395
7396   out:
7397
7398         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7399         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7400         cli_rmdir(cli, "\\shortname");
7401         torture_close_connection(cli);
7402         return correct;
7403 }
7404
7405 static void pagedsearch_cb(struct tevent_req *req)
7406 {
7407         int rc;
7408         struct tldap_message *msg;
7409         char *dn;
7410
7411         rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
7412         if (rc != TLDAP_SUCCESS) {
7413                 d_printf("tldap_search_paged_recv failed: %s\n",
7414                          tldap_err2string(rc));
7415                 return;
7416         }
7417         if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
7418                 TALLOC_FREE(msg);
7419                 return;
7420         }
7421         if (!tldap_entry_dn(msg, &dn)) {
7422                 d_printf("tldap_entry_dn failed\n");
7423                 return;
7424         }
7425         d_printf("%s\n", dn);
7426         TALLOC_FREE(msg);
7427 }
7428
7429 static bool run_tldap(int dummy)
7430 {
7431         struct tldap_context *ld;
7432         int fd, rc;
7433         NTSTATUS status;
7434         struct sockaddr_storage addr;
7435         struct tevent_context *ev;
7436         struct tevent_req *req;
7437         char *basedn;
7438         const char *filter;
7439
7440         if (!resolve_name(host, &addr, 0, false)) {
7441                 d_printf("could not find host %s\n", host);
7442                 return false;
7443         }
7444         status = open_socket_out(&addr, 389, 9999, &fd);
7445         if (!NT_STATUS_IS_OK(status)) {
7446                 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
7447                 return false;
7448         }
7449
7450         ld = tldap_context_create(talloc_tos(), fd);
7451         if (ld == NULL) {
7452                 close(fd);
7453                 d_printf("tldap_context_create failed\n");
7454                 return false;
7455         }
7456
7457         rc = tldap_fetch_rootdse(ld);
7458         if (rc != TLDAP_SUCCESS) {
7459                 d_printf("tldap_fetch_rootdse failed: %s\n",
7460                          tldap_errstr(talloc_tos(), ld, rc));
7461                 return false;
7462         }
7463
7464         basedn = tldap_talloc_single_attribute(
7465                 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
7466         if (basedn == NULL) {
7467                 d_printf("no defaultNamingContext\n");
7468                 return false;
7469         }
7470         d_printf("defaultNamingContext: %s\n", basedn);
7471
7472         ev = tevent_context_init(talloc_tos());
7473         if (ev == NULL) {
7474                 d_printf("tevent_context_init failed\n");
7475                 return false;
7476         }
7477
7478         req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
7479                                       TLDAP_SCOPE_SUB, "(objectclass=*)",
7480                                       NULL, 0, 0,
7481                                       NULL, 0, NULL, 0, 0, 0, 0, 5);
7482         if (req == NULL) {
7483                 d_printf("tldap_search_paged_send failed\n");
7484                 return false;
7485         }
7486         tevent_req_set_callback(req, pagedsearch_cb, NULL);
7487
7488         tevent_req_poll(req, ev);
7489
7490         TALLOC_FREE(req);
7491
7492         /* test search filters against rootDSE */
7493         filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
7494                    "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
7495
7496         rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
7497                           NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
7498                           talloc_tos(), NULL, NULL);
7499         if (rc != TLDAP_SUCCESS) {
7500                 d_printf("tldap_search with complex filter failed: %s\n",
7501                          tldap_errstr(talloc_tos(), ld, rc));
7502                 return false;
7503         }
7504
7505         TALLOC_FREE(ld);
7506         return true;
7507 }
7508
7509 /* Torture test to ensure no regression of :
7510 https://bugzilla.samba.org/show_bug.cgi?id=7084
7511 */
7512
7513 static bool run_dir_createtime(int dummy)
7514 {
7515         struct cli_state *cli;
7516         const char *dname = "\\testdir";
7517         const char *fname = "\\testdir\\testfile";
7518         NTSTATUS status;
7519         struct timespec create_time;
7520         struct timespec create_time1;
7521         uint16_t fnum;
7522         bool ret = false;
7523
7524         if (!torture_open_connection(&cli, 0)) {
7525                 return false;
7526         }
7527
7528         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7529         cli_rmdir(cli, dname);
7530
7531         status = cli_mkdir(cli, dname);
7532         if (!NT_STATUS_IS_OK(status)) {
7533                 printf("mkdir failed: %s\n", nt_errstr(status));
7534                 goto out;
7535         }
7536
7537         status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
7538                                 NULL, NULL, NULL);
7539         if (!NT_STATUS_IS_OK(status)) {
7540                 printf("cli_qpathinfo2 returned %s\n",
7541                        nt_errstr(status));
7542                 goto out;
7543         }
7544
7545         /* Sleep 3 seconds, then create a file. */
7546         sleep(3);
7547
7548         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
7549                          DENY_NONE, &fnum);
7550         if (!NT_STATUS_IS_OK(status)) {
7551                 printf("cli_openx failed: %s\n", nt_errstr(status));
7552                 goto out;
7553         }
7554
7555         status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
7556                                 NULL, NULL, NULL);
7557         if (!NT_STATUS_IS_OK(status)) {
7558                 printf("cli_qpathinfo2 (2) returned %s\n",
7559                        nt_errstr(status));
7560                 goto out;
7561         }
7562
7563         if (timespec_compare(&create_time1, &create_time)) {
7564                 printf("run_dir_createtime: create time was updated (error)\n");
7565         } else {
7566                 printf("run_dir_createtime: create time was not updated (correct)\n");
7567                 ret = true;
7568         }
7569
7570   out:
7571
7572         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7573         cli_rmdir(cli, dname);
7574         if (!torture_close_connection(cli)) {
7575                 ret = false;
7576         }
7577         return ret;
7578 }
7579
7580
7581 static bool run_streamerror(int dummy)
7582 {
7583         struct cli_state *cli;
7584         const char *dname = "\\testdir";
7585         const char *streamname =
7586                 "testdir:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
7587         NTSTATUS status;
7588         time_t change_time, access_time, write_time;
7589         off_t size;
7590         uint16_t mode, fnum;
7591         bool ret = true;
7592
7593         if (!torture_open_connection(&cli, 0)) {
7594                 return false;
7595         }
7596
7597         cli_unlink(cli, "\\testdir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7598         cli_rmdir(cli, dname);
7599
7600         status = cli_mkdir(cli, dname);
7601         if (!NT_STATUS_IS_OK(status)) {
7602                 printf("mkdir failed: %s\n", nt_errstr(status));
7603                 return false;
7604         }
7605
7606         status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
7607                                 &write_time, &size, &mode);
7608         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7609                 printf("pathinfo returned %s, expected "
7610                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
7611                        nt_errstr(status));
7612                 ret = false;
7613         }
7614
7615         status = cli_ntcreate(cli, streamname, 0x16,
7616                               FILE_READ_DATA|FILE_READ_EA|
7617                               FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
7618                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7619                               FILE_OPEN, 0, 0, &fnum);
7620
7621         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7622                 printf("ntcreate returned %s, expected "
7623                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
7624                        nt_errstr(status));
7625                 ret = false;
7626         }
7627
7628
7629         cli_rmdir(cli, dname);
7630         return ret;
7631 }
7632
7633 static bool run_local_substitute(int dummy)
7634 {
7635         bool ok = true;
7636
7637         ok &= subst_test("%U", "bla", "", -1, -1, "bla");
7638         ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
7639         ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
7640         ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
7641         ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
7642         ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
7643         ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
7644         ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
7645
7646         /* Different captialization rules in sub_basic... */
7647
7648         ok &=  (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
7649                        "blaDOM") == 0);
7650
7651         return ok;
7652 }
7653
7654 static bool run_local_base64(int dummy)
7655 {
7656         int i;
7657         bool ret = true;
7658
7659         for (i=1; i<2000; i++) {
7660                 DATA_BLOB blob1, blob2;
7661                 char *b64;
7662
7663                 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
7664                 blob1.length = i;
7665                 generate_random_buffer(blob1.data, blob1.length);
7666
7667                 b64 = base64_encode_data_blob(talloc_tos(), blob1);
7668                 if (b64 == NULL) {
7669                         d_fprintf(stderr, "base64_encode_data_blob failed "
7670                                   "for %d bytes\n", i);
7671                         ret = false;
7672                 }
7673                 blob2 = base64_decode_data_blob(b64);
7674                 TALLOC_FREE(b64);
7675
7676                 if (data_blob_cmp(&blob1, &blob2)) {
7677                         d_fprintf(stderr, "data_blob_cmp failed for %d "
7678                                   "bytes\n", i);
7679                         ret = false;
7680                 }
7681                 TALLOC_FREE(blob1.data);
7682                 data_blob_free(&blob2);
7683         }
7684         return ret;
7685 }
7686
7687 static bool run_local_gencache(int dummy)
7688 {
7689         char *val;
7690         time_t tm;
7691         DATA_BLOB blob;
7692
7693         if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
7694                 d_printf("%s: gencache_set() failed\n", __location__);
7695                 return False;
7696         }
7697
7698         if (!gencache_get("foo", NULL, NULL)) {
7699                 d_printf("%s: gencache_get() failed\n", __location__);
7700                 return False;
7701         }
7702
7703         if (!gencache_get("foo", &val, &tm)) {
7704                 d_printf("%s: gencache_get() failed\n", __location__);
7705                 return False;
7706         }
7707
7708         if (strcmp(val, "bar") != 0) {
7709                 d_printf("%s: gencache_get() returned %s, expected %s\n",
7710                          __location__, val, "bar");
7711                 SAFE_FREE(val);
7712                 return False;
7713         }
7714
7715         SAFE_FREE(val);
7716
7717         if (!gencache_del("foo")) {
7718                 d_printf("%s: gencache_del() failed\n", __location__);
7719                 return False;
7720         }
7721         if (gencache_del("foo")) {
7722                 d_printf("%s: second gencache_del() succeeded\n",
7723                          __location__);
7724                 return False;
7725         }
7726
7727         if (gencache_get("foo", &val, &tm)) {
7728                 d_printf("%s: gencache_get() on deleted entry "
7729                          "succeeded\n", __location__);
7730                 return False;
7731         }
7732
7733         blob = data_blob_string_const_null("bar");
7734         tm = time(NULL) + 60;
7735
7736         if (!gencache_set_data_blob("foo", &blob, tm)) {
7737                 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
7738                 return False;
7739         }
7740
7741         if (!gencache_get_data_blob("foo", &blob, NULL, NULL)) {
7742                 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
7743                 return False;
7744         }
7745
7746         if (strcmp((const char *)blob.data, "bar") != 0) {
7747                 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
7748                          __location__, (const char *)blob.data, "bar");
7749                 data_blob_free(&blob);
7750                 return False;
7751         }
7752
7753         data_blob_free(&blob);
7754
7755         if (!gencache_del("foo")) {
7756                 d_printf("%s: gencache_del() failed\n", __location__);
7757                 return False;
7758         }
7759         if (gencache_del("foo")) {
7760                 d_printf("%s: second gencache_del() succeeded\n",
7761                          __location__);
7762                 return False;
7763         }
7764
7765         if (gencache_get_data_blob("foo", &blob, NULL, NULL)) {
7766                 d_printf("%s: gencache_get_data_blob() on deleted entry "
7767                          "succeeded\n", __location__);
7768                 return False;
7769         }
7770
7771         return True;
7772 }
7773
7774 static bool rbt_testval(struct db_context *db, const char *key,
7775                         const char *value)
7776 {
7777         struct db_record *rec;
7778         TDB_DATA data = string_tdb_data(value);
7779         bool ret = false;
7780         NTSTATUS status;
7781         TDB_DATA dbvalue;
7782
7783         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
7784         if (rec == NULL) {
7785                 d_fprintf(stderr, "fetch_locked failed\n");
7786                 goto done;
7787         }
7788         status = dbwrap_record_store(rec, data, 0);
7789         if (!NT_STATUS_IS_OK(status)) {
7790                 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
7791                 goto done;
7792         }
7793         TALLOC_FREE(rec);
7794
7795         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
7796         if (rec == NULL) {
7797                 d_fprintf(stderr, "second fetch_locked failed\n");
7798                 goto done;
7799         }
7800
7801         dbvalue = dbwrap_record_get_value(rec);
7802         if ((dbvalue.dsize != data.dsize)
7803             || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
7804                 d_fprintf(stderr, "Got wrong data back\n");
7805                 goto done;
7806         }
7807
7808         ret = true;
7809  done:
7810         TALLOC_FREE(rec);
7811         return ret;
7812 }
7813
7814 static bool run_local_rbtree(int dummy)
7815 {
7816         struct db_context *db;
7817         bool ret = false;
7818         int i;
7819
7820         db = db_open_rbt(NULL);
7821
7822         if (db == NULL) {
7823                 d_fprintf(stderr, "db_open_rbt failed\n");
7824                 return false;
7825         }
7826
7827         for (i=0; i<1000; i++) {
7828                 char *key, *value;
7829
7830                 if (asprintf(&key, "key%ld", random()) == -1) {
7831                         goto done;
7832                 }
7833                 if (asprintf(&value, "value%ld", random()) == -1) {
7834                         SAFE_FREE(key);
7835                         goto done;
7836                 }
7837
7838                 if (!rbt_testval(db, key, value)) {
7839                         SAFE_FREE(key);
7840                         SAFE_FREE(value);
7841                         goto done;
7842                 }
7843
7844                 SAFE_FREE(value);
7845                 if (asprintf(&value, "value%ld", random()) == -1) {
7846                         SAFE_FREE(key);
7847                         goto done;
7848                 }
7849
7850                 if (!rbt_testval(db, key, value)) {
7851                         SAFE_FREE(key);
7852                         SAFE_FREE(value);
7853                         goto done;
7854                 }
7855
7856                 SAFE_FREE(key);
7857                 SAFE_FREE(value);
7858         }
7859
7860         ret = true;
7861
7862  done:
7863         TALLOC_FREE(db);
7864         return ret;
7865 }
7866
7867
7868 /*
7869   local test for character set functions
7870
7871   This is a very simple test for the functionality in convert_string_error()
7872  */
7873 static bool run_local_convert_string(int dummy)
7874 {
7875         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
7876         const char *test_strings[2] = { "March", "M\303\244rz" };
7877         char dst[7];
7878         int i;
7879
7880         for (i=0; i<2; i++) {
7881                 const char *str = test_strings[i];
7882                 int len = strlen(str);
7883                 size_t converted_size;
7884                 bool ret;
7885
7886                 memset(dst, 'X', sizeof(dst));
7887
7888                 /* first try with real source length */
7889                 ret = convert_string_error(CH_UNIX, CH_UTF8,
7890                                            str, len,
7891                                            dst, sizeof(dst),
7892                                            &converted_size);
7893                 if (ret != true) {
7894                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
7895                         goto failed;
7896                 }
7897
7898                 if (converted_size != len) {
7899                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
7900                                   str, len, (int)converted_size);
7901                         goto failed;
7902                 }
7903
7904                 if (strncmp(str, dst, converted_size) != 0) {
7905                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
7906                         goto failed;
7907                 }
7908
7909                 if (strlen(str) != converted_size) {
7910                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
7911                                   (int)strlen(str), (int)converted_size);
7912                         goto failed;
7913                 }
7914
7915                 if (dst[converted_size] != 'X') {
7916                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
7917                         goto failed;
7918                 }
7919
7920                 /* now with srclen==-1, this causes the nul to be
7921                  * converted too */
7922                 ret = convert_string_error(CH_UNIX, CH_UTF8,
7923                                            str, -1,
7924                                            dst, sizeof(dst),
7925                                            &converted_size);
7926                 if (ret != true) {
7927                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
7928                         goto failed;
7929                 }
7930
7931                 if (converted_size != len+1) {
7932                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
7933                                   str, len, (int)converted_size);
7934                         goto failed;
7935                 }
7936
7937                 if (strncmp(str, dst, converted_size) != 0) {
7938                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
7939                         goto failed;
7940                 }
7941
7942                 if (len+1 != converted_size) {
7943                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
7944                                   len+1, (int)converted_size);
7945                         goto failed;
7946                 }
7947
7948                 if (dst[converted_size] != 'X') {
7949                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
7950                         goto failed;
7951                 }
7952
7953         }
7954
7955
7956         TALLOC_FREE(tmp_ctx);
7957         return true;
7958 failed:
7959         TALLOC_FREE(tmp_ctx);
7960         return false;
7961 }
7962
7963
7964 struct talloc_dict_test {
7965         int content;
7966 };
7967
7968 static int talloc_dict_traverse_fn(DATA_BLOB key, void *data, void *priv)
7969 {
7970         int *count = (int *)priv;
7971         *count += 1;
7972         return 0;
7973 }
7974
7975 static bool run_local_talloc_dict(int dummy)
7976 {
7977         struct talloc_dict *dict;
7978         struct talloc_dict_test *t;
7979         int key, count, res;
7980         bool ok;
7981
7982         dict = talloc_dict_init(talloc_tos());
7983         if (dict == NULL) {
7984                 return false;
7985         }
7986
7987         t = talloc(talloc_tos(), struct talloc_dict_test);
7988         if (t == NULL) {
7989                 return false;
7990         }
7991
7992         key = 1;
7993         t->content = 1;
7994         ok = talloc_dict_set(dict, data_blob_const(&key, sizeof(key)), &t);
7995         if (!ok) {
7996                 return false;
7997         }
7998
7999         count = 0;
8000         res = talloc_dict_traverse(dict, talloc_dict_traverse_fn, &count);
8001         if (res == -1) {
8002                 return false;
8003         }
8004
8005         if (count != 1) {
8006                 return false;
8007         }
8008
8009         if (count != res) {
8010                 return false;
8011         }
8012
8013         TALLOC_FREE(dict);
8014
8015         return true;
8016 }
8017
8018 static bool run_local_string_to_sid(int dummy) {
8019         struct dom_sid sid;
8020
8021         if (string_to_sid(&sid, "S--1-5-32-545")) {
8022                 printf("allowing S--1-5-32-545\n");
8023                 return false;
8024         }
8025         if (string_to_sid(&sid, "S-1-5-32-+545")) {
8026                 printf("allowing S-1-5-32-+545\n");
8027                 return false;
8028         }
8029         if (string_to_sid(&sid, "S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0")) {
8030                 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
8031                 return false;
8032         }
8033         if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
8034                 printf("allowing S-1-5-32-545-abc\n");
8035                 return false;
8036         }
8037         if (!string_to_sid(&sid, "S-1-5-32-545")) {
8038                 printf("could not parse S-1-5-32-545\n");
8039                 return false;
8040         }
8041         if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
8042                 printf("mis-parsed S-1-5-32-545 as %s\n",
8043                        sid_string_tos(&sid));
8044                 return false;
8045         }
8046         return true;
8047 }
8048
8049 static bool run_local_binary_to_sid(int dummy) {
8050         struct dom_sid *sid = talloc(NULL, struct dom_sid);
8051         static const char good_binary_sid[] = {
8052                 0x1, /* revision number */
8053                 15, /* num auths */
8054                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8055                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8056                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8057                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8058                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8059                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8060                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8061                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8062                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8063                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8064                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8065                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8066                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8067                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8068                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8069                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8070         };
8071
8072         static const char long_binary_sid[] = {
8073                 0x1, /* revision number */
8074                 15, /* num auths */
8075                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8076                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8077                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8078                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8079                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8080                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8081                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8082                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8083                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8084                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8085                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8086                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8087                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8088                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8089                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8090                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8091                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
8092                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
8093                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
8094         };
8095
8096         static const char long_binary_sid2[] = {
8097                 0x1, /* revision number */
8098                 32, /* num auths */
8099                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8100                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8101                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8102                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8103                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8104                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8105                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8106                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8107                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8108                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8109                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8110                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8111                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8112                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8113                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8114                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8115                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
8116                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
8117                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
8118                 0x1, 0x1, 0x1, 0x1, /* auth[18] */
8119                 0x1, 0x1, 0x1, 0x1, /* auth[19] */
8120                 0x1, 0x1, 0x1, 0x1, /* auth[20] */
8121                 0x1, 0x1, 0x1, 0x1, /* auth[21] */
8122                 0x1, 0x1, 0x1, 0x1, /* auth[22] */
8123                 0x1, 0x1, 0x1, 0x1, /* auth[23] */
8124                 0x1, 0x1, 0x1, 0x1, /* auth[24] */
8125                 0x1, 0x1, 0x1, 0x1, /* auth[25] */
8126                 0x1, 0x1, 0x1, 0x1, /* auth[26] */
8127                 0x1, 0x1, 0x1, 0x1, /* auth[27] */
8128                 0x1, 0x1, 0x1, 0x1, /* auth[28] */
8129                 0x1, 0x1, 0x1, 0x1, /* auth[29] */
8130                 0x1, 0x1, 0x1, 0x1, /* auth[30] */
8131                 0x1, 0x1, 0x1, 0x1, /* auth[31] */
8132         };
8133
8134         if (!sid_parse(good_binary_sid, sizeof(good_binary_sid), sid)) {
8135                 return false;
8136         }
8137         if (sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid)) {
8138                 return false;
8139         }
8140         if (sid_parse(long_binary_sid, sizeof(long_binary_sid), sid)) {
8141                 return false;
8142         }
8143         return true;
8144 }
8145
8146 /* Split a path name into filename and stream name components. Canonicalise
8147  * such that an implicit $DATA token is always explicit.
8148  *
8149  * The "specification" of this function can be found in the
8150  * run_local_stream_name() function in torture.c, I've tried those
8151  * combinations against a W2k3 server.
8152  */
8153
8154 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
8155                                        char **pbase, char **pstream)
8156 {
8157         char *base = NULL;
8158         char *stream = NULL;
8159         char *sname; /* stream name */
8160         const char *stype; /* stream type */
8161
8162         DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
8163
8164         sname = strchr_m(fname, ':');
8165
8166         if (lp_posix_pathnames() || (sname == NULL)) {
8167                 if (pbase != NULL) {
8168                         base = talloc_strdup(mem_ctx, fname);
8169                         NT_STATUS_HAVE_NO_MEMORY(base);
8170                 }
8171                 goto done;
8172         }
8173
8174         if (pbase != NULL) {
8175                 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
8176                 NT_STATUS_HAVE_NO_MEMORY(base);
8177         }
8178
8179         sname += 1;
8180
8181         stype = strchr_m(sname, ':');
8182
8183         if (stype == NULL) {
8184                 sname = talloc_strdup(mem_ctx, sname);
8185                 stype = "$DATA";
8186         }
8187         else {
8188                 if (strcasecmp_m(stype, ":$DATA") != 0) {
8189                         /*
8190                          * If there is an explicit stream type, so far we only
8191                          * allow $DATA. Is there anything else allowed? -- vl
8192                          */
8193                         DEBUG(10, ("[%s] is an invalid stream type\n", stype));
8194                         TALLOC_FREE(base);
8195                         return NT_STATUS_OBJECT_NAME_INVALID;
8196                 }
8197                 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
8198                 stype += 1;
8199         }
8200
8201         if (sname == NULL) {
8202                 TALLOC_FREE(base);
8203                 return NT_STATUS_NO_MEMORY;
8204         }
8205
8206         if (sname[0] == '\0') {
8207                 /*
8208                  * no stream name, so no stream
8209                  */
8210                 goto done;
8211         }
8212
8213         if (pstream != NULL) {
8214                 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
8215                 if (stream == NULL) {
8216                         TALLOC_FREE(sname);
8217                         TALLOC_FREE(base);
8218                         return NT_STATUS_NO_MEMORY;
8219                 }
8220                 /*
8221                  * upper-case the type field
8222                  */
8223                 strupper_m(strchr_m(stream, ':')+1);
8224         }
8225
8226  done:
8227         if (pbase != NULL) {
8228                 *pbase = base;
8229         }
8230         if (pstream != NULL) {
8231                 *pstream = stream;
8232         }
8233         return NT_STATUS_OK;
8234 }
8235
8236 static bool test_stream_name(const char *fname, const char *expected_base,
8237                              const char *expected_stream,
8238                              NTSTATUS expected_status)
8239 {
8240         NTSTATUS status;
8241         char *base = NULL;
8242         char *stream = NULL;
8243
8244         status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
8245         if (!NT_STATUS_EQUAL(status, expected_status)) {
8246                 goto error;
8247         }
8248
8249         if (!NT_STATUS_IS_OK(status)) {
8250                 return true;
8251         }
8252
8253         if (base == NULL) goto error;
8254
8255         if (strcmp(expected_base, base) != 0) goto error;
8256
8257         if ((expected_stream != NULL) && (stream == NULL)) goto error;
8258         if ((expected_stream == NULL) && (stream != NULL)) goto error;
8259
8260         if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
8261                 goto error;
8262
8263         TALLOC_FREE(base);
8264         TALLOC_FREE(stream);
8265         return true;
8266
8267  error:
8268         d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
8269                   fname, expected_base ? expected_base : "<NULL>",
8270                   expected_stream ? expected_stream : "<NULL>",
8271                   nt_errstr(expected_status));
8272         d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
8273                   base ? base : "<NULL>", stream ? stream : "<NULL>",
8274                   nt_errstr(status));
8275         TALLOC_FREE(base);
8276         TALLOC_FREE(stream);
8277         return false;
8278 }
8279
8280 static bool run_local_stream_name(int dummy)
8281 {
8282         bool ret = true;
8283
8284         ret &= test_stream_name(
8285                 "bla", "bla", NULL, NT_STATUS_OK);
8286         ret &= test_stream_name(
8287                 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
8288         ret &= test_stream_name(
8289                 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8290         ret &= test_stream_name(
8291                 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
8292         ret &= test_stream_name(
8293                 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8294         ret &= test_stream_name(
8295                 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
8296         ret &= test_stream_name(
8297                 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
8298         ret &= test_stream_name(
8299                 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
8300
8301         return ret;
8302 }
8303
8304 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
8305 {
8306         if (a.length != b.length) {
8307                 printf("a.length=%d != b.length=%d\n",
8308                        (int)a.length, (int)b.length);
8309                 return false;
8310         }
8311         if (memcmp(a.data, b.data, a.length) != 0) {
8312                 printf("a.data and b.data differ\n");
8313                 return false;
8314         }
8315         return true;
8316 }
8317
8318 static bool run_local_memcache(int dummy)
8319 {
8320         struct memcache *cache;
8321         DATA_BLOB k1, k2;
8322         DATA_BLOB d1, d2, d3;
8323         DATA_BLOB v1, v2, v3;
8324
8325         TALLOC_CTX *mem_ctx;
8326         char *str1, *str2;
8327         size_t size1, size2;
8328         bool ret = false;
8329
8330         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
8331
8332         if (cache == NULL) {
8333                 printf("memcache_init failed\n");
8334                 return false;
8335         }
8336
8337         d1 = data_blob_const("d1", 2);
8338         d2 = data_blob_const("d2", 2);
8339         d3 = data_blob_const("d3", 2);
8340
8341         k1 = data_blob_const("d1", 2);
8342         k2 = data_blob_const("d2", 2);
8343
8344         memcache_add(cache, STAT_CACHE, k1, d1);
8345         memcache_add(cache, GETWD_CACHE, k2, d2);
8346
8347         if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
8348                 printf("could not find k1\n");
8349                 return false;
8350         }
8351         if (!data_blob_equal(d1, v1)) {
8352                 return false;
8353         }
8354
8355         if (!memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8356                 printf("could not find k2\n");
8357                 return false;
8358         }
8359         if (!data_blob_equal(d2, v2)) {
8360                 return false;
8361         }
8362
8363         memcache_add(cache, STAT_CACHE, k1, d3);
8364
8365         if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
8366                 printf("could not find replaced k1\n");
8367                 return false;
8368         }
8369         if (!data_blob_equal(d3, v3)) {
8370                 return false;
8371         }
8372
8373         memcache_add(cache, GETWD_CACHE, k1, d1);
8374
8375         if (memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8376                 printf("Did find k2, should have been purged\n");
8377                 return false;
8378         }
8379
8380         TALLOC_FREE(cache);
8381
8382         cache = memcache_init(NULL, 0);
8383
8384         mem_ctx = talloc_init("foo");
8385
8386         str1 = talloc_strdup(mem_ctx, "string1");
8387         str2 = talloc_strdup(mem_ctx, "string2");
8388
8389         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8390                             data_blob_string_const("torture"), &str1);
8391         size1 = talloc_total_size(cache);
8392
8393         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8394                             data_blob_string_const("torture"), &str2);
8395         size2 = talloc_total_size(cache);
8396
8397         printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
8398
8399         if (size2 > size1) {
8400                 printf("memcache leaks memory!\n");
8401                 goto fail;
8402         }
8403
8404         ret = true;
8405  fail:
8406         TALLOC_FREE(cache);
8407         return ret;
8408 }
8409
8410 static void wbclient_done(struct tevent_req *req)
8411 {
8412         wbcErr wbc_err;
8413         struct winbindd_response *wb_resp;
8414         int *i = (int *)tevent_req_callback_data_void(req);
8415
8416         wbc_err = wb_trans_recv(req, req, &wb_resp);
8417         TALLOC_FREE(req);
8418         *i += 1;
8419         d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
8420 }
8421
8422 static bool run_local_wbclient(int dummy)
8423 {
8424         struct event_context *ev;
8425         struct wb_context **wb_ctx;
8426         struct winbindd_request wb_req;
8427         bool result = false;
8428         int i, j;
8429
8430         BlockSignals(True, SIGPIPE);
8431
8432         ev = tevent_context_init_byname(talloc_tos(), "epoll");
8433         if (ev == NULL) {
8434                 goto fail;
8435         }
8436
8437         wb_ctx = talloc_array(ev, struct wb_context *, nprocs);
8438         if (wb_ctx == NULL) {
8439                 goto fail;
8440         }
8441
8442         ZERO_STRUCT(wb_req);
8443         wb_req.cmd = WINBINDD_PING;
8444
8445         d_printf("nprocs=%d, numops=%d\n", (int)nprocs, (int)torture_numops);
8446
8447         for (i=0; i<nprocs; i++) {
8448                 wb_ctx[i] = wb_context_init(ev, NULL);
8449                 if (wb_ctx[i] == NULL) {
8450                         goto fail;
8451                 }
8452                 for (j=0; j<torture_numops; j++) {
8453                         struct tevent_req *req;
8454                         req = wb_trans_send(ev, ev, wb_ctx[i],
8455                                             (j % 2) == 0, &wb_req);
8456                         if (req == NULL) {
8457                                 goto fail;
8458                         }
8459                         tevent_req_set_callback(req, wbclient_done, &i);
8460                 }
8461         }
8462
8463         i = 0;
8464
8465         while (i < nprocs * torture_numops) {
8466                 tevent_loop_once(ev);
8467         }
8468
8469         result = true;
8470  fail:
8471         TALLOC_FREE(ev);
8472         return result;
8473 }
8474
8475 static void getaddrinfo_finished(struct tevent_req *req)
8476 {
8477         char *name = (char *)tevent_req_callback_data_void(req);
8478         struct addrinfo *ainfo;
8479         int res;
8480
8481         res = getaddrinfo_recv(req, &ainfo);
8482         if (res != 0) {
8483                 d_printf("gai(%s) returned %s\n", name, gai_strerror(res));
8484                 return;
8485         }
8486         d_printf("gai(%s) succeeded\n", name);
8487         freeaddrinfo(ainfo);
8488 }
8489
8490 static bool run_getaddrinfo_send(int dummy)
8491 {
8492         TALLOC_CTX *frame = talloc_stackframe();
8493         struct fncall_context *ctx;
8494         struct tevent_context *ev;
8495         bool result = false;
8496         const char *names[4] = { "www.samba.org", "notfound.samba.org",
8497                                  "www.slashdot.org", "heise.de" };
8498         struct tevent_req *reqs[4];
8499         int i;
8500
8501         ev = event_context_init(frame);
8502         if (ev == NULL) {
8503                 goto fail;
8504         }
8505
8506         ctx = fncall_context_init(frame, 4);
8507
8508         for (i=0; i<ARRAY_SIZE(names); i++) {
8509                 reqs[i] = getaddrinfo_send(frame, ev, ctx, names[i], NULL,
8510                                            NULL);
8511                 if (reqs[i] == NULL) {
8512                         goto fail;
8513                 }
8514                 tevent_req_set_callback(reqs[i], getaddrinfo_finished,
8515                                         discard_const_p(void, names[i]));
8516         }
8517
8518         for (i=0; i<ARRAY_SIZE(reqs); i++) {
8519                 tevent_loop_once(ev);
8520         }
8521
8522         result = true;
8523 fail:
8524         TALLOC_FREE(frame);
8525         return result;
8526 }
8527
8528 static bool dbtrans_inc(struct db_context *db)
8529 {
8530         struct db_record *rec;
8531         uint32_t val;
8532         bool ret = false;
8533         NTSTATUS status;
8534         TDB_DATA value;
8535
8536         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
8537         if (rec == NULL) {
8538                 printf(__location__ "fetch_lock failed\n");
8539                 return false;
8540         }
8541
8542         value = dbwrap_record_get_value(rec);
8543
8544         if (value.dsize != sizeof(uint32_t)) {
8545                 printf(__location__ "value.dsize = %d\n",
8546                        (int)value.dsize);
8547                 goto fail;
8548         }
8549
8550         memcpy(&val, value.dptr, sizeof(val));
8551         val += 1;
8552
8553         status = dbwrap_record_store(
8554                 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
8555         if (!NT_STATUS_IS_OK(status)) {
8556                 printf(__location__ "store failed: %s\n",
8557                        nt_errstr(status));
8558                 goto fail;
8559         }
8560
8561         ret = true;
8562 fail:
8563         TALLOC_FREE(rec);
8564         return ret;
8565 }
8566
8567 static bool run_local_dbtrans(int dummy)
8568 {
8569         struct db_context *db;
8570         struct db_record *rec;
8571         NTSTATUS status;
8572         uint32_t initial;
8573         int res;
8574         TDB_DATA value;
8575
8576         db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
8577                      O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1);
8578         if (db == NULL) {
8579                 printf("Could not open transtest.db\n");
8580                 return false;
8581         }
8582
8583         res = dbwrap_transaction_start(db);
8584         if (res != 0) {
8585                 printf(__location__ "transaction_start failed\n");
8586                 return false;
8587         }
8588
8589         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
8590         if (rec == NULL) {
8591                 printf(__location__ "fetch_lock failed\n");
8592                 return false;
8593         }
8594
8595         value = dbwrap_record_get_value(rec);
8596
8597         if (value.dptr == NULL) {
8598                 initial = 0;
8599                 status = dbwrap_record_store(
8600                         rec, make_tdb_data((uint8_t *)&initial,
8601                                            sizeof(initial)),
8602                         0);
8603                 if (!NT_STATUS_IS_OK(status)) {
8604                         printf(__location__ "store returned %s\n",
8605                                nt_errstr(status));
8606                         return false;
8607                 }
8608         }
8609
8610         TALLOC_FREE(rec);
8611
8612         res = dbwrap_transaction_commit(db);
8613         if (res != 0) {
8614                 printf(__location__ "transaction_commit failed\n");
8615                 return false;
8616         }
8617
8618         while (true) {
8619                 uint32_t val, val2;
8620                 int i;
8621
8622                 res = dbwrap_transaction_start(db);
8623                 if (res != 0) {
8624                         printf(__location__ "transaction_start failed\n");
8625                         break;
8626                 }
8627
8628                 status = dbwrap_fetch_uint32(db, "transtest", &val);
8629                 if (!NT_STATUS_IS_OK(status)) {
8630                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
8631                                nt_errstr(status));
8632                         break;
8633                 }
8634
8635                 for (i=0; i<10; i++) {
8636                         if (!dbtrans_inc(db)) {
8637                                 return false;
8638                         }
8639                 }
8640
8641                 status = dbwrap_fetch_uint32(db, "transtest", &val2);
8642                 if (!NT_STATUS_IS_OK(status)) {
8643                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
8644                                nt_errstr(status));
8645                         break;
8646                 }
8647
8648                 if (val2 != val + 10) {
8649                         printf(__location__ "val=%d, val2=%d\n",
8650                                (int)val, (int)val2);
8651                         break;
8652                 }
8653
8654                 printf("val2=%d\r", val2);
8655
8656                 res = dbwrap_transaction_commit(db);
8657                 if (res != 0) {
8658                         printf(__location__ "transaction_commit failed\n");
8659                         break;
8660                 }
8661         }
8662
8663         TALLOC_FREE(db);
8664         return true;
8665 }
8666
8667 /*
8668  * Just a dummy test to be run under a debugger. There's no real way
8669  * to inspect the tevent_select specific function from outside of
8670  * tevent_select.c.
8671  */
8672
8673 static bool run_local_tevent_select(int dummy)
8674 {
8675         struct tevent_context *ev;
8676         struct tevent_fd *fd1, *fd2;
8677         bool result = false;
8678
8679         ev = tevent_context_init_byname(NULL, "select");
8680         if (ev == NULL) {
8681                 d_fprintf(stderr, "tevent_context_init_byname failed\n");
8682                 goto fail;
8683         }
8684
8685         fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
8686         if (fd1 == NULL) {
8687                 d_fprintf(stderr, "tevent_add_fd failed\n");
8688                 goto fail;
8689         }
8690         fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
8691         if (fd2 == NULL) {
8692                 d_fprintf(stderr, "tevent_add_fd failed\n");
8693                 goto fail;
8694         }
8695         TALLOC_FREE(fd2);
8696
8697         fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
8698         if (fd2 == NULL) {
8699                 d_fprintf(stderr, "tevent_add_fd failed\n");
8700                 goto fail;
8701         }
8702
8703         result = true;
8704 fail:
8705         TALLOC_FREE(ev);
8706         return result;
8707 }
8708
8709 static bool run_local_hex_encode_buf(int dummy)
8710 {
8711         char buf[17];
8712         uint8_t src[8];
8713         int i;
8714
8715         for (i=0; i<sizeof(src); i++) {
8716                 src[i] = i;
8717         }
8718         hex_encode_buf(buf, src, sizeof(src));
8719         if (strcmp(buf, "0001020304050607") != 0) {
8720                 return false;
8721         }
8722         hex_encode_buf(buf, NULL, 0);
8723         if (buf[0] != '\0') {
8724                 return false;
8725         }
8726         return true;
8727 }
8728
8729 static double create_procs(bool (*fn)(int), bool *result)
8730 {
8731         int i, status;
8732         volatile pid_t *child_status;
8733         volatile bool *child_status_out;
8734         int synccount;
8735         int tries = 8;
8736         struct timeval start;
8737
8738         synccount = 0;
8739
8740         child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*nprocs);
8741         if (!child_status) {
8742                 printf("Failed to setup shared memory\n");
8743                 return -1;
8744         }
8745
8746         child_status_out = (volatile bool *)shm_setup(sizeof(bool)*nprocs);
8747         if (!child_status_out) {
8748                 printf("Failed to setup result status shared memory\n");
8749                 return -1;
8750         }
8751
8752         for (i = 0; i < nprocs; i++) {
8753                 child_status[i] = 0;
8754                 child_status_out[i] = True;
8755         }
8756
8757         start = timeval_current();
8758
8759         for (i=0;i<nprocs;i++) {
8760                 procnum = i;
8761                 if (fork() == 0) {
8762                         pid_t mypid = getpid();
8763                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
8764
8765                         slprintf(myname,sizeof(myname),"CLIENT%d", i);
8766
8767                         while (1) {
8768                                 if (torture_open_connection(&current_cli, i)) break;
8769                                 if (tries-- == 0) {
8770                                         printf("pid %d failed to start\n", (int)getpid());
8771                                         _exit(1);
8772                                 }
8773                                 smb_msleep(10); 
8774                         }
8775
8776                         child_status[i] = getpid();
8777
8778                         while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
8779
8780                         child_status_out[i] = fn(i);
8781                         _exit(0);
8782                 }
8783         }
8784
8785         do {
8786                 synccount = 0;
8787                 for (i=0;i<nprocs;i++) {
8788                         if (child_status[i]) synccount++;
8789                 }
8790                 if (synccount == nprocs) break;
8791                 smb_msleep(10);
8792         } while (timeval_elapsed(&start) < 30);
8793
8794         if (synccount != nprocs) {
8795                 printf("FAILED TO START %d CLIENTS (started %d)\n", nprocs, synccount);
8796                 *result = False;
8797                 return timeval_elapsed(&start);
8798         }
8799
8800         /* start the client load */
8801         start = timeval_current();
8802
8803         for (i=0;i<nprocs;i++) {
8804                 child_status[i] = 0;
8805         }
8806
8807         printf("%d clients started\n", nprocs);
8808
8809         for (i=0;i<nprocs;i++) {
8810                 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
8811         }
8812
8813         printf("\n");
8814
8815         for (i=0;i<nprocs;i++) {
8816                 if (!child_status_out[i]) {
8817                         *result = False;
8818                 }
8819         }
8820         return timeval_elapsed(&start);
8821 }
8822
8823 #define FLAG_MULTIPROC 1
8824
8825 static struct {
8826         const char *name;
8827         bool (*fn)(int);
8828         unsigned flags;
8829 } torture_ops[] = {
8830         {"FDPASS", run_fdpasstest, 0},
8831         {"LOCK1",  run_locktest1,  0},
8832         {"LOCK2",  run_locktest2,  0},
8833         {"LOCK3",  run_locktest3,  0},
8834         {"LOCK4",  run_locktest4,  0},
8835         {"LOCK5",  run_locktest5,  0},
8836         {"LOCK6",  run_locktest6,  0},
8837         {"LOCK7",  run_locktest7,  0},
8838         {"LOCK8",  run_locktest8,  0},
8839         {"LOCK9",  run_locktest9,  0},
8840         {"UNLINK", run_unlinktest, 0},
8841         {"BROWSE", run_browsetest, 0},
8842         {"ATTR",   run_attrtest,   0},
8843         {"TRANS2", run_trans2test, 0},
8844         {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
8845         {"TORTURE",run_torture,    FLAG_MULTIPROC},
8846         {"RANDOMIPC", run_randomipc, 0},
8847         {"NEGNOWAIT", run_negprot_nowait, 0},
8848         {"NBENCH",  run_nbench, 0},
8849         {"NBENCH2", run_nbench2, 0},
8850         {"OPLOCK1",  run_oplock1, 0},
8851         {"OPLOCK2",  run_oplock2, 0},
8852         {"OPLOCK4",  run_oplock4, 0},
8853         {"DIR",  run_dirtest, 0},
8854         {"DIR1",  run_dirtest1, 0},
8855         {"DIR-CREATETIME",  run_dir_createtime, 0},
8856         {"DENY1",  torture_denytest1, 0},
8857         {"DENY2",  torture_denytest2, 0},
8858         {"TCON",  run_tcon_test, 0},
8859         {"TCONDEV",  run_tcon_devtype_test, 0},
8860         {"RW1",  run_readwritetest, 0},
8861         {"RW2",  run_readwritemulti, FLAG_MULTIPROC},
8862         {"RW3",  run_readwritelarge, 0},
8863         {"RW-SIGNING",  run_readwritelarge_signtest, 0},
8864         {"OPEN", run_opentest, 0},
8865         {"POSIX", run_simple_posix_open_test, 0},
8866         {"POSIX-APPEND", run_posix_append, 0},
8867         {"CASE-INSENSITIVE-CREATE", run_case_insensitive_create, 0},
8868         {"ASYNC-ECHO", run_async_echo, 0},
8869         { "UID-REGRESSION-TEST", run_uid_regression_test, 0},
8870         { "SHORTNAME-TEST", run_shortname_test, 0},
8871         { "ADDRCHANGE", run_addrchange, 0},
8872 #if 1
8873         {"OPENATTR", run_openattrtest, 0},
8874 #endif
8875         {"XCOPY", run_xcopy, 0},
8876         {"RENAME", run_rename, 0},
8877         {"DELETE", run_deletetest, 0},
8878         {"DELETE-LN", run_deletetest_ln, 0},
8879         {"PROPERTIES", run_properties, 0},
8880         {"MANGLE", torture_mangle, 0},
8881         {"MANGLE1", run_mangle1, 0},
8882         {"W2K", run_w2ktest, 0},
8883         {"TRANS2SCAN", torture_trans2_scan, 0},
8884         {"NTTRANSSCAN", torture_nttrans_scan, 0},
8885         {"UTABLE", torture_utable, 0},
8886         {"CASETABLE", torture_casetable, 0},
8887         {"ERRMAPEXTRACT", run_error_map_extract, 0},
8888         {"PIPE_NUMBER", run_pipe_number, 0},
8889         {"TCON2",  run_tcon2_test, 0},
8890         {"IOCTL",  torture_ioctl_test, 0},
8891         {"CHKPATH",  torture_chkpath_test, 0},
8892         {"FDSESS", run_fdsesstest, 0},
8893         { "EATEST", run_eatest, 0},
8894         { "SESSSETUP_BENCH", run_sesssetup_bench, 0},
8895         { "CHAIN1", run_chain1, 0},
8896         { "CHAIN2", run_chain2, 0},
8897         { "CHAIN3", run_chain3, 0},
8898         { "WINDOWS-WRITE", run_windows_write, 0},
8899         { "NTTRANS-CREATE", run_nttrans_create, 0},
8900         { "NTTRANS-FSCTL", run_nttrans_fsctl, 0},
8901         { "CLI_ECHO", run_cli_echo, 0},
8902         { "GETADDRINFO", run_getaddrinfo_send, 0},
8903         { "TLDAP", run_tldap },
8904         { "STREAMERROR", run_streamerror },
8905         { "NOTIFY-BENCH", run_notify_bench },
8906         { "BAD-NBT-SESSION", run_bad_nbt_session },
8907         { "SMB-ANY-CONNECT", run_smb_any_connect },
8908         { "NOTIFY-ONLINE", run_notify_online },
8909         { "SMB2-BASIC", run_smb2_basic },
8910         { "SMB2-NEGPROT", run_smb2_negprot },
8911         { "SMB2-SESSION-RECONNECT", run_smb2_session_reconnect },
8912         { "SMB2-TCON-DEPENDENCE", run_smb2_tcon_dependence },
8913         { "SMB2-MULTI-CHANNEL", run_smb2_multi_channel },
8914         { "SMB2-SESSION-REAUTH", run_smb2_session_reauth },
8915         { "CLEANUP1", run_cleanup1 },
8916         { "CLEANUP2", run_cleanup2 },
8917         { "LOCAL-SUBSTITUTE", run_local_substitute, 0},
8918         { "LOCAL-GENCACHE", run_local_gencache, 0},
8919         { "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0},
8920         { "LOCAL-BASE64", run_local_base64, 0},
8921         { "LOCAL-RBTREE", run_local_rbtree, 0},
8922         { "LOCAL-MEMCACHE", run_local_memcache, 0},
8923         { "LOCAL-STREAM-NAME", run_local_stream_name, 0},
8924         { "LOCAL-WBCLIENT", run_local_wbclient, 0},
8925         { "LOCAL-string_to_sid", run_local_string_to_sid, 0},
8926         { "LOCAL-binary_to_sid", run_local_binary_to_sid, 0},
8927         { "LOCAL-DBTRANS", run_local_dbtrans, 0},
8928         { "LOCAL-TEVENT-SELECT", run_local_tevent_select, 0},
8929         { "LOCAL-CONVERT-STRING", run_local_convert_string, 0},
8930         { "LOCAL-CONV-AUTH-INFO", run_local_conv_auth_info, 0},
8931         { "LOCAL-sprintf_append", run_local_sprintf_append, 0},
8932         { "LOCAL-hex_encode_buf", run_local_hex_encode_buf, 0},
8933         {NULL, NULL, 0}};
8934
8935
8936
8937 /****************************************************************************
8938 run a specified test or "ALL"
8939 ****************************************************************************/
8940 static bool run_test(const char *name)
8941 {
8942         bool ret = True;
8943         bool result = True;
8944         bool found = False;
8945         int i;
8946         double t;
8947         if (strequal(name,"ALL")) {
8948                 for (i=0;torture_ops[i].name;i++) {
8949                         run_test(torture_ops[i].name);
8950                 }
8951                 found = True;
8952         }
8953
8954         for (i=0;torture_ops[i].name;i++) {
8955                 fstr_sprintf(randomfname, "\\XX%x", 
8956                          (unsigned)random());
8957
8958                 if (strequal(name, torture_ops[i].name)) {
8959                         found = True;
8960                         printf("Running %s\n", name);
8961                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
8962                                 t = create_procs(torture_ops[i].fn, &result);
8963                                 if (!result) { 
8964                                         ret = False;
8965                                         printf("TEST %s FAILED!\n", name);
8966                                 }
8967                         } else {
8968                                 struct timeval start;
8969                                 start = timeval_current();
8970                                 if (!torture_ops[i].fn(0)) {
8971                                         ret = False;
8972                                         printf("TEST %s FAILED!\n", name);
8973                                 }
8974                                 t = timeval_elapsed(&start);
8975                         }
8976                         printf("%s took %g secs\n\n", name, t);
8977                 }
8978         }
8979
8980         if (!found) {
8981                 printf("Did not find a test named %s\n", name);
8982                 ret = False;
8983         }
8984
8985         return ret;
8986 }
8987
8988
8989 static void usage(void)
8990 {
8991         int i;
8992
8993         printf("WARNING samba4 test suite is much more complete nowadays.\n");
8994         printf("Please use samba4 torture.\n\n");
8995
8996         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
8997
8998         printf("\t-d debuglevel\n");
8999         printf("\t-U user%%pass\n");
9000         printf("\t-k               use kerberos\n");
9001         printf("\t-N numprocs\n");
9002         printf("\t-n my_netbios_name\n");
9003         printf("\t-W workgroup\n");
9004         printf("\t-o num_operations\n");
9005         printf("\t-O socket_options\n");
9006         printf("\t-m maximum protocol\n");
9007         printf("\t-L use oplocks\n");
9008         printf("\t-c CLIENT.TXT   specify client load file for NBENCH\n");
9009         printf("\t-A showall\n");
9010         printf("\t-p port\n");
9011         printf("\t-s seed\n");
9012         printf("\t-b unclist_filename   specify multiple shares for multiple connections\n");
9013         printf("\t-f filename   filename to test\n");
9014         printf("\n\n");
9015
9016         printf("tests are:");
9017         for (i=0;torture_ops[i].name;i++) {
9018                 printf(" %s", torture_ops[i].name);
9019         }
9020         printf("\n");
9021
9022         printf("default test is ALL\n");
9023
9024         exit(1);
9025 }
9026
9027 /****************************************************************************
9028   main program
9029 ****************************************************************************/
9030  int main(int argc,char *argv[])
9031 {
9032         int opt, i;
9033         char *p;
9034         int gotuser = 0;
9035         int gotpass = 0;
9036         bool correct = True;
9037         TALLOC_CTX *frame = talloc_stackframe();
9038         int seed = time(NULL);
9039
9040 #ifdef HAVE_SETBUFFER
9041         setbuffer(stdout, NULL, 0);
9042 #endif
9043
9044         setup_logging("smbtorture", DEBUG_STDOUT);
9045
9046         load_case_tables();
9047
9048         if (is_default_dyn_CONFIGFILE()) {
9049                 if(getenv("SMB_CONF_PATH")) {
9050                         set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
9051                 }
9052         }
9053         lp_load_global(get_dyn_CONFIGFILE());
9054         load_interfaces();
9055
9056         if (argc < 2) {
9057                 usage();
9058         }
9059
9060         for(p = argv[1]; *p; p++)
9061           if(*p == '\\')
9062             *p = '/';
9063
9064         if (strncmp(argv[1], "//", 2)) {
9065                 usage();
9066         }
9067
9068         fstrcpy(host, &argv[1][2]);
9069         p = strchr_m(&host[2],'/');
9070         if (!p) {
9071                 usage();
9072         }
9073         *p = 0;
9074         fstrcpy(share, p+1);
9075
9076         fstrcpy(myname, get_myname(talloc_tos()));
9077         if (!*myname) {
9078                 fprintf(stderr, "Failed to get my hostname.\n");
9079                 return 1;
9080         }
9081
9082         if (*username == 0 && getenv("LOGNAME")) {
9083           fstrcpy(username,getenv("LOGNAME"));
9084         }
9085
9086         argc--;
9087         argv++;
9088
9089         fstrcpy(workgroup, lp_workgroup());
9090
9091         while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
9092                != EOF) {
9093                 switch (opt) {
9094                 case 'p':
9095                         port_to_use = atoi(optarg);
9096                         break;
9097                 case 's':
9098                         seed = atoi(optarg);
9099                         break;
9100                 case 'W':
9101                         fstrcpy(workgroup,optarg);
9102                         break;
9103                 case 'm':
9104                         max_protocol = interpret_protocol(optarg, max_protocol);
9105                         break;
9106                 case 'N':
9107                         nprocs = atoi(optarg);
9108                         break;
9109                 case 'o':
9110                         torture_numops = atoi(optarg);
9111                         break;
9112                 case 'd':
9113                         lp_set_cmdline("log level", optarg);
9114                         break;
9115                 case 'O':
9116                         sockops = optarg;
9117                         break;
9118                 case 'L':
9119                         use_oplocks = True;
9120                         break;
9121                 case 'l':
9122                         local_path = optarg;
9123                         break;
9124                 case 'A':
9125                         torture_showall = True;
9126                         break;
9127                 case 'n':
9128                         fstrcpy(myname, optarg);
9129                         break;
9130                 case 'c':
9131                         client_txt = optarg;
9132                         break;
9133                 case 'e':
9134                         do_encrypt = true;
9135                         break;
9136                 case 'k':
9137 #ifdef HAVE_KRB5
9138                         use_kerberos = True;
9139 #else
9140                         d_printf("No kerberos support compiled in\n");
9141                         exit(1);
9142 #endif
9143                         break;
9144                 case 'U':
9145                         gotuser = 1;
9146                         fstrcpy(username,optarg);
9147                         p = strchr_m(username,'%');
9148                         if (p) {
9149                                 *p = 0;
9150                                 fstrcpy(password, p+1);
9151                                 gotpass = 1;
9152                         }
9153                         break;
9154                 case 'b':
9155                         fstrcpy(multishare_conn_fname, optarg);
9156                         use_multishare_conn = True;
9157                         break;
9158                 case 'B':
9159                         torture_blocksize = atoi(optarg);
9160                         break;
9161                 case 'f':
9162                         test_filename = SMB_STRDUP(optarg);
9163                         break;
9164                 default:
9165                         printf("Unknown option %c (%d)\n", (char)opt, opt);
9166                         usage();
9167                 }
9168         }
9169
9170         d_printf("using seed %d\n", seed);
9171
9172         srandom(seed);
9173
9174         if(use_kerberos && !gotuser) gotpass = True;
9175
9176         while (!gotpass) {
9177                 p = getpass("Password:");
9178                 if (p) {
9179                         fstrcpy(password, p);
9180                         gotpass = 1;
9181                 }
9182         }
9183
9184         printf("host=%s share=%s user=%s myname=%s\n", 
9185                host, share, username, myname);
9186
9187         if (argc == optind) {
9188                 correct = run_test("ALL");
9189         } else {
9190                 for (i=optind;i<argc;i++) {
9191                         if (!run_test(argv[i])) {
9192                                 correct = False;
9193                         }
9194                 }
9195         }
9196
9197         TALLOC_FREE(frame);
9198
9199         if (correct) {
9200                 return(0);
9201         } else {
9202                 return(1);
9203         }
9204 }