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