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