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