s3:torture: make use of CLI_FULL_CONNECTION_FORCE_DOS_ERRORS
[kai/samba.git] / source3 / torture / torture.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB torture tester
4    Copyright (C) Andrew Tridgell 1997-1998
5    Copyright (C) Jeremy Allison 2009
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "system/shmem.h"
23 #include "wbc_async.h"
24 #include "torture/proto.h"
25 #include "libcli/security/security.h"
26 #include "tldap.h"
27 #include "tldap_util.h"
28 #include "../librpc/gen_ndr/svcctl.h"
29 #include "memcache.h"
30 #include "nsswitch/winbind_client.h"
31 #include "dbwrap/dbwrap.h"
32 #include "dbwrap/dbwrap_open.h"
33 #include "talloc_dict.h"
34 #include "async_smb.h"
35 #include "libsmb/libsmb.h"
36 #include "libsmb/clirap.h"
37 #include "trans2.h"
38 #include "libsmb/nmblib.h"
39 #include "../lib/util/tevent_ntstatus.h"
40 #include "util_tdb.h"
41 #include "libsmb/read_smb.h"
42
43 extern char *optarg;
44 extern int optind;
45
46 fstring host, workgroup, share, password, username, myname;
47 static int max_protocol = PROTOCOL_NT1;
48 static const char *sockops="TCP_NODELAY";
49 static int nprocs=1;
50 static int port_to_use=0;
51 int torture_numops=100;
52 int torture_blocksize=1024*1024;
53 static int procnum; /* records process count number when forking */
54 static struct cli_state *current_cli;
55 static fstring randomfname;
56 static bool use_oplocks;
57 static bool use_level_II_oplocks;
58 static const char *client_txt = "client_oplocks.txt";
59 static bool use_kerberos;
60 static bool force_dos_errors;
61 static fstring multishare_conn_fname;
62 static bool use_multishare_conn = False;
63 static bool do_encrypt;
64 static const char *local_path = NULL;
65 static int signing_state = Undefined;
66 char *test_filename;
67
68 bool torture_showall = False;
69
70 static double create_procs(bool (*fn)(int), bool *result);
71
72
73 /* return a pointer to a anonymous shared memory segment of size "size"
74    which will persist across fork() but will disappear when all processes
75    exit 
76
77    The memory is not zeroed 
78
79    This function uses system5 shared memory. It takes advantage of a property
80    that the memory is not destroyed if it is attached when the id is removed
81    */
82 void *shm_setup(int size)
83 {
84         int shmid;
85         void *ret;
86
87 #ifdef __QNXNTO__
88         shmid = shm_open("private", O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
89         if (shmid == -1) {
90                 printf("can't get shared memory\n");
91                 exit(1);
92         }
93         shm_unlink("private");
94         if (ftruncate(shmid, size) == -1) {
95                 printf("can't set shared memory size\n");
96                 exit(1);
97         }
98         ret = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, shmid, 0);
99         if (ret == MAP_FAILED) {
100                 printf("can't map shared memory\n");
101                 exit(1);
102         }
103 #else
104         shmid = shmget(IPC_PRIVATE, size, S_IRUSR | S_IWUSR);
105         if (shmid == -1) {
106                 printf("can't get shared memory\n");
107                 exit(1);
108         }
109         ret = (void *)shmat(shmid, 0, 0);
110         if (!ret || ret == (void *)-1) {
111                 printf("can't attach to shared memory\n");
112                 return NULL;
113         }
114         /* the following releases the ipc, but note that this process
115            and all its children will still have access to the memory, its
116            just that the shmid is no longer valid for other shm calls. This
117            means we don't leave behind lots of shm segments after we exit 
118
119            See Stevens "advanced programming in unix env" for details
120            */
121         shmctl(shmid, IPC_RMID, 0);
122 #endif
123
124         return ret;
125 }
126
127 /********************************************************************
128  Ensure a connection is encrypted.
129 ********************************************************************/
130
131 static bool force_cli_encryption(struct cli_state *c,
132                         const char *sharename)
133 {
134         uint16 major, minor;
135         uint32 caplow, caphigh;
136         NTSTATUS status;
137
138         if (!SERVER_HAS_UNIX_CIFS(c)) {
139                 d_printf("Encryption required and "
140                         "server that doesn't support "
141                         "UNIX extensions - failing connect\n");
142                         return false;
143         }
144
145         status = cli_unix_extensions_version(c, &major, &minor, &caplow,
146                                              &caphigh);
147         if (!NT_STATUS_IS_OK(status)) {
148                 d_printf("Encryption required and "
149                         "can't get UNIX CIFS extensions "
150                         "version from server: %s\n", nt_errstr(status));
151                 return false;
152         }
153
154         if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
155                 d_printf("Encryption required and "
156                         "share %s doesn't support "
157                         "encryption.\n", sharename);
158                 return false;
159         }
160
161         if (c->use_kerberos) {
162                 status = cli_gss_smb_encryption_start(c);
163         } else {
164                 status = cli_raw_ntlm_smb_encryption_start(c,
165                                                 username,
166                                                 password,
167                                                 workgroup);
168         }
169
170         if (!NT_STATUS_IS_OK(status)) {
171                 d_printf("Encryption required and "
172                         "setup failed with error %s.\n",
173                         nt_errstr(status));
174                 return false;
175         }
176
177         return true;
178 }
179
180
181 static struct cli_state *open_nbt_connection(void)
182 {
183         struct cli_state *c;
184         NTSTATUS status;
185         int flags = 0;
186
187         if (use_oplocks) {
188                 flags |= CLI_FULL_CONNECTION_OPLOCKS;
189         }
190
191         if (use_level_II_oplocks) {
192                 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
193         }
194
195         if (use_kerberos) {
196                 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
197         }
198
199         if (force_dos_errors) {
200                 flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
201         }
202
203         status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
204                                 signing_state, flags, &c);
205         if (!NT_STATUS_IS_OK(status)) {
206                 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
207                 return NULL;
208         }
209
210         cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
211
212         return c;
213 }
214
215 /****************************************************************************
216  Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
217 ****************************************************************************/
218
219 static bool cli_bad_session_request(int fd,
220                          struct nmb_name *calling, struct nmb_name *called)
221 {
222         TALLOC_CTX *frame;
223         uint8_t len_buf[4];
224         struct iovec iov[3];
225         ssize_t len;
226         uint8_t *inbuf;
227         int err;
228         bool ret = false;
229         uint8_t message_type;
230         uint8_t error;
231
232         frame = talloc_stackframe();
233
234         iov[0].iov_base = len_buf;
235         iov[0].iov_len  = sizeof(len_buf);
236
237         /* put in the destination name */
238
239         iov[1].iov_base = name_mangle(talloc_tos(), called->name,
240                                       called->name_type);
241         if (iov[1].iov_base == NULL) {
242                 goto fail;
243         }
244         iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
245                                   talloc_get_size(iov[1].iov_base));
246
247         /* and my name */
248
249         iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
250                                       calling->name_type);
251         if (iov[2].iov_base == NULL) {
252                 goto fail;
253         }
254         iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
255                                   talloc_get_size(iov[2].iov_base));
256
257         /* Deliberately corrupt the name len (first byte) */
258         *((uint8_t *)iov[2].iov_base) = 100;
259
260         /* send a session request (RFC 1002) */
261         /* setup the packet length
262          * Remove four bytes from the length count, since the length
263          * field in the NBT Session Service header counts the number
264          * of bytes which follow.  The cli_send_smb() function knows
265          * about this and accounts for those four bytes.
266          * CRH.
267          */
268
269         _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
270         SCVAL(len_buf,0,0x81);
271
272         len = write_data_iov(fd, iov, 3);
273         if (len == -1) {
274                 goto fail;
275         }
276         len = read_smb(fd, talloc_tos(), &inbuf, &err);
277         if (len == -1) {
278                 errno = err;
279                 goto fail;
280         }
281
282         message_type = CVAL(inbuf, 0);
283         if (message_type != 0x83) {
284                 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
285                           message_type);
286                 goto fail;
287         }
288
289         if (smb_len(inbuf) != 1) {
290                 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
291                           (int)smb_len(inbuf));
292                 goto fail;
293         }
294
295         error = CVAL(inbuf, 4);
296         if (error !=  0x82) {
297                 d_fprintf(stderr, "Expected error 0x82, got %d\n",
298                           (int)error);
299                 goto fail;
300         }
301
302         ret = true;
303 fail:
304         TALLOC_FREE(frame);
305         return ret;
306 }
307
308 /* Insert a NULL at the first separator of the given path and return a pointer
309  * to the remainder of the string.
310  */
311 static char *
312 terminate_path_at_separator(char * path)
313 {
314         char * p;
315
316         if (!path) {
317                 return NULL;
318         }
319
320         if ((p = strchr_m(path, '/'))) {
321                 *p = '\0';
322                 return p + 1;
323         }
324
325         if ((p = strchr_m(path, '\\'))) {
326                 *p = '\0';
327                 return p + 1;
328         }
329
330         /* No separator. */
331         return NULL;
332 }
333
334 /*
335   parse a //server/share type UNC name
336 */
337 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
338                       char **hostname, char **sharename)
339 {
340         char *p;
341
342         *hostname = *sharename = NULL;
343
344         if (strncmp(unc_name, "\\\\", 2) &&
345             strncmp(unc_name, "//", 2)) {
346                 return False;
347         }
348
349         *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
350         p = terminate_path_at_separator(*hostname);
351
352         if (p && *p) {
353                 *sharename = talloc_strdup(mem_ctx, p);
354                 terminate_path_at_separator(*sharename);
355         }
356
357         if (*hostname && *sharename) {
358                 return True;
359         }
360
361         TALLOC_FREE(*hostname);
362         TALLOC_FREE(*sharename);
363         return False;
364 }
365
366 static bool torture_open_connection_share(struct cli_state **c,
367                                    const char *hostname, 
368                                    const char *sharename)
369 {
370         int flags = 0;
371         NTSTATUS status;
372
373         if (use_kerberos)
374                 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
375         if (use_oplocks)
376                 flags |= CLI_FULL_CONNECTION_OPLOCKS;
377         if (use_level_II_oplocks)
378                 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
379
380         status = cli_full_connection(c, myname,
381                                      hostname, NULL, port_to_use, 
382                                      sharename, "?????", 
383                                      username, workgroup, 
384                                      password, flags, signing_state);
385         if (!NT_STATUS_IS_OK(status)) {
386                 printf("failed to open share connection: //%s/%s port:%d - %s\n",
387                         hostname, sharename, port_to_use, nt_errstr(status));
388                 return False;
389         }
390
391         cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
392
393         if (do_encrypt) {
394                 return force_cli_encryption(*c,
395                                         sharename);
396         }
397         return True;
398 }
399
400 bool torture_open_connection(struct cli_state **c, int conn_index)
401 {
402         char **unc_list = NULL;
403         int num_unc_names = 0;
404         bool result;
405
406         if (use_multishare_conn==True) {
407                 char *h, *s;
408                 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
409                 if (!unc_list || num_unc_names <= 0) {
410                         printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
411                         exit(1);
412                 }
413
414                 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
415                                       NULL, &h, &s)) {
416                         printf("Failed to parse UNC name %s\n",
417                                unc_list[conn_index % num_unc_names]);
418                         TALLOC_FREE(unc_list);
419                         exit(1);
420                 }
421
422                 result = torture_open_connection_share(c, h, s);
423
424                 /* h, s were copied earlier */
425                 TALLOC_FREE(unc_list);
426                 return result;
427         }
428
429         return torture_open_connection_share(c, host, share);
430 }
431
432 bool torture_init_connection(struct cli_state **pcli)
433 {
434         struct cli_state *cli;
435
436         cli = open_nbt_connection();
437         if (cli == NULL) {
438                 return false;
439         }
440
441         *pcli = cli;
442         return true;
443 }
444
445 bool torture_cli_session_setup2(struct cli_state *cli, uint16 *new_vuid)
446 {
447         uint16_t old_vuid = cli_state_get_uid(cli);
448         fstring old_user_name;
449         size_t passlen = strlen(password);
450         NTSTATUS status;
451         bool ret;
452
453         fstrcpy(old_user_name, cli->user_name);
454         cli_state_set_uid(cli, 0);
455         ret = NT_STATUS_IS_OK(cli_session_setup(cli, username,
456                                                 password, passlen,
457                                                 password, passlen,
458                                                 workgroup));
459         *new_vuid = cli_state_get_uid(cli);
460         cli_state_set_uid(cli, old_vuid);
461         status = cli_set_username(cli, old_user_name);
462         if (!NT_STATUS_IS_OK(status)) {
463                 return false;
464         }
465         return ret;
466 }
467
468
469 bool torture_close_connection(struct cli_state *c)
470 {
471         bool ret = True;
472         NTSTATUS status;
473
474         status = cli_tdis(c);
475         if (!NT_STATUS_IS_OK(status)) {
476                 printf("tdis failed (%s)\n", nt_errstr(status));
477                 ret = False;
478         }
479
480         cli_shutdown(c);
481
482         return ret;
483 }
484
485
486 /* check if the server produced the expected dos or nt error code */
487 static bool check_both_error(int line, NTSTATUS status,
488                              uint8 eclass, uint32 ecode, NTSTATUS nterr)
489 {
490         if (NT_STATUS_IS_DOS(status)) {
491                 uint8 cclass;
492                 uint32 num;
493
494                 /* Check DOS error */
495                 cclass = NT_STATUS_DOS_CLASS(status);
496                 num = NT_STATUS_DOS_CODE(status);
497
498                 if (eclass != cclass || ecode != num) {
499                         printf("unexpected error code class=%d code=%d\n",
500                                (int)cclass, (int)num);
501                         printf(" expected %d/%d %s (line=%d)\n",
502                                (int)eclass, (int)ecode, nt_errstr(nterr), line);
503                         return false;
504                 }
505         } else {
506                 /* Check NT error */
507                 if (!NT_STATUS_EQUAL(nterr, status)) {
508                         printf("unexpected error code %s\n",
509                                 nt_errstr(status));
510                         printf(" expected %s (line=%d)\n",
511                                 nt_errstr(nterr), line);
512                         return false;
513                 }
514         }
515
516         return true;
517 }
518
519
520 /* check if the server produced the expected error code */
521 static bool check_error(int line, NTSTATUS status,
522                         uint8 eclass, uint32 ecode, NTSTATUS nterr)
523 {
524         if (NT_STATUS_IS_DOS(status)) {
525                 uint8 cclass;
526                 uint32 num;
527
528                 /* Check DOS error */
529
530                 cclass = NT_STATUS_DOS_CLASS(status);
531                 num = NT_STATUS_DOS_CODE(status);
532
533                 if (eclass != cclass || ecode != num) {
534                         printf("unexpected error code class=%d code=%d\n", 
535                                (int)cclass, (int)num);
536                         printf(" expected %d/%d %s (line=%d)\n", 
537                                (int)eclass, (int)ecode, nt_errstr(nterr),
538                                line);
539                         return False;
540                 }
541
542         } else {
543                 /* Check NT error */
544
545                 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
546                         printf("unexpected error code %s\n",
547                                nt_errstr(status));
548                         printf(" expected %s (line=%d)\n", nt_errstr(nterr),
549                                line);
550                         return False;
551                 }
552         }
553
554         return True;
555 }
556
557
558 static bool wait_lock(struct cli_state *c, int fnum, uint32 offset, uint32 len)
559 {
560         NTSTATUS status;
561
562         status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
563
564         while (!NT_STATUS_IS_OK(status)) {
565                 if (!check_both_error(__LINE__, status, ERRDOS,
566                                       ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
567                         return false;
568                 }
569
570                 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
571         }
572
573         return true;
574 }
575
576
577 static bool rw_torture(struct cli_state *c)
578 {
579         const char *lockfname = "\\torture.lck";
580         fstring fname;
581         uint16_t fnum;
582         uint16_t fnum2;
583         pid_t pid2, pid = getpid();
584         int i, j;
585         char buf[1024];
586         bool correct = True;
587         size_t nread = 0;
588         NTSTATUS status;
589
590         memset(buf, '\0', sizeof(buf));
591
592         status = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL, 
593                          DENY_NONE, &fnum2);
594         if (!NT_STATUS_IS_OK(status)) {
595                 status = cli_open(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
596         }
597         if (!NT_STATUS_IS_OK(status)) {
598                 printf("open of %s failed (%s)\n",
599                        lockfname, nt_errstr(status));
600                 return False;
601         }
602
603         for (i=0;i<torture_numops;i++) {
604                 unsigned n = (unsigned)sys_random()%10;
605
606                 if (i % 10 == 0) {
607                         printf("%d\r", i); fflush(stdout);
608                 }
609                 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
610
611                 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
612                         return False;
613                 }
614
615                 status = cli_open(c, fname, O_RDWR | O_CREAT | O_TRUNC,
616                                   DENY_ALL, &fnum);
617                 if (!NT_STATUS_IS_OK(status)) {
618                         printf("open failed (%s)\n", nt_errstr(status));
619                         correct = False;
620                         break;
621                 }
622
623                 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
624                                       sizeof(pid), NULL);
625                 if (!NT_STATUS_IS_OK(status)) {
626                         printf("write failed (%s)\n", nt_errstr(status));
627                         correct = False;
628                 }
629
630                 for (j=0;j<50;j++) {
631                         status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
632                                               sizeof(pid)+(j*sizeof(buf)),
633                                               sizeof(buf), NULL);
634                         if (!NT_STATUS_IS_OK(status)) {
635                                 printf("write failed (%s)\n",
636                                        nt_errstr(status));
637                                 correct = False;
638                         }
639                 }
640
641                 pid2 = 0;
642
643                 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
644                                   &nread);
645                 if (!NT_STATUS_IS_OK(status)) {
646                         printf("read failed (%s)\n", nt_errstr(status));
647                         correct = false;
648                 } else if (nread != sizeof(pid)) {
649                         printf("read/write compare failed: "
650                                "recv %ld req %ld\n", (unsigned long)nread,
651                                (unsigned long)sizeof(pid));
652                         correct = false;
653                 }
654
655                 if (pid2 != pid) {
656                         printf("data corruption!\n");
657                         correct = False;
658                 }
659
660                 status = cli_close(c, fnum);
661                 if (!NT_STATUS_IS_OK(status)) {
662                         printf("close failed (%s)\n", nt_errstr(status));
663                         correct = False;
664                 }
665
666                 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
667                 if (!NT_STATUS_IS_OK(status)) {
668                         printf("unlink failed (%s)\n", nt_errstr(status));
669                         correct = False;
670                 }
671
672                 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
673                 if (!NT_STATUS_IS_OK(status)) {
674                         printf("unlock failed (%s)\n", nt_errstr(status));
675                         correct = False;
676                 }
677         }
678
679         cli_close(c, fnum2);
680         cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
681
682         printf("%d\n", i);
683
684         return correct;
685 }
686
687 static bool run_torture(int dummy)
688 {
689         struct cli_state *cli;
690         bool ret;
691
692         cli = current_cli;
693
694         cli_sockopt(cli, sockops);
695
696         ret = rw_torture(cli);
697
698         if (!torture_close_connection(cli)) {
699                 ret = False;
700         }
701
702         return ret;
703 }
704
705 static bool rw_torture3(struct cli_state *c, char *lockfname)
706 {
707         uint16_t fnum = (uint16_t)-1;
708         unsigned int i = 0;
709         char buf[131072];
710         char buf_rd[131072];
711         unsigned count;
712         unsigned countprev = 0;
713         size_t sent = 0;
714         bool correct = True;
715         NTSTATUS status = NT_STATUS_OK;
716
717         srandom(1);
718         for (i = 0; i < sizeof(buf); i += sizeof(uint32))
719         {
720                 SIVAL(buf, i, sys_random());
721         }
722
723         if (procnum == 0)
724         {
725                 status = cli_unlink(
726                         c, lockfname,
727                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
728                 if (!NT_STATUS_IS_OK(status)) {
729                         printf("unlink failed (%s) (normal, this file should "
730                                "not exist)\n", nt_errstr(status));
731                 }
732
733                 status = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
734                                   DENY_NONE, &fnum);
735                 if (!NT_STATUS_IS_OK(status)) {
736                         printf("first open read/write of %s failed (%s)\n",
737                                         lockfname, nt_errstr(status));
738                         return False;
739                 }
740         }
741         else
742         {
743                 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
744                 {
745                         status = cli_open(c, lockfname, O_RDONLY, 
746                                          DENY_NONE, &fnum);
747                         if (!NT_STATUS_IS_OK(status)) {
748                                 break;
749                         }
750                         smb_msleep(10);
751                 }
752                 if (!NT_STATUS_IS_OK(status)) {
753                         printf("second open read-only of %s failed (%s)\n",
754                                         lockfname, nt_errstr(status));
755                         return False;
756                 }
757         }
758
759         i = 0;
760         for (count = 0; count < sizeof(buf); count += sent)
761         {
762                 if (count >= countprev) {
763                         printf("%d %8d\r", i, count);
764                         fflush(stdout);
765                         i++;
766                         countprev += (sizeof(buf) / 20);
767                 }
768
769                 if (procnum == 0)
770                 {
771                         sent = ((unsigned)sys_random()%(20))+ 1;
772                         if (sent > sizeof(buf) - count)
773                         {
774                                 sent = sizeof(buf) - count;
775                         }
776
777                         status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
778                                               count, sent, NULL);
779                         if (!NT_STATUS_IS_OK(status)) {
780                                 printf("write failed (%s)\n",
781                                        nt_errstr(status));
782                                 correct = False;
783                         }
784                 }
785                 else
786                 {
787                         status = cli_read(c, fnum, buf_rd+count, count,
788                                           sizeof(buf)-count, &sent);
789                         if(!NT_STATUS_IS_OK(status)) {
790                                 printf("read failed offset:%d size:%ld (%s)\n",
791                                        count, (unsigned long)sizeof(buf)-count,
792                                        nt_errstr(status));
793                                 correct = False;
794                                 sent = 0;
795                         } else if (sent > 0) {
796                                 if (memcmp(buf_rd+count, buf+count, sent) != 0)
797                                 {
798                                         printf("read/write compare failed\n");
799                                         printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
800                                         correct = False;
801                                         break;
802                                 }
803                         }
804                 }
805
806         }
807
808         status = cli_close(c, fnum);
809         if (!NT_STATUS_IS_OK(status)) {
810                 printf("close failed (%s)\n", nt_errstr(status));
811                 correct = False;
812         }
813
814         return correct;
815 }
816
817 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
818 {
819         const char *lockfname = "\\torture2.lck";
820         uint16_t fnum1;
821         uint16_t fnum2;
822         int i;
823         char buf[131072];
824         char buf_rd[131072];
825         bool correct = True;
826         size_t bytes_read;
827         NTSTATUS status;
828
829         status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
830         if (!NT_STATUS_IS_OK(status)) {
831                 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
832         }
833
834         status = cli_open(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
835                           DENY_NONE, &fnum1);
836         if (!NT_STATUS_IS_OK(status)) {
837                 printf("first open read/write of %s failed (%s)\n",
838                                 lockfname, nt_errstr(status));
839                 return False;
840         }
841
842         status = cli_open(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
843         if (!NT_STATUS_IS_OK(status)) {
844                 printf("second open read-only of %s failed (%s)\n",
845                                 lockfname, nt_errstr(status));
846                 cli_close(c1, fnum1);
847                 return False;
848         }
849
850         for (i = 0; i < torture_numops; i++)
851         {
852                 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
853                 if (i % 10 == 0) {
854                         printf("%d\r", i); fflush(stdout);
855                 }
856
857                 generate_random_buffer((unsigned char *)buf, buf_size);
858
859                 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
860                                       buf_size, NULL);
861                 if (!NT_STATUS_IS_OK(status)) {
862                         printf("write failed (%s)\n", nt_errstr(status));
863                         correct = False;
864                         break;
865                 }
866
867                 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
868                 if(!NT_STATUS_IS_OK(status)) {
869                         printf("read failed (%s)\n", nt_errstr(status));
870                         correct = false;
871                         break;
872                 } else if (bytes_read != buf_size) {
873                         printf("read failed\n");
874                         printf("read %ld, expected %ld\n",
875                                (unsigned long)bytes_read,
876                                (unsigned long)buf_size); 
877                         correct = False;
878                         break;
879                 }
880
881                 if (memcmp(buf_rd, buf, buf_size) != 0)
882                 {
883                         printf("read/write compare failed\n");
884                         correct = False;
885                         break;
886                 }
887         }
888
889         status = cli_close(c2, fnum2);
890         if (!NT_STATUS_IS_OK(status)) {
891                 printf("close failed (%s)\n", nt_errstr(status));
892                 correct = False;
893         }
894
895         status = cli_close(c1, fnum1);
896         if (!NT_STATUS_IS_OK(status)) {
897                 printf("close failed (%s)\n", nt_errstr(status));
898                 correct = False;
899         }
900
901         status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
902         if (!NT_STATUS_IS_OK(status)) {
903                 printf("unlink failed (%s)\n", nt_errstr(status));
904                 correct = False;
905         }
906
907         return correct;
908 }
909
910 static bool run_readwritetest(int dummy)
911 {
912         struct cli_state *cli1, *cli2;
913         bool test1, test2 = False;
914
915         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
916                 return False;
917         }
918         cli_sockopt(cli1, sockops);
919         cli_sockopt(cli2, sockops);
920
921         printf("starting readwritetest\n");
922
923         test1 = rw_torture2(cli1, cli2);
924         printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
925
926         if (test1) {
927                 test2 = rw_torture2(cli1, cli1);
928                 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
929         }
930
931         if (!torture_close_connection(cli1)) {
932                 test1 = False;
933         }
934
935         if (!torture_close_connection(cli2)) {
936                 test2 = False;
937         }
938
939         return (test1 && test2);
940 }
941
942 static bool run_readwritemulti(int dummy)
943 {
944         struct cli_state *cli;
945         bool test;
946
947         cli = current_cli;
948
949         cli_sockopt(cli, sockops);
950
951         printf("run_readwritemulti: fname %s\n", randomfname);
952         test = rw_torture3(cli, randomfname);
953
954         if (!torture_close_connection(cli)) {
955                 test = False;
956         }
957
958         return test;
959 }
960
961 static bool run_readwritelarge_internal(int max_xmit_k)
962 {
963         static struct cli_state *cli1;
964         uint16_t fnum1;
965         const char *lockfname = "\\large.dat";
966         SMB_OFF_T fsize;
967         char buf[126*1024];
968         bool correct = True;
969         NTSTATUS status;
970
971         if (!torture_open_connection(&cli1, 0)) {
972                 return False;
973         }
974         cli_sockopt(cli1, sockops);
975         memset(buf,'\0',sizeof(buf));
976
977         cli1->max_xmit = max_xmit_k*1024;
978
979         if (signing_state == Required) {
980                 /* Horrible cheat to force
981                    multiple signed outstanding
982                    packets against a Samba server.
983                 */
984                 cli1->is_samba = false;
985         }
986
987         printf("starting readwritelarge_internal\n");
988
989         cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
990
991         status = cli_open(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
992                           DENY_NONE, &fnum1);
993         if (!NT_STATUS_IS_OK(status)) {
994                 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
995                 return False;
996         }
997
998         cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
999
1000         status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1001                                      NULL, NULL, NULL);
1002         if (!NT_STATUS_IS_OK(status)) {
1003                 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1004                 correct = False;
1005         }
1006
1007         if (fsize == sizeof(buf))
1008                 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
1009                        (unsigned long)fsize);
1010         else {
1011                 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
1012                        (unsigned long)fsize);
1013                 correct = False;
1014         }
1015
1016         status = cli_close(cli1, fnum1);
1017         if (!NT_STATUS_IS_OK(status)) {
1018                 printf("close failed (%s)\n", nt_errstr(status));
1019                 correct = False;
1020         }
1021
1022         status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1023         if (!NT_STATUS_IS_OK(status)) {
1024                 printf("unlink failed (%s)\n", nt_errstr(status));
1025                 correct = False;
1026         }
1027
1028         status = cli_open(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1029                           DENY_NONE, &fnum1);
1030         if (!NT_STATUS_IS_OK(status)) {
1031                 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1032                 return False;
1033         }
1034
1035         cli1->max_xmit = 4*1024;
1036
1037         cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1038
1039         status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1040                                      NULL, NULL, NULL);
1041         if (!NT_STATUS_IS_OK(status)) {
1042                 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1043                 correct = False;
1044         }
1045
1046         if (fsize == sizeof(buf))
1047                 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1048                        (unsigned long)fsize);
1049         else {
1050                 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1051                        (unsigned long)fsize);
1052                 correct = False;
1053         }
1054
1055 #if 0
1056         /* ToDo - set allocation. JRA */
1057         if(!cli_set_allocation_size(cli1, fnum1, 0)) {
1058                 printf("set allocation size to zero failed (%s)\n", cli_errstr(&cli1));
1059                 return False;
1060         }
1061         if (!cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL, NULL,
1062                                  NULL, NULL)) {
1063                 printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
1064                 correct = False;
1065         }
1066         if (fsize != 0)
1067                 printf("readwritelarge test 3 (truncate test) succeeded (size = %x)\n", fsize);
1068 #endif
1069
1070         status = cli_close(cli1, fnum1);
1071         if (!NT_STATUS_IS_OK(status)) {
1072                 printf("close failed (%s)\n", nt_errstr(status));
1073                 correct = False;
1074         }
1075
1076         if (!torture_close_connection(cli1)) {
1077                 correct = False;
1078         }
1079         return correct;
1080 }
1081
1082 static bool run_readwritelarge(int dummy)
1083 {
1084         return run_readwritelarge_internal(128);
1085 }
1086
1087 static bool run_readwritelarge_signtest(int dummy)
1088 {
1089         bool ret;
1090         signing_state = Required;
1091         ret = run_readwritelarge_internal(2);
1092         signing_state = Undefined;
1093         return ret;
1094 }
1095
1096 int line_count = 0;
1097 int nbio_id;
1098
1099 #define ival(s) strtol(s, NULL, 0)
1100
1101 /* run a test that simulates an approximate netbench client load */
1102 static bool run_netbench(int client)
1103 {
1104         struct cli_state *cli;
1105         int i;
1106         char line[1024];
1107         char cname[20];
1108         FILE *f;
1109         const char *params[20];
1110         bool correct = True;
1111
1112         cli = current_cli;
1113
1114         nbio_id = client;
1115
1116         cli_sockopt(cli, sockops);
1117
1118         nb_setup(cli);
1119
1120         slprintf(cname,sizeof(cname)-1, "client%d", client);
1121
1122         f = fopen(client_txt, "r");
1123
1124         if (!f) {
1125                 perror(client_txt);
1126                 return False;
1127         }
1128
1129         while (fgets(line, sizeof(line)-1, f)) {
1130                 char *saveptr;
1131                 line_count++;
1132
1133                 line[strlen(line)-1] = 0;
1134
1135                 /* printf("[%d] %s\n", line_count, line); */
1136
1137                 all_string_sub(line,"client1", cname, sizeof(line));
1138
1139                 /* parse the command parameters */
1140                 params[0] = strtok_r(line, " ", &saveptr);
1141                 i = 0;
1142                 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1143
1144                 params[i] = "";
1145
1146                 if (i < 2) continue;
1147
1148                 if (!strncmp(params[0],"SMB", 3)) {
1149                         printf("ERROR: You are using a dbench 1 load file\n");
1150                         exit(1);
1151                 }
1152
1153                 if (!strcmp(params[0],"NTCreateX")) {
1154                         nb_createx(params[1], ival(params[2]), ival(params[3]), 
1155                                    ival(params[4]));
1156                 } else if (!strcmp(params[0],"Close")) {
1157                         nb_close(ival(params[1]));
1158                 } else if (!strcmp(params[0],"Rename")) {
1159                         nb_rename(params[1], params[2]);
1160                 } else if (!strcmp(params[0],"Unlink")) {
1161                         nb_unlink(params[1]);
1162                 } else if (!strcmp(params[0],"Deltree")) {
1163                         nb_deltree(params[1]);
1164                 } else if (!strcmp(params[0],"Rmdir")) {
1165                         nb_rmdir(params[1]);
1166                 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1167                         nb_qpathinfo(params[1]);
1168                 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1169                         nb_qfileinfo(ival(params[1]));
1170                 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1171                         nb_qfsinfo(ival(params[1]));
1172                 } else if (!strcmp(params[0],"FIND_FIRST")) {
1173                         nb_findfirst(params[1]);
1174                 } else if (!strcmp(params[0],"WriteX")) {
1175                         nb_writex(ival(params[1]), 
1176                                   ival(params[2]), ival(params[3]), ival(params[4]));
1177                 } else if (!strcmp(params[0],"ReadX")) {
1178                         nb_readx(ival(params[1]), 
1179                                   ival(params[2]), ival(params[3]), ival(params[4]));
1180                 } else if (!strcmp(params[0],"Flush")) {
1181                         nb_flush(ival(params[1]));
1182                 } else {
1183                         printf("Unknown operation %s\n", params[0]);
1184                         exit(1);
1185                 }
1186         }
1187         fclose(f);
1188
1189         nb_cleanup();
1190
1191         if (!torture_close_connection(cli)) {
1192                 correct = False;
1193         }
1194
1195         return correct;
1196 }
1197
1198
1199 /* run a test that simulates an approximate netbench client load */
1200 static bool run_nbench(int dummy)
1201 {
1202         double t;
1203         bool correct = True;
1204
1205         nbio_shmem(nprocs);
1206
1207         nbio_id = -1;
1208
1209         signal(SIGALRM, nb_alarm);
1210         alarm(1);
1211         t = create_procs(run_netbench, &correct);
1212         alarm(0);
1213
1214         printf("\nThroughput %g MB/sec\n", 
1215                1.0e-6 * nbio_total() / t);
1216         return correct;
1217 }
1218
1219
1220 /*
1221   This test checks for two things:
1222
1223   1) correct support for retaining locks over a close (ie. the server
1224      must not use posix semantics)
1225   2) support for lock timeouts
1226  */
1227 static bool run_locktest1(int dummy)
1228 {
1229         struct cli_state *cli1, *cli2;
1230         const char *fname = "\\lockt1.lck";
1231         uint16_t fnum1, fnum2, fnum3;
1232         time_t t1, t2;
1233         unsigned lock_timeout;
1234         NTSTATUS status;
1235
1236         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1237                 return False;
1238         }
1239         cli_sockopt(cli1, sockops);
1240         cli_sockopt(cli2, sockops);
1241
1242         printf("starting locktest1\n");
1243
1244         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1245
1246         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1247                           &fnum1);
1248         if (!NT_STATUS_IS_OK(status)) {
1249                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1250                 return False;
1251         }
1252
1253         status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1254         if (!NT_STATUS_IS_OK(status)) {
1255                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1256                 return False;
1257         }
1258
1259         status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1260         if (!NT_STATUS_IS_OK(status)) {
1261                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1262                 return False;
1263         }
1264
1265         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1266         if (!NT_STATUS_IS_OK(status)) {
1267                 printf("lock1 failed (%s)\n", nt_errstr(status));
1268                 return false;
1269         }
1270
1271         status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1272         if (NT_STATUS_IS_OK(status)) {
1273                 printf("lock2 succeeded! This is a locking bug\n");
1274                 return false;
1275         } else {
1276                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1277                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1278                         return false;
1279                 }
1280         }
1281
1282         lock_timeout = (1 + (random() % 20));
1283         printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1284         t1 = time(NULL);
1285         status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1286         if (NT_STATUS_IS_OK(status)) {
1287                 printf("lock3 succeeded! This is a locking bug\n");
1288                 return false;
1289         } else {
1290                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1291                                       NT_STATUS_FILE_LOCK_CONFLICT)) {
1292                         return false;
1293                 }
1294         }
1295         t2 = time(NULL);
1296
1297         if (ABS(t2 - t1) < lock_timeout-1) {
1298                 printf("error: This server appears not to support timed lock requests\n");
1299         }
1300
1301         printf("server slept for %u seconds for a %u second timeout\n",
1302                (unsigned int)(t2-t1), lock_timeout);
1303
1304         status = cli_close(cli1, fnum2);
1305         if (!NT_STATUS_IS_OK(status)) {
1306                 printf("close1 failed (%s)\n", nt_errstr(status));
1307                 return False;
1308         }
1309
1310         status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1311         if (NT_STATUS_IS_OK(status)) {
1312                 printf("lock4 succeeded! This is a locking bug\n");
1313                 return false;
1314         } else {
1315                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1316                                       NT_STATUS_FILE_LOCK_CONFLICT)) {
1317                         return false;
1318                 }
1319         }
1320
1321         status = cli_close(cli1, fnum1);
1322         if (!NT_STATUS_IS_OK(status)) {
1323                 printf("close2 failed (%s)\n", nt_errstr(status));
1324                 return False;
1325         }
1326
1327         status = cli_close(cli2, fnum3);
1328         if (!NT_STATUS_IS_OK(status)) {
1329                 printf("close3 failed (%s)\n", nt_errstr(status));
1330                 return False;
1331         }
1332
1333         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1334         if (!NT_STATUS_IS_OK(status)) {
1335                 printf("unlink failed (%s)\n", nt_errstr(status));
1336                 return False;
1337         }
1338
1339
1340         if (!torture_close_connection(cli1)) {
1341                 return False;
1342         }
1343
1344         if (!torture_close_connection(cli2)) {
1345                 return False;
1346         }
1347
1348         printf("Passed locktest1\n");
1349         return True;
1350 }
1351
1352 /*
1353   this checks to see if a secondary tconx can use open files from an
1354   earlier tconx
1355  */
1356 static bool run_tcon_test(int dummy)
1357 {
1358         static struct cli_state *cli;
1359         const char *fname = "\\tcontest.tmp";
1360         uint16 fnum1;
1361         uint16 cnum1, cnum2, cnum3;
1362         uint16 vuid1, vuid2;
1363         char buf[4];
1364         bool ret = True;
1365         NTSTATUS status;
1366
1367         memset(buf, '\0', sizeof(buf));
1368
1369         if (!torture_open_connection(&cli, 0)) {
1370                 return False;
1371         }
1372         cli_sockopt(cli, sockops);
1373
1374         printf("starting tcontest\n");
1375
1376         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1377
1378         status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1379         if (!NT_STATUS_IS_OK(status)) {
1380                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1381                 return False;
1382         }
1383
1384         cnum1 = cli_state_get_tid(cli);
1385         vuid1 = cli_state_get_uid(cli);
1386
1387         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1388         if (!NT_STATUS_IS_OK(status)) {
1389                 printf("initial write failed (%s)", nt_errstr(status));
1390                 return False;
1391         }
1392
1393         status = cli_tcon_andx(cli, share, "?????",
1394                                password, strlen(password)+1);
1395         if (!NT_STATUS_IS_OK(status)) {
1396                 printf("%s refused 2nd tree connect (%s)\n", host,
1397                        nt_errstr(status));
1398                 cli_shutdown(cli);
1399                 return False;
1400         }
1401
1402         cnum2 = cli_state_get_tid(cli);
1403         cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1404         vuid2 = cli_state_get_uid(cli) + 1;
1405
1406         /* try a write with the wrong tid */
1407         cli_state_set_tid(cli, cnum2);
1408
1409         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1410         if (NT_STATUS_IS_OK(status)) {
1411                 printf("* server allows write with wrong TID\n");
1412                 ret = False;
1413         } else {
1414                 printf("server fails write with wrong TID : %s\n",
1415                        nt_errstr(status));
1416         }
1417
1418
1419         /* try a write with an invalid tid */
1420         cli_state_set_tid(cli, cnum3);
1421
1422         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1423         if (NT_STATUS_IS_OK(status)) {
1424                 printf("* server allows write with invalid TID\n");
1425                 ret = False;
1426         } else {
1427                 printf("server fails write with invalid TID : %s\n",
1428                        nt_errstr(status));
1429         }
1430
1431         /* try a write with an invalid vuid */
1432         cli_state_set_uid(cli, vuid2);
1433         cli_state_set_tid(cli, cnum1);
1434
1435         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1436         if (NT_STATUS_IS_OK(status)) {
1437                 printf("* server allows write with invalid VUID\n");
1438                 ret = False;
1439         } else {
1440                 printf("server fails write with invalid VUID : %s\n",
1441                        nt_errstr(status));
1442         }
1443
1444         cli_state_set_tid(cli, cnum1);
1445         cli_state_set_uid(cli, vuid1);
1446
1447         status = cli_close(cli, fnum1);
1448         if (!NT_STATUS_IS_OK(status)) {
1449                 printf("close failed (%s)\n", nt_errstr(status));
1450                 return False;
1451         }
1452
1453         cli_state_set_tid(cli, cnum2);
1454
1455         status = cli_tdis(cli);
1456         if (!NT_STATUS_IS_OK(status)) {
1457                 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1458                 return False;
1459         }
1460
1461         cli_state_set_tid(cli, cnum1);
1462
1463         if (!torture_close_connection(cli)) {
1464                 return False;
1465         }
1466
1467         return ret;
1468 }
1469
1470
1471 /*
1472  checks for old style tcon support
1473  */
1474 static bool run_tcon2_test(int dummy)
1475 {
1476         static struct cli_state *cli;
1477         uint16 cnum, max_xmit;
1478         char *service;
1479         NTSTATUS status;
1480
1481         if (!torture_open_connection(&cli, 0)) {
1482                 return False;
1483         }
1484         cli_sockopt(cli, sockops);
1485
1486         printf("starting tcon2 test\n");
1487
1488         if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1489                 return false;
1490         }
1491
1492         status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1493
1494         SAFE_FREE(service);
1495
1496         if (!NT_STATUS_IS_OK(status)) {
1497                 printf("tcon2 failed : %s\n", nt_errstr(status));
1498         } else {
1499                 printf("tcon OK : max_xmit=%d cnum=%d\n",
1500                        (int)max_xmit, (int)cnum);
1501         }
1502
1503         if (!torture_close_connection(cli)) {
1504                 return False;
1505         }
1506
1507         printf("Passed tcon2 test\n");
1508         return True;
1509 }
1510
1511 static bool tcon_devtest(struct cli_state *cli,
1512                          const char *myshare, const char *devtype,
1513                          const char *return_devtype,
1514                          NTSTATUS expected_error)
1515 {
1516         NTSTATUS status;
1517         bool ret;
1518
1519         status = cli_tcon_andx(cli, myshare, devtype,
1520                                password, strlen(password)+1);
1521
1522         if (NT_STATUS_IS_OK(expected_error)) {
1523                 if (NT_STATUS_IS_OK(status)) {
1524                         if (strcmp(cli->dev, return_devtype) == 0) {
1525                                 ret = True;
1526                         } else { 
1527                                 printf("tconX to share %s with type %s "
1528                                        "succeeded but returned the wrong "
1529                                        "device type (got [%s] but should have got [%s])\n",
1530                                        myshare, devtype, cli->dev, return_devtype);
1531                                 ret = False;
1532                         }
1533                 } else {
1534                         printf("tconX to share %s with type %s "
1535                                "should have succeeded but failed\n",
1536                                myshare, devtype);
1537                         ret = False;
1538                 }
1539                 cli_tdis(cli);
1540         } else {
1541                 if (NT_STATUS_IS_OK(status)) {
1542                         printf("tconx to share %s with type %s "
1543                                "should have failed but succeeded\n",
1544                                myshare, devtype);
1545                         ret = False;
1546                 } else {
1547                         if (NT_STATUS_EQUAL(cli_nt_error(cli),
1548                                             expected_error)) {
1549                                 ret = True;
1550                         } else {
1551                                 printf("Returned unexpected error\n");
1552                                 ret = False;
1553                         }
1554                 }
1555         }
1556         return ret;
1557 }
1558
1559 /*
1560  checks for correct tconX support
1561  */
1562 static bool run_tcon_devtype_test(int dummy)
1563 {
1564         static struct cli_state *cli1 = NULL;
1565         int flags = 0;
1566         NTSTATUS status;
1567         bool ret = True;
1568
1569         status = cli_full_connection(&cli1, myname,
1570                                      host, NULL, port_to_use,
1571                                      NULL, NULL,
1572                                      username, workgroup,
1573                                      password, flags, signing_state);
1574
1575         if (!NT_STATUS_IS_OK(status)) {
1576                 printf("could not open connection\n");
1577                 return False;
1578         }
1579
1580         if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1581                 ret = False;
1582
1583         if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1584                 ret = False;
1585
1586         if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1587                 ret = False;
1588
1589         if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1590                 ret = False;
1591
1592         if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1593                 ret = False;
1594
1595         if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1596                 ret = False;
1597
1598         if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1599                 ret = False;
1600
1601         if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1602                 ret = False;
1603
1604         if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1605                 ret = False;
1606
1607         if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1608                 ret = False;
1609
1610         cli_shutdown(cli1);
1611
1612         if (ret)
1613                 printf("Passed tcondevtest\n");
1614
1615         return ret;
1616 }
1617
1618
1619 /*
1620   This test checks that 
1621
1622   1) the server supports multiple locking contexts on the one SMB
1623   connection, distinguished by PID.  
1624
1625   2) the server correctly fails overlapping locks made by the same PID (this
1626      goes against POSIX behaviour, which is why it is tricky to implement)
1627
1628   3) the server denies unlock requests by an incorrect client PID
1629 */
1630 static bool run_locktest2(int dummy)
1631 {
1632         static struct cli_state *cli;
1633         const char *fname = "\\lockt2.lck";
1634         uint16_t fnum1, fnum2, fnum3;
1635         bool correct = True;
1636         NTSTATUS status;
1637
1638         if (!torture_open_connection(&cli, 0)) {
1639                 return False;
1640         }
1641
1642         cli_sockopt(cli, sockops);
1643
1644         printf("starting locktest2\n");
1645
1646         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1647
1648         cli_setpid(cli, 1);
1649
1650         status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1651         if (!NT_STATUS_IS_OK(status)) {
1652                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1653                 return False;
1654         }
1655
1656         status = cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1657         if (!NT_STATUS_IS_OK(status)) {
1658                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1659                 return False;
1660         }
1661
1662         cli_setpid(cli, 2);
1663
1664         status = cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1665         if (!NT_STATUS_IS_OK(status)) {
1666                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1667                 return False;
1668         }
1669
1670         cli_setpid(cli, 1);
1671
1672         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1673         if (!NT_STATUS_IS_OK(status)) {
1674                 printf("lock1 failed (%s)\n", nt_errstr(status));
1675                 return false;
1676         }
1677
1678         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1679         if (NT_STATUS_IS_OK(status)) {
1680                 printf("WRITE lock1 succeeded! This is a locking bug\n");
1681                 correct = false;
1682         } else {
1683                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1684                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1685                         return false;
1686                 }
1687         }
1688
1689         status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1690         if (NT_STATUS_IS_OK(status)) {
1691                 printf("WRITE lock2 succeeded! This is a locking bug\n");
1692                 correct = false;
1693         } else {
1694                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1695                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1696                         return false;
1697                 }
1698         }
1699
1700         status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1701         if (NT_STATUS_IS_OK(status)) {
1702                 printf("READ lock2 succeeded! This is a locking bug\n");
1703                 correct = false;
1704         } else {
1705                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1706                                  NT_STATUS_FILE_LOCK_CONFLICT)) {
1707                         return false;
1708                 }
1709         }
1710
1711         status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1712         if (!NT_STATUS_IS_OK(status)) {
1713                 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1714         }
1715         cli_setpid(cli, 2);
1716         if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1717                 printf("unlock at 100 succeeded! This is a locking bug\n");
1718                 correct = False;
1719         }
1720
1721         status = cli_unlock(cli, fnum1, 0, 4);
1722         if (NT_STATUS_IS_OK(status)) {
1723                 printf("unlock1 succeeded! This is a locking bug\n");
1724                 correct = false;
1725         } else {
1726                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1727                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1728                         return false;
1729                 }
1730         }
1731
1732         status = cli_unlock(cli, fnum1, 0, 8);
1733         if (NT_STATUS_IS_OK(status)) {
1734                 printf("unlock2 succeeded! This is a locking bug\n");
1735                 correct = false;
1736         } else {
1737                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1738                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1739                         return false;
1740                 }
1741         }
1742
1743         status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1744         if (NT_STATUS_IS_OK(status)) {
1745                 printf("lock3 succeeded! This is a locking bug\n");
1746                 correct = false;
1747         } else {
1748                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1749                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1750                         return false;
1751                 }
1752         }
1753
1754         cli_setpid(cli, 1);
1755
1756         status = cli_close(cli, fnum1);
1757         if (!NT_STATUS_IS_OK(status)) {
1758                 printf("close1 failed (%s)\n", nt_errstr(status));
1759                 return False;
1760         }
1761
1762         status = cli_close(cli, fnum2);
1763         if (!NT_STATUS_IS_OK(status)) {
1764                 printf("close2 failed (%s)\n", nt_errstr(status));
1765                 return False;
1766         }
1767
1768         status = cli_close(cli, fnum3);
1769         if (!NT_STATUS_IS_OK(status)) {
1770                 printf("close3 failed (%s)\n", nt_errstr(status));
1771                 return False;
1772         }
1773
1774         if (!torture_close_connection(cli)) {
1775                 correct = False;
1776         }
1777
1778         printf("locktest2 finished\n");
1779
1780         return correct;
1781 }
1782
1783
1784 /*
1785   This test checks that 
1786
1787   1) the server supports the full offset range in lock requests
1788 */
1789 static bool run_locktest3(int dummy)
1790 {
1791         static struct cli_state *cli1, *cli2;
1792         const char *fname = "\\lockt3.lck";
1793         uint16_t fnum1, fnum2;
1794         int i;
1795         uint32 offset;
1796         bool correct = True;
1797         NTSTATUS status;
1798
1799 #define NEXT_OFFSET offset += (~(uint32)0) / torture_numops
1800
1801         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1802                 return False;
1803         }
1804         cli_sockopt(cli1, sockops);
1805         cli_sockopt(cli2, sockops);
1806
1807         printf("starting locktest3\n");
1808
1809         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1810
1811         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1812                          &fnum1);
1813         if (!NT_STATUS_IS_OK(status)) {
1814                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1815                 return False;
1816         }
1817
1818         status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1819         if (!NT_STATUS_IS_OK(status)) {
1820                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1821                 return False;
1822         }
1823
1824         for (offset=i=0;i<torture_numops;i++) {
1825                 NEXT_OFFSET;
1826
1827                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1828                 if (!NT_STATUS_IS_OK(status)) {
1829                         printf("lock1 %d failed (%s)\n", 
1830                                i,
1831                                nt_errstr(status));
1832                         return False;
1833                 }
1834
1835                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1836                 if (!NT_STATUS_IS_OK(status)) {
1837                         printf("lock2 %d failed (%s)\n", 
1838                                i,
1839                                nt_errstr(status));
1840                         return False;
1841                 }
1842         }
1843
1844         for (offset=i=0;i<torture_numops;i++) {
1845                 NEXT_OFFSET;
1846
1847                 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1848                 if (NT_STATUS_IS_OK(status)) {
1849                         printf("error: lock1 %d succeeded!\n", i);
1850                         return False;
1851                 }
1852
1853                 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1854                 if (NT_STATUS_IS_OK(status)) {
1855                         printf("error: lock2 %d succeeded!\n", i);
1856                         return False;
1857                 }
1858
1859                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1860                 if (NT_STATUS_IS_OK(status)) {
1861                         printf("error: lock3 %d succeeded!\n", i);
1862                         return False;
1863                 }
1864
1865                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1866                 if (NT_STATUS_IS_OK(status)) {
1867                         printf("error: lock4 %d succeeded!\n", i);
1868                         return False;
1869                 }
1870         }
1871
1872         for (offset=i=0;i<torture_numops;i++) {
1873                 NEXT_OFFSET;
1874
1875                 status = cli_unlock(cli1, fnum1, offset-1, 1);
1876                 if (!NT_STATUS_IS_OK(status)) {
1877                         printf("unlock1 %d failed (%s)\n", 
1878                                i,
1879                                nt_errstr(status));
1880                         return False;
1881                 }
1882
1883                 status = cli_unlock(cli2, fnum2, offset-2, 1);
1884                 if (!NT_STATUS_IS_OK(status)) {
1885                         printf("unlock2 %d failed (%s)\n", 
1886                                i,
1887                                nt_errstr(status));
1888                         return False;
1889                 }
1890         }
1891
1892         status = cli_close(cli1, fnum1);
1893         if (!NT_STATUS_IS_OK(status)) {
1894                 printf("close1 failed (%s)\n", nt_errstr(status));
1895                 return False;
1896         }
1897
1898         status = cli_close(cli2, fnum2);
1899         if (!NT_STATUS_IS_OK(status)) {
1900                 printf("close2 failed (%s)\n", nt_errstr(status));
1901                 return False;
1902         }
1903
1904         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1905         if (!NT_STATUS_IS_OK(status)) {
1906                 printf("unlink failed (%s)\n", nt_errstr(status));
1907                 return False;
1908         }
1909
1910         if (!torture_close_connection(cli1)) {
1911                 correct = False;
1912         }
1913
1914         if (!torture_close_connection(cli2)) {
1915                 correct = False;
1916         }
1917
1918         printf("finished locktest3\n");
1919
1920         return correct;
1921 }
1922
1923 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
1924                            char *buf, off_t offset, size_t size,
1925                            size_t *nread, size_t expect)
1926 {
1927         NTSTATUS status;
1928         size_t l_nread;
1929
1930         status = cli_read(cli, fnum, buf, offset, size, &l_nread);
1931
1932         if(!NT_STATUS_IS_OK(status)) {
1933                 return false;
1934         } else if (l_nread != expect) {
1935                 return false;
1936         }
1937
1938         if (nread) {
1939                 *nread = l_nread;
1940         }
1941
1942         return true;
1943 }
1944
1945 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1946         printf("** "); correct = False; \
1947         }
1948
1949 /*
1950   looks at overlapping locks
1951 */
1952 static bool run_locktest4(int dummy)
1953 {
1954         static struct cli_state *cli1, *cli2;
1955         const char *fname = "\\lockt4.lck";
1956         uint16_t fnum1, fnum2, f;
1957         bool ret;
1958         char buf[1000];
1959         bool correct = True;
1960         NTSTATUS status;
1961
1962         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1963                 return False;
1964         }
1965
1966         cli_sockopt(cli1, sockops);
1967         cli_sockopt(cli2, sockops);
1968
1969         printf("starting locktest4\n");
1970
1971         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1972
1973         cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1974         cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1975
1976         memset(buf, 0, sizeof(buf));
1977
1978         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
1979                               NULL);
1980         if (!NT_STATUS_IS_OK(status)) {
1981                 printf("Failed to create file: %s\n", nt_errstr(status));
1982                 correct = False;
1983                 goto fail;
1984         }
1985
1986         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1987               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
1988         EXPECTED(ret, False);
1989         printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1990
1991         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
1992               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
1993         EXPECTED(ret, True);
1994         printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1995
1996         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
1997               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
1998         EXPECTED(ret, False);
1999         printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
2000
2001         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
2002               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
2003         EXPECTED(ret, True);
2004         printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
2005
2006         ret = (cli_setpid(cli1, 1),
2007               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
2008               (cli_setpid(cli1, 2),
2009               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
2010         EXPECTED(ret, False);
2011         printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
2012
2013         ret = (cli_setpid(cli1, 1),
2014               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
2015               (cli_setpid(cli1, 2),
2016               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
2017         EXPECTED(ret, True);
2018         printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
2019
2020         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
2021               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
2022         EXPECTED(ret, True);
2023         printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
2024
2025         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
2026               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
2027         EXPECTED(ret, False);
2028         printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
2029
2030         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
2031               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
2032         EXPECTED(ret, False);
2033         printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
2034
2035         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
2036               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2037         EXPECTED(ret, True);
2038         printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2039
2040         ret = (cli_setpid(cli1, 1),
2041              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2042              (cli_setpid(cli1, 2),
2043              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2044         EXPECTED(ret, False);
2045         printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2046
2047         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2048               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2049               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2050         EXPECTED(ret, False);
2051         printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2052
2053
2054         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2055               test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2056         EXPECTED(ret, False);
2057         printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2058
2059         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2060         ret = NT_STATUS_IS_OK(status);
2061         if (ret) {
2062                 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2063                                       NULL);
2064                 ret = NT_STATUS_IS_OK(status);
2065         }
2066         EXPECTED(ret, False);
2067         printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2068
2069
2070         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2071               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2072               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2073               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2074         EXPECTED(ret, True);
2075         printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2076
2077
2078         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2079               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2080               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2081               test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2082               !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2083                                              150, 4, NULL))) &&
2084               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2085         EXPECTED(ret, True);
2086         printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2087
2088         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2089               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2090               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2091                                            160, 4, NULL)) &&
2092               test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2093         EXPECTED(ret, True);
2094         printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2095
2096         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2097               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2098               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2099                                            170, 4, NULL)) &&
2100               test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2101         EXPECTED(ret, True);
2102         printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2103
2104         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2105               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2106               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2107               !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2108                                             190, 4, NULL)) &&
2109               test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2110         EXPECTED(ret, True);
2111         printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2112
2113         cli_close(cli1, fnum1);
2114         cli_close(cli2, fnum2);
2115         cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2116         cli_open(cli1, fname, O_RDWR, DENY_NONE, &f);
2117         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2118               NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2119               NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2120               NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2121               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2122         cli_close(cli1, f);
2123         cli_close(cli1, fnum1);
2124         EXPECTED(ret, True);
2125         printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2126
2127  fail:
2128         cli_close(cli1, fnum1);
2129         cli_close(cli2, fnum2);
2130         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2131         torture_close_connection(cli1);
2132         torture_close_connection(cli2);
2133
2134         printf("finished locktest4\n");
2135         return correct;
2136 }
2137
2138 /*
2139   looks at lock upgrade/downgrade.
2140 */
2141 static bool run_locktest5(int dummy)
2142 {
2143         static struct cli_state *cli1, *cli2;
2144         const char *fname = "\\lockt5.lck";
2145         uint16_t fnum1, fnum2, fnum3;
2146         bool ret;
2147         char buf[1000];
2148         bool correct = True;
2149         NTSTATUS status;
2150
2151         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2152                 return False;
2153         }
2154
2155         cli_sockopt(cli1, sockops);
2156         cli_sockopt(cli2, sockops);
2157
2158         printf("starting locktest5\n");
2159
2160         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2161
2162         cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2163         cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2164         cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2165
2166         memset(buf, 0, sizeof(buf));
2167
2168         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2169                               NULL);
2170         if (!NT_STATUS_IS_OK(status)) {
2171                 printf("Failed to create file: %s\n", nt_errstr(status));
2172                 correct = False;
2173                 goto fail;
2174         }
2175
2176         /* Check for NT bug... */
2177         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2178               NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2179         cli_close(cli1, fnum1);
2180         cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2181         status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2182         ret = NT_STATUS_IS_OK(status);
2183         EXPECTED(ret, True);
2184         printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2185         cli_close(cli1, fnum1);
2186         cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2187         cli_unlock(cli1, fnum3, 0, 1);
2188
2189         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2190               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2191         EXPECTED(ret, True);
2192         printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2193
2194         status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2195         ret = NT_STATUS_IS_OK(status);
2196         EXPECTED(ret, False);
2197
2198         printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2199
2200         /* Unlock the process 2 lock. */
2201         cli_unlock(cli2, fnum2, 0, 4);
2202
2203         status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2204         ret = NT_STATUS_IS_OK(status);
2205         EXPECTED(ret, False);
2206
2207         printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
2208
2209         /* Unlock the process 1 fnum3 lock. */
2210         cli_unlock(cli1, fnum3, 0, 4);
2211
2212         /* Stack 2 more locks here. */
2213         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2214               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2215
2216         EXPECTED(ret, True);
2217         printf("the same process %s stack read locks\n", ret?"can":"cannot");
2218
2219         /* Unlock the first process lock, then check this was the WRITE lock that was
2220                 removed. */
2221
2222         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2223               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2224
2225         EXPECTED(ret, True);
2226         printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2227
2228         /* Unlock the process 2 lock. */
2229         cli_unlock(cli2, fnum2, 0, 4);
2230
2231         /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2232
2233         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2234                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2235                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2236
2237         EXPECTED(ret, True);
2238         printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot"); 
2239
2240         /* Ensure the next unlock fails. */
2241         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2242         EXPECTED(ret, False);
2243         printf("the same process %s count the lock stack\n", !ret?"can":"cannot"); 
2244
2245         /* Ensure connection 2 can get a write lock. */
2246         status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2247         ret = NT_STATUS_IS_OK(status);
2248         EXPECTED(ret, True);
2249
2250         printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2251
2252
2253  fail:
2254         cli_close(cli1, fnum1);
2255         cli_close(cli2, fnum2);
2256         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2257         if (!torture_close_connection(cli1)) {
2258                 correct = False;
2259         }
2260         if (!torture_close_connection(cli2)) {
2261                 correct = False;
2262         }
2263
2264         printf("finished locktest5\n");
2265
2266         return correct;
2267 }
2268
2269 /*
2270   tries the unusual lockingX locktype bits
2271 */
2272 static bool run_locktest6(int dummy)
2273 {
2274         static struct cli_state *cli;
2275         const char *fname[1] = { "\\lock6.txt" };
2276         int i;
2277         uint16_t fnum;
2278         NTSTATUS status;
2279
2280         if (!torture_open_connection(&cli, 0)) {
2281                 return False;
2282         }
2283
2284         cli_sockopt(cli, sockops);
2285
2286         printf("starting locktest6\n");
2287
2288         for (i=0;i<1;i++) {
2289                 printf("Testing %s\n", fname[i]);
2290
2291                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2292
2293                 cli_open(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2294                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2295                 cli_close(cli, fnum);
2296                 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2297
2298                 cli_open(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2299                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2300                 cli_close(cli, fnum);
2301                 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2302
2303                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2304         }
2305
2306         torture_close_connection(cli);
2307
2308         printf("finished locktest6\n");
2309         return True;
2310 }
2311
2312 static bool run_locktest7(int dummy)
2313 {
2314         struct cli_state *cli1;
2315         const char *fname = "\\lockt7.lck";
2316         uint16_t fnum1;
2317         char buf[200];
2318         bool correct = False;
2319         size_t nread;
2320         NTSTATUS status;
2321
2322         if (!torture_open_connection(&cli1, 0)) {
2323                 return False;
2324         }
2325
2326         cli_sockopt(cli1, sockops);
2327
2328         printf("starting locktest7\n");
2329
2330         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2331
2332         cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2333
2334         memset(buf, 0, sizeof(buf));
2335
2336         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2337                               NULL);
2338         if (!NT_STATUS_IS_OK(status)) {
2339                 printf("Failed to create file: %s\n", nt_errstr(status));
2340                 goto fail;
2341         }
2342
2343         cli_setpid(cli1, 1);
2344
2345         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2346         if (!NT_STATUS_IS_OK(status)) {
2347                 printf("Unable to apply read lock on range 130:4, "
2348                        "error was %s\n", nt_errstr(status));
2349                 goto fail;
2350         } else {
2351                 printf("pid1 successfully locked range 130:4 for READ\n");
2352         }
2353
2354         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2355         if (!NT_STATUS_IS_OK(status)) {
2356                 printf("pid1 unable to read the range 130:4, error was %s\n",
2357                       nt_errstr(status));
2358                 goto fail;
2359         } else if (nread != 4) {
2360                 printf("pid1 unable to read the range 130:4, "
2361                        "recv %ld req %d\n", (unsigned long)nread, 4);
2362                 goto fail;
2363         } else {
2364                 printf("pid1 successfully read the range 130:4\n");
2365         }
2366
2367         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2368         if (!NT_STATUS_IS_OK(status)) {
2369                 printf("pid1 unable to write to the range 130:4, error was "
2370                        "%s\n", nt_errstr(status));
2371                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2372                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2373                         goto fail;
2374                 }
2375         } else {
2376                 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2377                 goto fail;
2378         }
2379
2380         cli_setpid(cli1, 2);
2381
2382         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2383         if (!NT_STATUS_IS_OK(status)) {
2384                 printf("pid2 unable to read the range 130:4, error was %s\n",
2385                       nt_errstr(status));
2386                 goto fail;
2387         } else if (nread != 4) {
2388                 printf("pid2 unable to read the range 130:4, "
2389                        "recv %ld req %d\n", (unsigned long)nread, 4);
2390                 goto fail;
2391         } else {
2392                 printf("pid2 successfully read the range 130:4\n");
2393         }
2394
2395         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2396         if (!NT_STATUS_IS_OK(status)) {
2397                 printf("pid2 unable to write to the range 130:4, error was "
2398                        "%s\n", nt_errstr(status));
2399                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2400                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2401                         goto fail;
2402                 }
2403         } else {
2404                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2405                 goto fail;
2406         }
2407
2408         cli_setpid(cli1, 1);
2409         cli_unlock(cli1, fnum1, 130, 4);
2410
2411         status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2412         if (!NT_STATUS_IS_OK(status)) {
2413                 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2414                 goto fail;
2415         } else {
2416                 printf("pid1 successfully locked range 130:4 for WRITE\n");
2417         }
2418
2419         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2420         if (!NT_STATUS_IS_OK(status)) {
2421                 printf("pid1 unable to read the range 130:4, error was %s\n",
2422                       nt_errstr(status));
2423                 goto fail;
2424         } else if (nread != 4) {
2425                 printf("pid1 unable to read the range 130:4, "
2426                        "recv %ld req %d\n", (unsigned long)nread, 4);
2427                 goto fail;
2428         } else {
2429                 printf("pid1 successfully read the range 130:4\n");
2430         }
2431
2432         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2433         if (!NT_STATUS_IS_OK(status)) {
2434                 printf("pid1 unable to write to the range 130:4, error was "
2435                        "%s\n", nt_errstr(status));
2436                 goto fail;
2437         } else {
2438                 printf("pid1 successfully wrote to the range 130:4\n");
2439         }
2440
2441         cli_setpid(cli1, 2);
2442
2443         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2444         if (!NT_STATUS_IS_OK(status)) {
2445                 printf("pid2 unable to read the range 130:4, error was "
2446                        "%s\n", nt_errstr(status));
2447                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2448                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2449                         goto fail;
2450                 }
2451         } else {
2452                 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2453                        (unsigned long)nread);
2454                 goto fail;
2455         }
2456
2457         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2458         if (!NT_STATUS_IS_OK(status)) {
2459                 printf("pid2 unable to write to the range 130:4, error was "
2460                        "%s\n", nt_errstr(status));
2461                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2462                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2463                         goto fail;
2464                 }
2465         } else {
2466                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2467                 goto fail;
2468         }
2469
2470         cli_unlock(cli1, fnum1, 130, 0);
2471         correct = True;
2472
2473 fail:
2474         cli_close(cli1, fnum1);
2475         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2476         torture_close_connection(cli1);
2477
2478         printf("finished locktest7\n");
2479         return correct;
2480 }
2481
2482 /*
2483  * This demonstrates a problem with our use of GPFS share modes: A file
2484  * descriptor sitting in the pending close queue holding a GPFS share mode
2485  * blocks opening a file another time. Happens with Word 2007 temp files.
2486  * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2487  * open is denied with NT_STATUS_SHARING_VIOLATION.
2488  */
2489
2490 static bool run_locktest8(int dummy)
2491 {
2492         struct cli_state *cli1;
2493         const char *fname = "\\lockt8.lck";
2494         uint16_t fnum1, fnum2;
2495         char buf[200];
2496         bool correct = False;
2497         NTSTATUS status;
2498
2499         if (!torture_open_connection(&cli1, 0)) {
2500                 return False;
2501         }
2502
2503         cli_sockopt(cli1, sockops);
2504
2505         printf("starting locktest8\n");
2506
2507         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2508
2509         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2510                           &fnum1);
2511         if (!NT_STATUS_IS_OK(status)) {
2512                 d_fprintf(stderr, "cli_open returned %s\n", nt_errstr(status));
2513                 return false;
2514         }
2515
2516         memset(buf, 0, sizeof(buf));
2517
2518         status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2519         if (!NT_STATUS_IS_OK(status)) {
2520                 d_fprintf(stderr, "cli_open second time returned %s\n",
2521                           nt_errstr(status));
2522                 goto fail;
2523         }
2524
2525         status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2526         if (!NT_STATUS_IS_OK(status)) {
2527                 printf("Unable to apply read lock on range 1:1, error was "
2528                        "%s\n", nt_errstr(status));
2529                 goto fail;
2530         }
2531
2532         status = cli_close(cli1, fnum1);
2533         if (!NT_STATUS_IS_OK(status)) {
2534                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2535                 goto fail;
2536         }
2537
2538         status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2539         if (!NT_STATUS_IS_OK(status)) {
2540                 d_fprintf(stderr, "cli_open third time returned %s\n",
2541                           nt_errstr(status));
2542                 goto fail;
2543         }
2544
2545         correct = true;
2546
2547 fail:
2548         cli_close(cli1, fnum1);
2549         cli_close(cli1, fnum2);
2550         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2551         torture_close_connection(cli1);
2552
2553         printf("finished locktest8\n");
2554         return correct;
2555 }
2556
2557 /*
2558  * This test is designed to be run in conjunction with
2559  * external NFS or POSIX locks taken in the filesystem.
2560  * It checks that the smbd server will block until the
2561  * lock is released and then acquire it. JRA.
2562  */
2563
2564 static bool got_alarm;
2565 static struct cli_state *alarm_cli;
2566
2567 static void alarm_handler(int dummy)
2568 {
2569         got_alarm = True;
2570 }
2571
2572 static void alarm_handler_parent(int dummy)
2573 {
2574         cli_state_disconnect(alarm_cli);
2575 }
2576
2577 static void do_local_lock(int read_fd, int write_fd)
2578 {
2579         int fd;
2580         char c = '\0';
2581         struct flock lock;
2582         const char *local_pathname = NULL;
2583         int ret;
2584
2585         local_pathname = talloc_asprintf(talloc_tos(),
2586                         "%s/lockt9.lck", local_path);
2587         if (!local_pathname) {
2588                 printf("child: alloc fail\n");
2589                 exit(1);
2590         }
2591
2592         unlink(local_pathname);
2593         fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2594         if (fd == -1) {
2595                 printf("child: open of %s failed %s.\n",
2596                         local_pathname, strerror(errno));
2597                 exit(1);
2598         }
2599
2600         /* Now take a fcntl lock. */
2601         lock.l_type = F_WRLCK;
2602         lock.l_whence = SEEK_SET;
2603         lock.l_start = 0;
2604         lock.l_len = 4;
2605         lock.l_pid = getpid();
2606
2607         ret = fcntl(fd,F_SETLK,&lock);
2608         if (ret == -1) {
2609                 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2610                         local_pathname, strerror(errno));
2611                 exit(1);
2612         } else {
2613                 printf("child: got lock 0:4 on file %s.\n",
2614                         local_pathname );
2615                 fflush(stdout);
2616         }
2617
2618         CatchSignal(SIGALRM, alarm_handler);
2619         alarm(5);
2620         /* Signal the parent. */
2621         if (write(write_fd, &c, 1) != 1) {
2622                 printf("child: start signal fail %s.\n",
2623                         strerror(errno));
2624                 exit(1);
2625         }
2626         alarm(0);
2627
2628         alarm(10);
2629         /* Wait for the parent to be ready. */
2630         if (read(read_fd, &c, 1) != 1) {
2631                 printf("child: reply signal fail %s.\n",
2632                         strerror(errno));
2633                 exit(1);
2634         }
2635         alarm(0);
2636
2637         sleep(5);
2638         close(fd);
2639         printf("child: released lock 0:4 on file %s.\n",
2640                 local_pathname );
2641         fflush(stdout);
2642         exit(0);
2643 }
2644
2645 static bool run_locktest9(int dummy)
2646 {
2647         struct cli_state *cli1;
2648         const char *fname = "\\lockt9.lck";
2649         uint16_t fnum;
2650         bool correct = False;
2651         int pipe_in[2], pipe_out[2];
2652         pid_t child_pid;
2653         char c = '\0';
2654         int ret;
2655         struct timeval start;
2656         double seconds;
2657         NTSTATUS status;
2658
2659         printf("starting locktest9\n");
2660
2661         if (local_path == NULL) {
2662                 d_fprintf(stderr, "locktest9 must be given a local path via -l <localpath>\n");
2663                 return false;
2664         }
2665
2666         if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2667                 return false;
2668         }
2669
2670         child_pid = fork();
2671         if (child_pid == -1) {
2672                 return false;
2673         }
2674
2675         if (child_pid == 0) {
2676                 /* Child. */
2677                 do_local_lock(pipe_out[0], pipe_in[1]);
2678                 exit(0);
2679         }
2680
2681         close(pipe_out[0]);
2682         close(pipe_in[1]);
2683         pipe_out[0] = -1;
2684         pipe_in[1] = -1;
2685
2686         /* Parent. */
2687         ret = read(pipe_in[0], &c, 1);
2688         if (ret != 1) {
2689                 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2690                         strerror(errno));
2691                 return false;
2692         }
2693
2694         if (!torture_open_connection(&cli1, 0)) {
2695                 return false;
2696         }
2697
2698         cli_sockopt(cli1, sockops);
2699
2700         status = cli_open(cli1, fname, O_RDWR, DENY_NONE,
2701                           &fnum);
2702         if (!NT_STATUS_IS_OK(status)) {
2703                 d_fprintf(stderr, "cli_open returned %s\n", nt_errstr(status));
2704                 return false;
2705         }
2706
2707         /* Ensure the child has the lock. */
2708         status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2709         if (NT_STATUS_IS_OK(status)) {
2710                 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2711                 goto fail;
2712         } else {
2713                 d_printf("Child has the lock.\n");
2714         }
2715
2716         /* Tell the child to wait 5 seconds then exit. */
2717         ret = write(pipe_out[1], &c, 1);
2718         if (ret != 1) {
2719                 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2720                         strerror(errno));
2721                 goto fail;
2722         }
2723
2724         /* Wait 20 seconds for the lock. */
2725         alarm_cli = cli1;
2726         CatchSignal(SIGALRM, alarm_handler_parent);
2727         alarm(20);
2728
2729         start = timeval_current();
2730
2731         status = cli_lock32(cli1, fnum, 0, 4, -1, WRITE_LOCK);
2732         if (!NT_STATUS_IS_OK(status)) {
2733                 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2734                        "%s\n", nt_errstr(status));
2735                 goto fail_nofd;
2736         }
2737         alarm(0);
2738
2739         seconds = timeval_elapsed(&start);
2740
2741         printf("Parent got the lock after %.2f seconds.\n",
2742                 seconds);
2743
2744         status = cli_close(cli1, fnum);
2745         if (!NT_STATUS_IS_OK(status)) {
2746                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2747                 goto fail;
2748         }
2749
2750         correct = true;
2751
2752 fail:
2753         cli_close(cli1, fnum);
2754         torture_close_connection(cli1);
2755
2756 fail_nofd:
2757
2758         printf("finished locktest9\n");
2759         return correct;
2760 }
2761
2762 /*
2763 test whether fnums and tids open on one VC are available on another (a major
2764 security hole)
2765 */
2766 static bool run_fdpasstest(int dummy)
2767 {
2768         struct cli_state *cli1, *cli2;
2769         const char *fname = "\\fdpass.tst";
2770         uint16_t fnum1;
2771         char buf[1024];
2772         NTSTATUS status;
2773
2774         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2775                 return False;
2776         }
2777         cli_sockopt(cli1, sockops);
2778         cli_sockopt(cli2, sockops);
2779
2780         printf("starting fdpasstest\n");
2781
2782         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2783
2784         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
2785                           &fnum1);
2786         if (!NT_STATUS_IS_OK(status)) {
2787                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2788                 return False;
2789         }
2790
2791         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
2792                               13, NULL);
2793         if (!NT_STATUS_IS_OK(status)) {
2794                 printf("write failed (%s)\n", nt_errstr(status));
2795                 return False;
2796         }
2797
2798         cli_state_set_uid(cli2, cli_state_get_uid(cli1));
2799         cli_state_set_tid(cli2, cli_state_get_tid(cli1));
2800         cli_setpid(cli2, cli_getpid(cli1));
2801
2802         if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
2803                 printf("read succeeded! nasty security hole [%s]\n", buf);
2804                 return false;
2805         }
2806
2807         cli_close(cli1, fnum1);
2808         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2809
2810         torture_close_connection(cli1);
2811         torture_close_connection(cli2);
2812
2813         printf("finished fdpasstest\n");
2814         return True;
2815 }
2816
2817 static bool run_fdsesstest(int dummy)
2818 {
2819         struct cli_state *cli;
2820         uint16 new_vuid;
2821         uint16 saved_vuid;
2822         uint16 new_cnum;
2823         uint16 saved_cnum;
2824         const char *fname = "\\fdsess.tst";
2825         const char *fname1 = "\\fdsess1.tst";
2826         uint16_t fnum1;
2827         uint16_t fnum2;
2828         char buf[1024];
2829         bool ret = True;
2830         NTSTATUS status;
2831
2832         if (!torture_open_connection(&cli, 0))
2833                 return False;
2834         cli_sockopt(cli, sockops);
2835
2836         if (!torture_cli_session_setup2(cli, &new_vuid))
2837                 return False;
2838
2839         saved_cnum = cli_state_get_tid(cli);
2840         if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, share, "?????", "", 1)))
2841                 return False;
2842         new_cnum = cli_state_get_tid(cli);
2843         cli_state_set_tid(cli, saved_cnum);
2844
2845         printf("starting fdsesstest\n");
2846
2847         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2848         cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2849
2850         status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2851         if (!NT_STATUS_IS_OK(status)) {
2852                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2853                 return False;
2854         }
2855
2856         status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
2857                               NULL);
2858         if (!NT_STATUS_IS_OK(status)) {
2859                 printf("write failed (%s)\n", nt_errstr(status));
2860                 return False;
2861         }
2862
2863         saved_vuid = cli_state_get_uid(cli);
2864         cli_state_set_uid(cli, new_vuid);
2865
2866         if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2867                 printf("read succeeded with different vuid! "
2868                        "nasty security hole [%s]\n", buf);
2869                 ret = false;
2870         }
2871         /* Try to open a file with different vuid, samba cnum. */
2872         if (NT_STATUS_IS_OK(cli_open(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
2873                 printf("create with different vuid, same cnum succeeded.\n");
2874                 cli_close(cli, fnum2);
2875                 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2876         } else {
2877                 printf("create with different vuid, same cnum failed.\n");
2878                 printf("This will cause problems with service clients.\n");
2879                 ret = False;
2880         }
2881
2882         cli_state_set_uid(cli, saved_vuid);
2883
2884         /* Try with same vuid, different cnum. */
2885         cli_state_set_tid(cli, new_cnum);
2886
2887         if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2888                 printf("read succeeded with different cnum![%s]\n", buf);
2889                 ret = false;
2890         }
2891
2892         cli_state_set_tid(cli, saved_cnum);
2893         cli_close(cli, fnum1);
2894         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2895
2896         torture_close_connection(cli);
2897
2898         printf("finished fdsesstest\n");
2899         return ret;
2900 }
2901
2902 /*
2903   This test checks that 
2904
2905   1) the server does not allow an unlink on a file that is open
2906 */
2907 static bool run_unlinktest(int dummy)
2908 {
2909         struct cli_state *cli;
2910         const char *fname = "\\unlink.tst";
2911         uint16_t fnum;
2912         bool correct = True;
2913         NTSTATUS status;
2914
2915         if (!torture_open_connection(&cli, 0)) {
2916                 return False;
2917         }
2918
2919         cli_sockopt(cli, sockops);
2920
2921         printf("starting unlink test\n");
2922
2923         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2924
2925         cli_setpid(cli, 1);
2926
2927         status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2928         if (!NT_STATUS_IS_OK(status)) {
2929                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2930                 return False;
2931         }
2932
2933         status = cli_unlink(cli, fname,
2934                             FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2935         if (NT_STATUS_IS_OK(status)) {
2936                 printf("error: server allowed unlink on an open file\n");
2937                 correct = False;
2938         } else {
2939                 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
2940                                       NT_STATUS_SHARING_VIOLATION);
2941         }
2942
2943         cli_close(cli, fnum);
2944         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2945
2946         if (!torture_close_connection(cli)) {
2947                 correct = False;
2948         }
2949
2950         printf("unlink test finished\n");
2951
2952         return correct;
2953 }
2954
2955
2956 /*
2957 test how many open files this server supports on the one socket
2958 */
2959 static bool run_maxfidtest(int dummy)
2960 {
2961         struct cli_state *cli;
2962         fstring fname;
2963         uint16_t fnums[0x11000];
2964         int i;
2965         int retries=4;
2966         bool correct = True;
2967         NTSTATUS status;
2968
2969         cli = current_cli;
2970
2971         if (retries <= 0) {
2972                 printf("failed to connect\n");
2973                 return False;
2974         }
2975
2976         cli_sockopt(cli, sockops);
2977
2978         for (i=0; i<0x11000; i++) {
2979                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2980                 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
2981                                   &fnums[i]);
2982                 if (!NT_STATUS_IS_OK(status)) {
2983                         printf("open of %s failed (%s)\n", 
2984                                fname, nt_errstr(status));
2985                         printf("maximum fnum is %d\n", i);
2986                         break;
2987                 }
2988                 printf("%6d\r", i);
2989         }
2990         printf("%6d\n", i);
2991         i--;
2992
2993         printf("cleaning up\n");
2994         for (;i>=0;i--) {
2995                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2996                 cli_close(cli, fnums[i]);
2997
2998                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2999                 if (!NT_STATUS_IS_OK(status)) {
3000                         printf("unlink of %s failed (%s)\n", 
3001                                fname, nt_errstr(status));
3002                         correct = False;
3003                 }
3004                 printf("%6d\r", i);
3005         }
3006         printf("%6d\n", 0);
3007
3008         printf("maxfid test finished\n");
3009         if (!torture_close_connection(cli)) {
3010                 correct = False;
3011         }
3012         return correct;
3013 }
3014
3015 /* generate a random buffer */
3016 static void rand_buf(char *buf, int len)
3017 {
3018         while (len--) {
3019                 *buf = (char)sys_random();
3020                 buf++;
3021         }
3022 }
3023
3024 /* send smb negprot commands, not reading the response */
3025 static bool run_negprot_nowait(int dummy)
3026 {
3027         struct tevent_context *ev;
3028         int i;
3029         struct cli_state *cli;
3030         bool correct = True;
3031
3032         printf("starting negprot nowait test\n");
3033
3034         ev = tevent_context_init(talloc_tos());
3035         if (ev == NULL) {
3036                 return false;
3037         }
3038
3039         if (!(cli = open_nbt_connection())) {
3040                 TALLOC_FREE(ev);
3041                 return False;
3042         }
3043
3044         for (i=0;i<50000;i++) {
3045                 struct tevent_req *req;
3046
3047                 req = cli_negprot_send(ev, ev, cli);
3048                 if (req == NULL) {
3049                         TALLOC_FREE(ev);
3050                         return false;
3051                 }
3052                 if (!tevent_req_poll(req, ev)) {
3053                         d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3054                                   strerror(errno));
3055                         TALLOC_FREE(ev);
3056                         return false;
3057                 }
3058                 TALLOC_FREE(req);
3059         }
3060
3061         if (torture_close_connection(cli)) {
3062                 correct = False;
3063         }
3064
3065         printf("finished negprot nowait test\n");
3066
3067         return correct;
3068 }
3069
3070 /* send smb negprot commands, not reading the response */
3071 static bool run_bad_nbt_session(int dummy)
3072 {
3073         struct nmb_name called, calling;
3074         struct sockaddr_storage ss;
3075         NTSTATUS status;
3076         int fd;
3077         bool ret;
3078
3079         printf("starting bad nbt session test\n");
3080
3081         make_nmb_name(&calling, myname, 0x0);
3082         make_nmb_name(&called , host, 0x20);
3083
3084         if (!resolve_name(host, &ss, 0x20, true)) {
3085                 d_fprintf(stderr, "Could not resolve name %s\n", host);
3086                 return false;
3087         }
3088
3089         status = open_socket_out(&ss, 139, 10000, &fd);
3090         if (!NT_STATUS_IS_OK(status)) {
3091                 d_fprintf(stderr, "open_socket_out failed: %s\n",
3092                           nt_errstr(status));
3093                 return false;
3094         }
3095
3096         ret = cli_bad_session_request(fd, &calling, &called);
3097         close(fd);
3098         if (!ret) {
3099                 d_fprintf(stderr, "open_socket_out failed: %s\n",
3100                           nt_errstr(status));
3101                 return false;
3102         }
3103
3104         printf("finished bad nbt session test\n");
3105         return true;
3106 }
3107
3108 /* send random IPC commands */
3109 static bool run_randomipc(int dummy)
3110 {
3111         char *rparam = NULL;
3112         char *rdata = NULL;
3113         unsigned int rdrcnt,rprcnt;
3114         char param[1024];
3115         int api, param_len, i;
3116         struct cli_state *cli;
3117         bool correct = True;
3118         int count = 50000;
3119
3120         printf("starting random ipc test\n");
3121
3122         if (!torture_open_connection(&cli, 0)) {
3123                 return False;
3124         }
3125
3126         for (i=0;i<count;i++) {
3127                 api = sys_random() % 500;
3128                 param_len = (sys_random() % 64);
3129
3130                 rand_buf(param, param_len);
3131
3132                 SSVAL(param,0,api); 
3133
3134                 cli_api(cli, 
3135                         param, param_len, 8,  
3136                         NULL, 0, BUFFER_SIZE, 
3137                         &rparam, &rprcnt,     
3138                         &rdata, &rdrcnt);
3139                 if (i % 100 == 0) {
3140                         printf("%d/%d\r", i,count);
3141                 }
3142         }
3143         printf("%d/%d\n", i, count);
3144
3145         if (!torture_close_connection(cli)) {
3146                 correct = False;
3147         }
3148
3149         printf("finished random ipc test\n");
3150
3151         return correct;
3152 }
3153
3154
3155
3156 static void browse_callback(const char *sname, uint32 stype, 
3157                             const char *comment, void *state)
3158 {
3159         printf("\t%20.20s %08x %s\n", sname, stype, comment);
3160 }
3161
3162
3163
3164 /*
3165   This test checks the browse list code
3166
3167 */
3168 static bool run_browsetest(int dummy)
3169 {
3170         static struct cli_state *cli;
3171         bool correct = True;
3172
3173         printf("starting browse test\n");
3174
3175         if (!torture_open_connection(&cli, 0)) {
3176                 return False;
3177         }
3178
3179         printf("domain list:\n");
3180         cli_NetServerEnum(cli, cli->server_domain, 
3181                           SV_TYPE_DOMAIN_ENUM,
3182                           browse_callback, NULL);
3183
3184         printf("machine list:\n");
3185         cli_NetServerEnum(cli, cli->server_domain, 
3186                           SV_TYPE_ALL,
3187                           browse_callback, NULL);
3188
3189         if (!torture_close_connection(cli)) {
3190                 correct = False;
3191         }
3192
3193         printf("browse test finished\n");
3194
3195         return correct;
3196
3197 }
3198
3199
3200 /*
3201   This checks how the getatr calls works
3202 */
3203 static bool run_attrtest(int dummy)
3204 {
3205         struct cli_state *cli;
3206         uint16_t fnum;
3207         time_t t, t2;
3208         const char *fname = "\\attrib123456789.tst";
3209         bool correct = True;
3210         NTSTATUS status;
3211
3212         printf("starting attrib test\n");
3213
3214         if (!torture_open_connection(&cli, 0)) {
3215                 return False;
3216         }
3217
3218         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3219         cli_open(cli, fname, 
3220                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3221         cli_close(cli, fnum);
3222
3223         status = cli_getatr(cli, fname, NULL, NULL, &t);
3224         if (!NT_STATUS_IS_OK(status)) {
3225                 printf("getatr failed (%s)\n", nt_errstr(status));
3226                 correct = False;
3227         }
3228
3229         if (abs(t - time(NULL)) > 60*60*24*10) {
3230                 printf("ERROR: SMBgetatr bug. time is %s",
3231                        ctime(&t));
3232                 t = time(NULL);
3233                 correct = True;
3234         }
3235
3236         t2 = t-60*60*24; /* 1 day ago */
3237
3238         status = cli_setatr(cli, fname, 0, t2);
3239         if (!NT_STATUS_IS_OK(status)) {
3240                 printf("setatr failed (%s)\n", nt_errstr(status));
3241                 correct = True;
3242         }
3243
3244         status = cli_getatr(cli, fname, NULL, NULL, &t);
3245         if (!NT_STATUS_IS_OK(status)) {
3246                 printf("getatr failed (%s)\n", nt_errstr(status));
3247                 correct = True;
3248         }
3249
3250         if (t != t2) {
3251                 printf("ERROR: getatr/setatr bug. times are\n%s",
3252                        ctime(&t));
3253                 printf("%s", ctime(&t2));
3254                 correct = True;
3255         }
3256
3257         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3258
3259         if (!torture_close_connection(cli)) {
3260                 correct = False;
3261         }
3262
3263         printf("attrib test finished\n");
3264
3265         return correct;
3266 }
3267
3268
3269 /*
3270   This checks a couple of trans2 calls
3271 */
3272 static bool run_trans2test(int dummy)
3273 {
3274         struct cli_state *cli;
3275         uint16_t fnum;
3276         SMB_OFF_T size;
3277         time_t c_time, a_time, m_time;
3278         struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
3279         const char *fname = "\\trans2.tst";
3280         const char *dname = "\\trans2";
3281         const char *fname2 = "\\trans2\\trans2.tst";
3282         char *pname;
3283         bool correct = True;
3284         NTSTATUS status;
3285         uint32_t fs_attr;
3286
3287         printf("starting trans2 test\n");
3288
3289         if (!torture_open_connection(&cli, 0)) {
3290                 return False;
3291         }
3292
3293         status = cli_get_fs_attr_info(cli, &fs_attr);
3294         if (!NT_STATUS_IS_OK(status)) {
3295                 printf("ERROR: cli_get_fs_attr_info returned %s\n",
3296                        nt_errstr(status));
3297                 correct = false;
3298         }
3299
3300         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3301         cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3302         status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
3303                                      &a_time_ts, &w_time_ts, &m_time_ts, NULL);
3304         if (!NT_STATUS_IS_OK(status)) {
3305                 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
3306                 correct = False;
3307         }
3308
3309         status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
3310         if (!NT_STATUS_IS_OK(status)) {
3311                 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
3312                 correct = False;
3313         }
3314
3315         if (strcmp(pname, fname)) {
3316                 printf("qfilename gave different name? [%s] [%s]\n",
3317                        fname, pname);
3318                 correct = False;
3319         }
3320
3321         cli_close(cli, fnum);
3322
3323         sleep(2);
3324
3325         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3326         status = cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
3327                           &fnum);
3328         if (!NT_STATUS_IS_OK(status)) {
3329                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3330                 return False;
3331         }
3332         cli_close(cli, fnum);
3333
3334         status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
3335                                 NULL);
3336         if (!NT_STATUS_IS_OK(status)) {
3337                 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
3338                 correct = False;
3339         } else {
3340                 time_t t = time(NULL);
3341
3342                 if (c_time != m_time) {
3343                         printf("create time=%s", ctime(&c_time));
3344                         printf("modify time=%s", ctime(&m_time));
3345                         printf("This system appears to have sticky create times\n");
3346                 }
3347                 if ((abs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
3348                         printf("access time=%s", ctime(&a_time));
3349                         printf("This system appears to set a midnight access time\n");
3350                         correct = False;
3351                 }
3352
3353                 if (abs(m_time - t) > 60*60*24*7) {
3354                         printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
3355                         correct = False;
3356                 }
3357         }
3358
3359
3360         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3361         cli_open(cli, fname, 
3362                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3363         cli_close(cli, fnum);
3364         status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
3365                                 &m_time_ts, &size, NULL, NULL);
3366         if (!NT_STATUS_IS_OK(status)) {
3367                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3368                 correct = False;
3369         } else {
3370                 if (w_time_ts.tv_sec < 60*60*24*2) {
3371                         printf("write time=%s", ctime(&w_time_ts.tv_sec));
3372                         printf("This system appears to set a initial 0 write time\n");
3373                         correct = False;
3374                 }
3375         }
3376
3377         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3378
3379
3380         /* check if the server updates the directory modification time
3381            when creating a new file */
3382         status = cli_mkdir(cli, dname);
3383         if (!NT_STATUS_IS_OK(status)) {
3384                 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
3385                 correct = False;
3386         }
3387         sleep(3);
3388         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3389                                 &w_time_ts, &m_time_ts, &size, NULL, NULL);
3390         if (!NT_STATUS_IS_OK(status)) {
3391                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3392                 correct = False;
3393         }
3394
3395         cli_open(cli, fname2, 
3396                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3397         cli_writeall(cli, fnum,  0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
3398         cli_close(cli, fnum);
3399         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3400                                 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
3401         if (!NT_STATUS_IS_OK(status)) {
3402                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3403                 correct = False;
3404         } else {
3405                 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
3406                     == 0) {
3407                         printf("This system does not update directory modification times\n");
3408                         correct = False;
3409                 }
3410         }
3411         cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3412         cli_rmdir(cli, dname);
3413
3414         if (!torture_close_connection(cli)) {
3415                 correct = False;
3416         }
3417
3418         printf("trans2 test finished\n");
3419
3420         return correct;
3421 }
3422
3423 /*
3424   This checks new W2K calls.
3425 */
3426
3427 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
3428 {
3429         uint8_t *buf = NULL;
3430         uint32 len;
3431         NTSTATUS status;
3432
3433         status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
3434                                pcli->max_xmit, NULL, &buf, &len);
3435         if (!NT_STATUS_IS_OK(status)) {
3436                 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
3437                        nt_errstr(status));
3438         } else {
3439                 printf("qfileinfo: level %d, len = %u\n", level, len);
3440                 dump_data(0, (uint8 *)buf, len);
3441                 printf("\n");
3442         }
3443         TALLOC_FREE(buf);
3444         return status;
3445 }
3446
3447 static bool run_w2ktest(int dummy)
3448 {
3449         struct cli_state *cli;
3450         uint16_t fnum;
3451         const char *fname = "\\w2ktest\\w2k.tst";
3452         int level;
3453         bool correct = True;
3454
3455         printf("starting w2k test\n");
3456
3457         if (!torture_open_connection(&cli, 0)) {
3458                 return False;
3459         }
3460
3461         cli_open(cli, fname, 
3462                         O_RDWR | O_CREAT , DENY_NONE, &fnum);
3463
3464         for (level = 1004; level < 1040; level++) {
3465                 new_trans(cli, fnum, level);
3466         }
3467
3468         cli_close(cli, fnum);
3469
3470         if (!torture_close_connection(cli)) {
3471                 correct = False;
3472         }
3473
3474         printf("w2k test finished\n");
3475
3476         return correct;
3477 }
3478
3479
3480 /*
3481   this is a harness for some oplock tests
3482  */
3483 static bool run_oplock1(int dummy)
3484 {
3485         struct cli_state *cli1;
3486         const char *fname = "\\lockt1.lck";
3487         uint16_t fnum1;
3488         bool correct = True;
3489         NTSTATUS status;
3490
3491         printf("starting oplock test 1\n");
3492
3493         if (!torture_open_connection(&cli1, 0)) {
3494                 return False;
3495         }
3496
3497         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3498
3499         cli_sockopt(cli1, sockops);
3500
3501         cli1->use_oplocks = True;
3502
3503         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3504                           &fnum1);
3505         if (!NT_STATUS_IS_OK(status)) {
3506                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3507                 return False;
3508         }
3509
3510         cli1->use_oplocks = False;
3511
3512         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3513         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3514
3515         status = cli_close(cli1, fnum1);
3516         if (!NT_STATUS_IS_OK(status)) {
3517                 printf("close2 failed (%s)\n", nt_errstr(status));
3518                 return False;
3519         }
3520
3521         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3522         if (!NT_STATUS_IS_OK(status)) {
3523                 printf("unlink failed (%s)\n", nt_errstr(status));
3524                 return False;
3525         }
3526
3527         if (!torture_close_connection(cli1)) {
3528                 correct = False;
3529         }
3530
3531         printf("finished oplock test 1\n");
3532
3533         return correct;
3534 }
3535
3536 static bool run_oplock2(int dummy)
3537 {
3538         struct cli_state *cli1, *cli2;
3539         const char *fname = "\\lockt2.lck";
3540         uint16_t fnum1, fnum2;
3541         int saved_use_oplocks = use_oplocks;
3542         char buf[4];
3543         bool correct = True;
3544         volatile bool *shared_correct;
3545         size_t nread;
3546         NTSTATUS status;
3547
3548         shared_correct = (volatile bool *)shm_setup(sizeof(bool));
3549         *shared_correct = True;
3550
3551         use_level_II_oplocks = True;
3552         use_oplocks = True;
3553
3554         printf("starting oplock test 2\n");
3555
3556         if (!torture_open_connection(&cli1, 0)) {
3557                 use_level_II_oplocks = False;
3558                 use_oplocks = saved_use_oplocks;
3559                 return False;
3560         }
3561
3562         if (!torture_open_connection(&cli2, 1)) {
3563                 use_level_II_oplocks = False;
3564                 use_oplocks = saved_use_oplocks;
3565                 return False;
3566         }
3567
3568         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3569
3570         cli_sockopt(cli1, sockops);
3571         cli_sockopt(cli2, sockops);
3572
3573         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3574                           &fnum1);
3575         if (!NT_STATUS_IS_OK(status)) {
3576                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3577                 return False;
3578         }
3579
3580         /* Don't need the globals any more. */
3581         use_level_II_oplocks = False;
3582         use_oplocks = saved_use_oplocks;
3583
3584         if (fork() == 0) {
3585                 /* Child code */
3586                 status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
3587                 if (!NT_STATUS_IS_OK(status)) {
3588                         printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
3589                         *shared_correct = False;
3590                         exit(0);
3591                 }
3592
3593                 sleep(2);
3594
3595                 status = cli_close(cli2, fnum2);
3596                 if (!NT_STATUS_IS_OK(status)) {
3597                         printf("close2 failed (%s)\n", nt_errstr(status));
3598                         *shared_correct = False;
3599                 }
3600
3601                 exit(0);
3602         }
3603
3604         sleep(2);
3605
3606         /* Ensure cli1 processes the break. Empty file should always return 0
3607          * bytes.  */
3608         status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
3609         if (!NT_STATUS_IS_OK(status)) {
3610                 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
3611                 correct = false;
3612         } else if (nread != 0) {
3613                 printf("read on empty fnum1 failed. recv %ld expected %d\n",
3614                       (unsigned long)nread, 0);
3615                 correct = false;
3616         }
3617
3618         /* Should now be at level II. */
3619         /* Test if sending a write locks causes a break to none. */
3620         status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
3621         if (!NT_STATUS_IS_OK(status)) {
3622                 printf("lock failed (%s)\n", nt_errstr(status));
3623                 correct = False;
3624         }
3625
3626         cli_unlock(cli1, fnum1, 0, 4);
3627
3628         sleep(2);
3629
3630         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
3631         if (!NT_STATUS_IS_OK(status)) {
3632                 printf("lock failed (%s)\n", nt_errstr(status));
3633                 correct = False;
3634         }
3635
3636         cli_unlock(cli1, fnum1, 0, 4);
3637
3638         sleep(2);
3639
3640         cli_read(cli1, fnum1, buf, 0, 4, NULL);
3641
3642         status = cli_close(cli1, fnum1);
3643         if (!NT_STATUS_IS_OK(status)) {
3644                 printf("close1 failed (%s)\n", nt_errstr(status));
3645                 correct = False;
3646         }
3647
3648         sleep(4);
3649
3650         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3651         if (!NT_STATUS_IS_OK(status)) {
3652                 printf("unlink failed (%s)\n", nt_errstr(status));
3653                 correct = False;
3654         }
3655
3656         if (!torture_close_connection(cli1)) {
3657                 correct = False;
3658         }
3659
3660         if (!*shared_correct) {
3661                 correct = False;
3662         }
3663
3664         printf("finished oplock test 2\n");
3665
3666         return correct;
3667 }
3668
3669 struct oplock4_state {
3670         struct tevent_context *ev;
3671         struct cli_state *cli;
3672         bool *got_break;
3673         uint16_t *fnum2;
3674 };
3675
3676 static void oplock4_got_break(struct tevent_req *req);
3677 static void oplock4_got_open(struct tevent_req *req);
3678
3679 static bool run_oplock4(int dummy)
3680 {
3681         struct tevent_context *ev;
3682         struct cli_state *cli1, *cli2;
3683         struct tevent_req *oplock_req, *open_req;
3684         const char *fname = "\\lockt4.lck";
3685         const char *fname_ln = "\\lockt4_ln.lck";
3686         uint16_t fnum1, fnum2;
3687         int saved_use_oplocks = use_oplocks;
3688         NTSTATUS status;
3689         bool correct = true;
3690
3691         bool got_break;
3692
3693         struct oplock4_state *state;
3694
3695         printf("starting oplock test 4\n");
3696
3697         if (!torture_open_connection(&cli1, 0)) {
3698                 use_level_II_oplocks = false;
3699                 use_oplocks = saved_use_oplocks;
3700                 return false;
3701         }
3702
3703         if (!torture_open_connection(&cli2, 1)) {
3704                 use_level_II_oplocks = false;
3705                 use_oplocks = saved_use_oplocks;
3706                 return false;
3707         }
3708
3709         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3710         cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3711
3712         cli_sockopt(cli1, sockops);
3713         cli_sockopt(cli2, sockops);
3714
3715         /* Create the file. */
3716         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3717                           &fnum1);
3718         if (!NT_STATUS_IS_OK(status)) {
3719                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3720                 return false;
3721         }
3722
3723         status = cli_close(cli1, fnum1);
3724         if (!NT_STATUS_IS_OK(status)) {
3725                 printf("close1 failed (%s)\n", nt_errstr(status));
3726                 return false;
3727         }
3728
3729         /* Now create a hardlink. */
3730         status = cli_nt_hardlink(cli1, fname, fname_ln);
3731         if (!NT_STATUS_IS_OK(status)) {
3732                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
3733                 return false;
3734         }
3735
3736         /* Prove that opening hardlinks cause deny modes to conflict. */
3737         status = cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
3738         if (!NT_STATUS_IS_OK(status)) {
3739                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3740                 return false;
3741         }
3742
3743         status = cli_open(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
3744         if (NT_STATUS_IS_OK(status)) {
3745                 printf("open of %s succeeded - should fail with sharing violation.\n",
3746                         fname_ln);
3747                 return false;
3748         }
3749
3750         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3751                 printf("open of %s should fail with sharing violation. Got %s\n",
3752                         fname_ln, nt_errstr(status));
3753                 return false;
3754         }
3755
3756         status = cli_close(cli1, fnum1);
3757         if (!NT_STATUS_IS_OK(status)) {
3758                 printf("close1 failed (%s)\n", nt_errstr(status));
3759                 return false;
3760         }
3761
3762         cli1->use_oplocks = true;
3763         cli1->use_level_II_oplocks = true;
3764
3765         cli2->use_oplocks = true;
3766         cli2->use_level_II_oplocks = true;
3767
3768         status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3769         if (!NT_STATUS_IS_OK(status)) {
3770                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3771                 return false;
3772         }
3773
3774         ev = tevent_context_init(talloc_tos());
3775         if (ev == NULL) {
3776                 printf("tevent_req_create failed\n");
3777                 return false;
3778         }
3779
3780         state = talloc(ev, struct oplock4_state);
3781         if (state == NULL) {
3782                 printf("talloc failed\n");
3783                 return false;
3784         }
3785         state->ev = ev;
3786         state->cli = cli1;
3787         state->got_break = &got_break;
3788         state->fnum2 = &fnum2;
3789
3790         oplock_req = cli_smb_oplock_break_waiter_send(
3791                 talloc_tos(), ev, cli1);
3792         if (oplock_req == NULL) {
3793                 printf("cli_smb_oplock_break_waiter_send failed\n");
3794                 return false;
3795         }
3796         tevent_req_set_callback(oplock_req, oplock4_got_break, state);
3797
3798         open_req = cli_open_send(
3799                 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
3800         if (oplock_req == NULL) {
3801                 printf("cli_open_send failed\n");
3802                 return false;
3803         }
3804         tevent_req_set_callback(open_req, oplock4_got_open, state);
3805
3806         got_break = false;
3807         fnum2 = 0xffff;
3808
3809         while (!got_break || fnum2 == 0xffff) {
3810                 int ret;
3811                 ret = tevent_loop_once(ev);
3812                 if (ret == -1) {
3813                         printf("tevent_loop_once failed: %s\n",
3814                                strerror(errno));
3815                         return false;
3816                 }
3817         }
3818
3819         status = cli_close(cli2, fnum2);
3820         if (!NT_STATUS_IS_OK(status)) {
3821                 printf("close2 failed (%s)\n", nt_errstr(status));
3822                 correct = false;
3823         }
3824
3825         status = cli_close(cli1, fnum1);
3826         if (!NT_STATUS_IS_OK(status)) {
3827                 printf("close1 failed (%s)\n", nt_errstr(status));
3828                 correct = false;
3829         }
3830
3831         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3832         if (!NT_STATUS_IS_OK(status)) {
3833                 printf("unlink failed (%s)\n", nt_errstr(status));
3834                 correct = false;
3835         }
3836
3837         status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3838         if (!NT_STATUS_IS_OK(status)) {
3839                 printf("unlink failed (%s)\n", nt_errstr(status));
3840                 correct = false;
3841         }
3842
3843         if (!torture_close_connection(cli1)) {
3844                 correct = false;
3845         }
3846
3847         if (!got_break) {
3848                 correct = false;
3849         }
3850
3851         printf("finished oplock test 4\n");
3852
3853         return correct;
3854 }
3855
3856 static void oplock4_got_break(struct tevent_req *req)
3857 {
3858         struct oplock4_state *state = tevent_req_callback_data(
3859                 req, struct oplock4_state);
3860         uint16_t fnum;
3861         uint8_t level;
3862         NTSTATUS status;
3863
3864         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
3865         TALLOC_FREE(req);
3866         if (!NT_STATUS_IS_OK(status)) {
3867                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
3868                        nt_errstr(status));
3869                 return;
3870         }
3871         *state->got_break = true;
3872
3873         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
3874                                   NO_OPLOCK);
3875         if (req == NULL) {
3876                 printf("cli_oplock_ack_send failed\n");
3877                 return;
3878         }
3879 }
3880
3881 static void oplock4_got_open(struct tevent_req *req)
3882 {
3883         struct oplock4_state *state = tevent_req_callback_data(
3884                 req, struct oplock4_state);
3885         NTSTATUS status;
3886
3887         status = cli_open_recv(req, state->fnum2);
3888         if (!NT_STATUS_IS_OK(status)) {
3889                 printf("cli_open_recv returned %s\n", nt_errstr(status));
3890                 *state->fnum2 = 0xffff;
3891         }
3892 }
3893
3894 /*
3895   Test delete on close semantics.
3896  */
3897 static bool run_deletetest(int dummy)
3898 {
3899         struct cli_state *cli1 = NULL;
3900         struct cli_state *cli2 = NULL;
3901         const char *fname = "\\delete.file";
3902         uint16_t fnum1 = (uint16_t)-1;
3903         uint16_t fnum2 = (uint16_t)-1;
3904         bool correct = True;
3905         NTSTATUS status;
3906
3907         printf("starting delete test\n");
3908
3909         if (!torture_open_connection(&cli1, 0)) {
3910                 return False;
3911         }
3912
3913         cli_sockopt(cli1, sockops);
3914
3915         /* Test 1 - this should delete the file on close. */
3916
3917         cli_setatr(cli1, fname, 0, 0);
3918         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3919
3920         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
3921                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
3922                               FILE_DELETE_ON_CLOSE, 0, &fnum1);
3923         if (!NT_STATUS_IS_OK(status)) {
3924                 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
3925                 correct = False;
3926                 goto fail;
3927         }
3928
3929         status = cli_close(cli1, fnum1);
3930         if (!NT_STATUS_IS_OK(status)) {
3931                 printf("[1] close failed (%s)\n", nt_errstr(status));
3932                 correct = False;
3933                 goto fail;
3934         }
3935
3936         if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1))) {
3937                 printf("[1] open of %s succeeded (should fail)\n", fname);
3938                 correct = False;
3939                 goto fail;
3940         }
3941
3942         printf("first delete on close test succeeded.\n");
3943
3944         /* Test 2 - this should delete the file on close. */
3945
3946         cli_setatr(cli1, fname, 0, 0);
3947         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3948
3949         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3950                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
3951                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
3952         if (!NT_STATUS_IS_OK(status)) {
3953                 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
3954                 correct = False;
3955                 goto fail;
3956         }
3957
3958         status = cli_nt_delete_on_close(cli1, fnum1, true);
3959         if (!NT_STATUS_IS_OK(status)) {
3960                 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
3961                 correct = False;
3962                 goto fail;
3963         }
3964
3965         status = cli_close(cli1, fnum1);
3966         if (!NT_STATUS_IS_OK(status)) {
3967                 printf("[2] close failed (%s)\n", nt_errstr(status));
3968                 correct = False;
3969                 goto fail;
3970         }
3971
3972         if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3973                 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
3974                 status = cli_close(cli1, fnum1);
3975                 if (!NT_STATUS_IS_OK(status)) {
3976                         printf("[2] close failed (%s)\n", nt_errstr(status));
3977                         correct = False;
3978                         goto fail;
3979                 }
3980                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3981         } else
3982                 printf("second delete on close test succeeded.\n");
3983
3984         /* Test 3 - ... */
3985         cli_setatr(cli1, fname, 0, 0);
3986         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3987
3988         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3989                               FILE_ATTRIBUTE_NORMAL,
3990                               FILE_SHARE_READ|FILE_SHARE_WRITE,
3991                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
3992         if (!NT_STATUS_IS_OK(status)) {
3993                 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
3994                 correct = False;
3995                 goto fail;
3996         }
3997
3998         /* This should fail with a sharing violation - open for delete is only compatible
3999            with SHARE_DELETE. */
4000
4001         if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4002                         FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, 0, &fnum2))) {
4003                 printf("[3] open  - 2 of %s succeeded - should have failed.\n", fname);
4004                 correct = False;
4005                 goto fail;
4006         }
4007
4008         /* This should succeed. */
4009         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4010                              FILE_ATTRIBUTE_NORMAL,
4011                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4012                              FILE_OPEN, 0, 0, &fnum2);
4013         if (!NT_STATUS_IS_OK(status)) {
4014                 printf("[3] open  - 2 of %s failed (%s)\n", fname, nt_errstr(status));
4015                 correct = False;
4016                 goto fail;
4017         }
4018
4019         status = cli_nt_delete_on_close(cli1, fnum1, true);
4020         if (!NT_STATUS_IS_OK(status)) {
4021                 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
4022                 correct = False;
4023                 goto fail;
4024         }
4025
4026         status = cli_close(cli1, fnum1);
4027         if (!NT_STATUS_IS_OK(status)) {
4028                 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
4029                 correct = False;
4030                 goto fail;
4031         }
4032
4033         status = cli_close(cli1, fnum2);
4034         if (!NT_STATUS_IS_OK(status)) {
4035                 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
4036                 correct = False;
4037                 goto fail;
4038         }
4039
4040         /* This should fail - file should no longer be there. */
4041
4042         if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
4043                 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
4044                 status = cli_close(cli1, fnum1);
4045                 if (!NT_STATUS_IS_OK(status)) {
4046                         printf("[3] close failed (%s)\n", nt_errstr(status));
4047                 }
4048                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4049                 correct = False;
4050                 goto fail;
4051         } else
4052                 printf("third delete on close test succeeded.\n");
4053
4054         /* Test 4 ... */
4055         cli_setatr(cli1, fname, 0, 0);
4056         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4057
4058         status = cli_ntcreate(cli1, fname, 0,
4059                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4060                               FILE_ATTRIBUTE_NORMAL,
4061                               FILE_SHARE_READ|FILE_SHARE_WRITE,
4062                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4063         if (!NT_STATUS_IS_OK(status)) {
4064                 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
4065                 correct = False;
4066                 goto fail;
4067         }
4068
4069         /* This should succeed. */
4070         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4071                              FILE_ATTRIBUTE_NORMAL,
4072                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4073                              FILE_OPEN, 0, 0, &fnum2);
4074         if (!NT_STATUS_IS_OK(status)) {
4075                 printf("[4] open  - 2 of %s failed (%s)\n", fname, nt_errstr(status));
4076                 correct = False;
4077                 goto fail;
4078         }
4079
4080         status = cli_close(cli1, fnum2);
4081         if (!NT_STATUS_IS_OK(status)) {
4082                 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
4083                 correct = False;
4084                 goto fail;
4085         }
4086
4087         status = cli_nt_delete_on_close(cli1, fnum1, true);
4088         if (!NT_STATUS_IS_OK(status)) {
4089                 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
4090                 correct = False;
4091                 goto fail;
4092         }
4093
4094         /* This should fail - no more opens once delete on close set. */
4095         if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4096                                    FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4097                                    FILE_OPEN, 0, 0, &fnum2))) {
4098                 printf("[4] open  - 3 of %s succeeded ! Should have failed.\n", fname );
4099                 correct = False;
4100                 goto fail;
4101         } else
4102                 printf("fourth delete on close test succeeded.\n");
4103
4104         status = cli_close(cli1, fnum1);
4105         if (!NT_STATUS_IS_OK(status)) {
4106                 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
4107                 correct = False;
4108                 goto fail;
4109         }
4110
4111         /* Test 5 ... */
4112         cli_setatr(cli1, fname, 0, 0);
4113         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4114
4115         status = cli_open(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
4116         if (!NT_STATUS_IS_OK(status)) {
4117                 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4118                 correct = False;
4119                 goto fail;
4120         }
4121
4122         /* This should fail - only allowed on NT opens with DELETE access. */
4123
4124         if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4125                 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
4126                 correct = False;
4127                 goto fail;
4128         }
4129
4130         status = cli_close(cli1, fnum1);
4131         if (!NT_STATUS_IS_OK(status)) {
4132                 printf("[5] close - 2 failed (%s)\n", nt_errstr(status));
4133                 correct = False;
4134                 goto fail;
4135         }
4136
4137         printf("fifth delete on close test succeeded.\n");
4138
4139         /* Test 6 ... */
4140         cli_setatr(cli1, fname, 0, 0);
4141         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4142
4143         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4144                              FILE_ATTRIBUTE_NORMAL,
4145                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4146                              FILE_OVERWRITE_IF, 0, 0, &fnum1);
4147         if (!NT_STATUS_IS_OK(status)) {
4148                 printf("[6] open of %s failed (%s)\n", fname,
4149                        nt_errstr(status));
4150                 correct = False;
4151                 goto fail;
4152         }
4153
4154         /* This should fail - only allowed on NT opens with DELETE access. */
4155
4156         if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4157                 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
4158                 correct = False;
4159                 goto fail;
4160         }
4161
4162         status = cli_close(cli1, fnum1);
4163         if (!NT_STATUS_IS_OK(status)) {
4164                 printf("[6] close - 2 failed (%s)\n", nt_errstr(status));
4165                 correct = False;
4166                 goto fail;
4167         }
4168
4169         printf("sixth delete on close test succeeded.\n");
4170
4171         /* Test 7 ... */
4172         cli_setatr(cli1, fname, 0, 0);
4173         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4174
4175         status = cli_ntcreate(cli1, fname, 0,
4176                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4177                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
4178                               0, 0, &fnum1);
4179         if (!NT_STATUS_IS_OK(status)) {
4180                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4181                 correct = False;
4182                 goto fail;
4183         }
4184
4185         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4186                 printf("[7] setting delete_on_close on file failed !\n");
4187                 correct = False;
4188                 goto fail;
4189         }
4190
4191         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, false))) {
4192                 printf("[7] unsetting delete_on_close on file failed !\n");
4193                 correct = False;
4194                 goto fail;
4195         }
4196
4197         status = cli_close(cli1, fnum1);
4198         if (!NT_STATUS_IS_OK(status)) {
4199                 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4200                 correct = False;
4201                 goto fail;
4202         }
4203
4204         /* This next open should succeed - we reset the flag. */
4205         status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4206         if (!NT_STATUS_IS_OK(status)) {
4207                 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4208                 correct = False;
4209                 goto fail;
4210         }
4211
4212         status = cli_close(cli1, fnum1);
4213         if (!NT_STATUS_IS_OK(status)) {
4214                 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4215                 correct = False;
4216                 goto fail;
4217         }
4218
4219         printf("seventh delete on close test succeeded.\n");
4220
4221         /* Test 7 ... */
4222         cli_setatr(cli1, fname, 0, 0);
4223         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4224
4225         if (!torture_open_connection(&cli2, 1)) {
4226                 printf("[8] failed to open second connection.\n");
4227                 correct = False;
4228                 goto fail;
4229         }
4230
4231         cli_sockopt(cli1, sockops);
4232
4233         status = cli_ntcreate(cli1, fname, 0,
4234                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4235                              FILE_ATTRIBUTE_NORMAL,
4236                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4237                              FILE_OVERWRITE_IF, 0, 0, &fnum1);
4238         if (!NT_STATUS_IS_OK(status)) {
4239                 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4240                 correct = False;
4241                 goto fail;
4242         }
4243
4244         status = cli_ntcreate(cli2, fname, 0,
4245                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4246                              FILE_ATTRIBUTE_NORMAL,
4247                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4248                              FILE_OPEN, 0, 0, &fnum2);
4249         if (!NT_STATUS_IS_OK(status)) {
4250                 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4251                 correct = False;
4252                 goto fail;
4253         }
4254
4255         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4256                 printf("[8] setting delete_on_close on file failed !\n");
4257                 correct = False;
4258                 goto fail;
4259         }
4260
4261         status = cli_close(cli1, fnum1);
4262         if (!NT_STATUS_IS_OK(status)) {
4263                 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
4264                 correct = False;
4265                 goto fail;
4266         }
4267
4268         status = cli_close(cli2, fnum2);
4269         if (!NT_STATUS_IS_OK(status)) {
4270                 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
4271                 correct = False;
4272                 goto fail;
4273         }
4274
4275         /* This should fail.. */
4276         status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4277         if (NT_STATUS_IS_OK(status)) {
4278                 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
4279                 goto fail;
4280                 correct = False;
4281         } else
4282                 printf("eighth delete on close test succeeded.\n");
4283
4284         /* This should fail - we need to set DELETE_ACCESS. */
4285         if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0,FILE_READ_DATA|FILE_WRITE_DATA,
4286                                    FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE, 0, &fnum1))) {
4287                 printf("[9] open of %s succeeded should have failed!\n", fname);
4288                 correct = False;
4289                 goto fail;
4290         }
4291
4292         printf("ninth delete on close test succeeded.\n");
4293
4294         status = cli_ntcreate(cli1, fname, 0,
4295                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4296                              FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4297                              FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
4298                              0, &fnum1);
4299         if (!NT_STATUS_IS_OK(status)) {
4300                 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
4301                 correct = False;
4302                 goto fail;
4303         }
4304
4305         /* This should delete the file. */
4306         status = cli_close(cli1, fnum1);
4307         if (!NT_STATUS_IS_OK(status)) {
4308                 printf("[10] close failed (%s)\n", nt_errstr(status));
4309                 correct = False;
4310                 goto fail;
4311         }
4312
4313         /* This should fail.. */
4314         if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
4315                 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
4316                 goto fail;
4317                 correct = False;
4318         } else
4319                 printf("tenth delete on close test succeeded.\n");
4320
4321         cli_setatr(cli1, fname, 0, 0);
4322         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4323
4324         /* What error do we get when attempting to open a read-only file with
4325            delete access ? */
4326
4327         /* Create a readonly file. */
4328         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4329                               FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
4330                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4331         if (!NT_STATUS_IS_OK(status)) {
4332                 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
4333                 correct = False;
4334                 goto fail;
4335         }
4336
4337         status = cli_close(cli1, fnum1);
4338         if (!NT_STATUS_IS_OK(status)) {
4339                 printf("[11] close failed (%s)\n", nt_errstr(status));
4340                 correct = False;
4341                 goto fail;
4342         }
4343
4344         /* Now try open for delete access. */
4345         if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES|DELETE_ACCESS,
4346                                    0, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4347                                    FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4348                 printf("[11] open of %s succeeded should have been denied with ACCESS_DENIED!\n", fname);
4349                 cli_close(cli1, fnum1);
4350                 goto fail;
4351                 correct = False;
4352         } else {
4353                 NTSTATUS nterr = cli_nt_error(cli1);
4354                 if (!NT_STATUS_EQUAL(nterr,NT_STATUS_ACCESS_DENIED)) {
4355                         printf("[11] open of %s should have been denied with ACCESS_DENIED! Got error %s\n", fname, nt_errstr(nterr));
4356                         goto fail;
4357                         correct = False;
4358                 } else {
4359                         printf("eleventh delete on close test succeeded.\n");
4360                 }
4361         }
4362
4363         printf("finished delete test\n");
4364
4365   fail:
4366         /* FIXME: This will crash if we aborted before cli2 got
4367          * intialized, because these functions don't handle
4368          * uninitialized connections. */
4369
4370         if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
4371         if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
4372         cli_setatr(cli1, fname, 0, 0);
4373         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4374
4375         if (cli1 && !torture_close_connection(cli1)) {
4376                 correct = False;
4377         }
4378         if (cli2 && !torture_close_connection(cli2)) {
4379                 correct = False;
4380         }
4381         return correct;
4382 }
4383
4384 static bool run_deletetest_ln(int dummy)
4385 {
4386         struct cli_state *cli;
4387         const char *fname = "\\delete1";
4388         const char *fname_ln = "\\delete1_ln";
4389         uint16_t fnum;
4390         uint16_t fnum1;
4391         NTSTATUS status;
4392         bool correct = true;
4393         time_t t;
4394
4395         printf("starting deletetest-ln\n");
4396
4397         if (!torture_open_connection(&cli, 0)) {
4398                 return false;
4399         }
4400
4401         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4402         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4403
4404         cli_sockopt(cli, sockops);
4405
4406         /* Create the file. */
4407         status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
4408         if (!NT_STATUS_IS_OK(status)) {
4409                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4410                 return false;
4411         }
4412
4413         status = cli_close(cli, fnum);
4414         if (!NT_STATUS_IS_OK(status)) {
4415                 printf("close1 failed (%s)\n", nt_errstr(status));
4416                 return false;
4417         }
4418
4419         /* Now create a hardlink. */
4420         status = cli_nt_hardlink(cli, fname, fname_ln);
4421         if (!NT_STATUS_IS_OK(status)) {
4422                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4423                 return false;
4424         }
4425
4426         /* Open the original file. */
4427         status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
4428                         FILE_ATTRIBUTE_NORMAL,
4429                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4430                         FILE_OPEN_IF, 0, 0, &fnum);
4431         if (!NT_STATUS_IS_OK(status)) {
4432                 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
4433                 return false;
4434         }
4435
4436         /* Unlink the hard link path. */
4437         status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
4438                         FILE_ATTRIBUTE_NORMAL,
4439                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4440                         FILE_OPEN_IF, 0, 0, &fnum1);
4441         if (!NT_STATUS_IS_OK(status)) {
4442                 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
4443                 return false;
4444         }
4445         status = cli_nt_delete_on_close(cli, fnum1, true);
4446         if (!NT_STATUS_IS_OK(status)) {
4447                 d_printf("(%s) failed to set delete_on_close %s: %s\n",
4448                         __location__, fname_ln, nt_errstr(status));
4449                 return false;
4450         }
4451
4452         status = cli_close(cli, fnum1);
4453         if (!NT_STATUS_IS_OK(status)) {
4454                 printf("close %s failed (%s)\n",
4455                         fname_ln, nt_errstr(status));
4456                 return false;
4457         }
4458
4459         status = cli_close(cli, fnum);
4460         if (!NT_STATUS_IS_OK(status)) {
4461                 printf("close %s failed (%s)\n",
4462                         fname, nt_errstr(status));
4463                 return false;
4464         }
4465
4466         /* Ensure the original file is still there. */
4467         status = cli_getatr(cli, fname, NULL, NULL, &t);
4468         if (!NT_STATUS_IS_OK(status)) {
4469                 printf("%s getatr on file %s failed (%s)\n",
4470                         __location__,
4471                         fname,
4472                         nt_errstr(status));
4473                 correct = False;
4474         }
4475
4476         /* Ensure the link path is gone. */
4477         status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
4478         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4479                 printf("%s, getatr for file %s returned wrong error code %s "
4480                         "- should have been deleted\n",
4481                         __location__,
4482                         fname_ln, nt_errstr(status));
4483                 correct = False;
4484         }
4485
4486         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4487         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4488
4489         if (!torture_close_connection(cli)) {
4490                 correct = false;
4491         }
4492
4493         printf("finished deletetest-ln\n");
4494
4495         return correct;
4496 }
4497
4498 /*
4499   print out server properties
4500  */
4501 static bool run_properties(int dummy)
4502 {
4503         struct cli_state *cli;
4504         bool correct = True;
4505
4506         printf("starting properties test\n");
4507
4508         ZERO_STRUCT(cli);
4509
4510         if (!torture_open_connection(&cli, 0)) {
4511                 return False;
4512         }
4513
4514         cli_sockopt(cli, sockops);
4515
4516         d_printf("Capabilities 0x%08x\n", cli_state_capabilities(cli));
4517
4518         if (!torture_close_connection(cli)) {
4519                 correct = False;
4520         }
4521
4522         return correct;
4523 }
4524
4525
4526
4527 /* FIRST_DESIRED_ACCESS   0xf019f */
4528 #define FIRST_DESIRED_ACCESS   FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
4529                                FILE_READ_EA|                           /* 0xf */ \
4530                                FILE_WRITE_EA|FILE_READ_ATTRIBUTES|     /* 0x90 */ \
4531                                FILE_WRITE_ATTRIBUTES|                  /* 0x100 */ \
4532                                DELETE_ACCESS|READ_CONTROL_ACCESS|\
4533                                WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS     /* 0xf0000 */
4534 /* SECOND_DESIRED_ACCESS  0xe0080 */
4535 #define SECOND_DESIRED_ACCESS  FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
4536                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4537                                WRITE_OWNER_ACCESS                      /* 0xe0000 */
4538
4539 #if 0
4540 #define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
4541                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4542                                FILE_READ_DATA|\
4543                                WRITE_OWNER_ACCESS                      /* */
4544 #endif
4545
4546 /*
4547   Test ntcreate calls made by xcopy
4548  */
4549 static bool run_xcopy(int dummy)
4550 {
4551         static struct cli_state *cli1;
4552         const char *fname = "\\test.txt";
4553         bool correct = True;
4554         uint16_t fnum1, fnum2;
4555         NTSTATUS status;
4556
4557         printf("starting xcopy test\n");
4558
4559         if (!torture_open_connection(&cli1, 0)) {
4560                 return False;
4561         }
4562
4563         status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
4564                               FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
4565                               FILE_OVERWRITE_IF, 0x4044, 0, &fnum1);
4566         if (!NT_STATUS_IS_OK(status)) {
4567                 printf("First open failed - %s\n", nt_errstr(status));
4568                 return False;
4569         }
4570
4571         status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
4572                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4573                              FILE_OPEN, 0x200000, 0, &fnum2);
4574         if (!NT_STATUS_IS_OK(status)) {
4575                 printf("second open failed - %s\n", nt_errstr(status));
4576                 return False;
4577         }
4578
4579         if (!torture_close_connection(cli1)) {
4580                 correct = False;
4581         }
4582
4583         return correct;
4584 }
4585
4586 /*
4587   Test rename on files open with share delete and no share delete.
4588  */
4589 static bool run_rename(int dummy)
4590 {
4591         static struct cli_state *cli1;
4592         const char *fname = "\\test.txt";
4593         const char *fname1 = "\\test1.txt";
4594         bool correct = True;
4595         uint16_t fnum1;
4596         uint16_t attr;
4597         NTSTATUS status;
4598
4599         printf("starting rename test\n");
4600
4601         if (!torture_open_connection(&cli1, 0)) {
4602                 return False;
4603         }
4604
4605         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4606         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4607
4608         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4609                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
4610                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4611         if (!NT_STATUS_IS_OK(status)) {
4612                 printf("First open failed - %s\n", nt_errstr(status));
4613                 return False;
4614         }
4615
4616         status = cli_rename(cli1, fname, fname1);
4617         if (!NT_STATUS_IS_OK(status)) {
4618                 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
4619         } else {
4620                 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
4621                 correct = False;
4622         }
4623
4624         status = cli_close(cli1, fnum1);
4625         if (!NT_STATUS_IS_OK(status)) {
4626                 printf("close - 1 failed (%s)\n", nt_errstr(status));
4627                 return False;
4628         }
4629
4630         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4631         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4632         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4633 #if 0
4634                               FILE_SHARE_DELETE|FILE_SHARE_NONE,
4635 #else
4636                               FILE_SHARE_DELETE|FILE_SHARE_READ,
4637 #endif
4638                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4639         if (!NT_STATUS_IS_OK(status)) {
4640                 printf("Second open failed - %s\n", nt_errstr(status));
4641                 return False;
4642         }
4643
4644         status = cli_rename(cli1, fname, fname1);
4645         if (!NT_STATUS_IS_OK(status)) {
4646                 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
4647                 correct = False;
4648         } else {
4649                 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
4650         }
4651
4652         status = cli_close(cli1, fnum1);
4653         if (!NT_STATUS_IS_OK(status)) {
4654                 printf("close - 2 failed (%s)\n", nt_errstr(status));
4655                 return False;
4656         }
4657
4658         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4659         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4660
4661         status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
4662                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4663                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4664         if (!NT_STATUS_IS_OK(status)) {
4665                 printf("Third open failed - %s\n", nt_errstr(status));
4666                 return False;
4667         }
4668
4669
4670 #if 0
4671   {
4672         uint16_t fnum2;
4673
4674         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
4675                                    FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4676                 printf("Fourth open failed - %s\n", cli_errstr(cli1));
4677                 return False;
4678         }
4679         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum2, true))) {
4680                 printf("[8] setting delete_on_close on file failed !\n");
4681                 return False;
4682         }
4683
4684         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
4685                 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
4686                 return False;
4687         }
4688   }
4689 #endif
4690
4691         status = cli_rename(cli1, fname, fname1);
4692         if (!NT_STATUS_IS_OK(status)) {
4693                 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
4694                 correct = False;
4695         } else {
4696                 printf("Third rename succeeded (SHARE_NONE)\n");
4697         }
4698
4699         status = cli_close(cli1, fnum1);
4700         if (!NT_STATUS_IS_OK(status)) {
4701                 printf("close - 3 failed (%s)\n", nt_errstr(status));
4702                 return False;
4703         }
4704
4705         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4706         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4707
4708         /*----*/
4709
4710         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4711                               FILE_ATTRIBUTE_NORMAL,
4712                               FILE_SHARE_READ | FILE_SHARE_WRITE,
4713                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4714         if (!NT_STATUS_IS_OK(status)) {
4715                 printf("Fourth open failed - %s\n", nt_errstr(status));
4716                 return False;
4717         }
4718
4719         status = cli_rename(cli1, fname, fname1);
4720         if (!NT_STATUS_IS_OK(status)) {
4721                 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
4722         } else {
4723                 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
4724                 correct = False;
4725         }
4726
4727         status = cli_close(cli1, fnum1);
4728         if (!NT_STATUS_IS_OK(status)) {
4729                 printf("close - 4 failed (%s)\n", nt_errstr(status));
4730                 return False;
4731         }
4732
4733         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4734         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4735
4736         /*--*/
4737
4738         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4739                          FILE_ATTRIBUTE_NORMAL,
4740                          FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4741                          FILE_OVERWRITE_IF, 0, 0, &fnum1);
4742         if (!NT_STATUS_IS_OK(status)) {
4743                 printf("Fifth open failed - %s\n", nt_errstr(status));
4744                 return False;
4745         }
4746
4747         status = cli_rename(cli1, fname, fname1);
4748         if (!NT_STATUS_IS_OK(status)) {
4749                 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
4750                 correct = False;
4751         } else {
4752                 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
4753         }
4754
4755         /*
4756          * Now check if the first name still exists ...
4757          */
4758
4759         /* if (!NT_STATUS_OP(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4760                                    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4761           printf("Opening original file after rename of open file fails: %s\n",
4762               cli_errstr(cli1));
4763         }
4764         else {
4765           printf("Opening original file after rename of open file works ...\n");
4766           (void)cli_close(cli1, fnum2);
4767           } */
4768
4769         /*--*/
4770         status = cli_close(cli1, fnum1);
4771         if (!NT_STATUS_IS_OK(status)) {
4772                 printf("close - 5 failed (%s)\n", nt_errstr(status));
4773                 return False;
4774         }
4775
4776         /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
4777         status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
4778         if (!NT_STATUS_IS_OK(status)) {
4779                 printf("getatr on file %s failed - %s ! \n",
4780                         fname1, nt_errstr(status));
4781                 correct = False;
4782         } else {
4783                 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
4784                         printf("Renamed file %s has wrong attr 0x%x "
4785                                 "(should be 0x%x)\n",
4786                                 fname1,
4787                                 attr,
4788                                 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
4789                         correct = False;
4790                 } else {
4791                         printf("Renamed file %s has archive bit set\n", fname1);
4792                 }
4793         }
4794
4795         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4796         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4797
4798         if (!torture_close_connection(cli1)) {
4799                 correct = False;
4800         }
4801
4802         return correct;
4803 }
4804
4805 static bool run_pipe_number(int dummy)
4806 {
4807         struct cli_state *cli1;
4808         const char *pipe_name = "\\SPOOLSS";
4809         uint16_t fnum;
4810         int num_pipes = 0;
4811         NTSTATUS status;
4812
4813         printf("starting pipenumber test\n");
4814         if (!torture_open_connection(&cli1, 0)) {
4815                 return False;
4816         }
4817
4818         cli_sockopt(cli1, sockops);
4819         while(1) {
4820                 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
4821                                       FILE_ATTRIBUTE_NORMAL,
4822                                       FILE_SHARE_READ|FILE_SHARE_WRITE,
4823                                       FILE_OPEN_IF, 0, 0, &fnum);
4824                 if (!NT_STATUS_IS_OK(status)) {
4825                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
4826                         break;
4827                 }
4828                 num_pipes++;
4829                 printf("\r%6d", num_pipes);
4830         }
4831
4832         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
4833         torture_close_connection(cli1);
4834         return True;
4835 }
4836
4837 /*
4838   Test open mode returns on read-only files.
4839  */
4840 static bool run_opentest(int dummy)
4841 {
4842         static struct cli_state *cli1;
4843         static struct cli_state *cli2;
4844         const char *fname = "\\readonly.file";
4845         uint16_t fnum1, fnum2;
4846         char buf[20];
4847         SMB_OFF_T fsize;
4848         bool correct = True;
4849         char *tmp_path;
4850         NTSTATUS status;
4851
4852         printf("starting open test\n");
4853
4854         if (!torture_open_connection(&cli1, 0)) {
4855                 return False;
4856         }
4857
4858         cli_setatr(cli1, fname, 0, 0);
4859         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4860
4861         cli_sockopt(cli1, sockops);
4862
4863         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4864         if (!NT_STATUS_IS_OK(status)) {
4865                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4866                 return False;
4867         }
4868
4869         status = cli_close(cli1, fnum1);
4870         if (!NT_STATUS_IS_OK(status)) {
4871                 printf("close2 failed (%s)\n", nt_errstr(status));
4872                 return False;
4873         }
4874
4875         status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
4876         if (!NT_STATUS_IS_OK(status)) {
4877                 printf("cli_setatr failed (%s)\n", nt_errstr(status));
4878                 return False;
4879         }
4880
4881         status = cli_open(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4882         if (!NT_STATUS_IS_OK(status)) {
4883                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4884                 return False;
4885         }
4886
4887         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
4888         status = cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4889
4890         if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
4891                         NT_STATUS_ACCESS_DENIED)) {
4892                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
4893         }
4894
4895         printf("finished open test 1\n");
4896
4897         cli_close(cli1, fnum1);
4898
4899         /* Now try not readonly and ensure ERRbadshare is returned. */
4900
4901         cli_setatr(cli1, fname, 0, 0);
4902
4903         status = cli_open(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4904         if (!NT_STATUS_IS_OK(status)) {
4905                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4906                 return False;
4907         }
4908
4909         /* This will fail - but the error should be ERRshare. */
4910         status = cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4911
4912         if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
4913                         NT_STATUS_SHARING_VIOLATION)) {
4914                 printf("correct error code ERRDOS/ERRbadshare returned\n");
4915         }
4916
4917         status = cli_close(cli1, fnum1);
4918         if (!NT_STATUS_IS_OK(status)) {
4919                 printf("close2 failed (%s)\n", nt_errstr(status));
4920                 return False;
4921         }
4922
4923         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4924
4925         printf("finished open test 2\n");
4926
4927         /* Test truncate open disposition on file opened for read. */
4928         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4929         if (!NT_STATUS_IS_OK(status)) {
4930                 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
4931                 return False;
4932         }
4933
4934         /* write 20 bytes. */
4935
4936         memset(buf, '\0', 20);
4937
4938         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
4939         if (!NT_STATUS_IS_OK(status)) {
4940                 printf("write failed (%s)\n", nt_errstr(status));
4941                 correct = False;
4942         }
4943
4944         status = cli_close(cli1, fnum1);
4945         if (!NT_STATUS_IS_OK(status)) {
4946                 printf("(3) close1 failed (%s)\n", nt_errstr(status));
4947                 return False;
4948         }
4949
4950         /* Ensure size == 20. */
4951         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
4952         if (!NT_STATUS_IS_OK(status)) {
4953                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
4954                 return False;
4955         }
4956
4957         if (fsize != 20) {
4958                 printf("(3) file size != 20\n");
4959                 return False;
4960         }
4961
4962         /* Now test if we can truncate a file opened for readonly. */
4963         status = cli_open(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
4964         if (!NT_STATUS_IS_OK(status)) {
4965                 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
4966                 return False;
4967         }
4968
4969         status = cli_close(cli1, fnum1);
4970         if (!NT_STATUS_IS_OK(status)) {
4971                 printf("close2 failed (%s)\n", nt_errstr(status));
4972                 return False;
4973         }
4974
4975         /* Ensure size == 0. */
4976         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
4977         if (!NT_STATUS_IS_OK(status)) {
4978                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
4979                 return False;
4980         }
4981
4982         if (fsize != 0) {
4983                 printf("(3) file size != 0\n");
4984                 return False;
4985         }
4986         printf("finished open test 3\n");
4987
4988         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4989
4990         printf("Do ctemp tests\n");
4991         status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
4992         if (!NT_STATUS_IS_OK(status)) {
4993                 printf("ctemp failed (%s)\n", nt_errstr(status));
4994                 return False;
4995         }
4996
4997         printf("ctemp gave path %s\n", tmp_path);
4998         status = cli_close(cli1, fnum1);
4999         if (!NT_STATUS_IS_OK(status)) {
5000                 printf("close of temp failed (%s)\n", nt_errstr(status));
5001         }
5002
5003         status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5004         if (!NT_STATUS_IS_OK(status)) {
5005                 printf("unlink of temp failed (%s)\n", nt_errstr(status));
5006         }
5007
5008         /* Test the non-io opens... */
5009
5010         if (!torture_open_connection(&cli2, 1)) {
5011                 return False;
5012         }
5013
5014         cli_setatr(cli2, fname, 0, 0);
5015         cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5016
5017         cli_sockopt(cli2, sockops);
5018
5019         printf("TEST #1 testing 2 non-io opens (no delete)\n");
5020         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5021                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5022                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5023         if (!NT_STATUS_IS_OK(status)) {
5024                 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5025                 return False;
5026         }
5027
5028         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5029                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5030                               FILE_OPEN_IF, 0, 0, &fnum2);
5031         if (!NT_STATUS_IS_OK(status)) {
5032                 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5033                 return False;
5034         }
5035
5036         status = cli_close(cli1, fnum1);
5037         if (!NT_STATUS_IS_OK(status)) {
5038                 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5039                 return False;
5040         }
5041
5042         status = cli_close(cli2, fnum2);
5043         if (!NT_STATUS_IS_OK(status)) {
5044                 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5045                 return False;
5046         }
5047
5048         printf("non-io open test #1 passed.\n");
5049
5050         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5051
5052         printf("TEST #2 testing 2 non-io opens (first with delete)\n");
5053
5054         status = cli_ntcreate(cli1, fname, 0,
5055                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5056                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5057                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5058         if (!NT_STATUS_IS_OK(status)) {
5059                 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5060                 return False;
5061         }
5062
5063         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5064                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5065                               FILE_OPEN_IF, 0, 0, &fnum2);
5066         if (!NT_STATUS_IS_OK(status)) {
5067                 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5068                 return False;
5069         }
5070
5071         status = cli_close(cli1, fnum1);
5072         if (!NT_STATUS_IS_OK(status)) {
5073                 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5074                 return False;
5075         }
5076
5077         status = cli_close(cli2, fnum2);
5078         if (!NT_STATUS_IS_OK(status)) {
5079                 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5080                 return False;
5081         }
5082
5083         printf("non-io open test #2 passed.\n");
5084
5085         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5086
5087         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
5088
5089         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5090                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5091                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5092         if (!NT_STATUS_IS_OK(status)) {
5093                 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5094                 return False;
5095         }
5096
5097         status = cli_ntcreate(cli2, fname, 0,
5098                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5099                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5100                               FILE_OPEN_IF, 0, 0, &fnum2);
5101         if (!NT_STATUS_IS_OK(status)) {
5102                 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5103                 return False;
5104         }
5105
5106         status = cli_close(cli1, fnum1);
5107         if (!NT_STATUS_IS_OK(status)) {
5108                 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5109                 return False;
5110         }
5111
5112         status = cli_close(cli2, fnum2);
5113         if (!NT_STATUS_IS_OK(status)) {
5114                 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5115                 return False;
5116         }
5117
5118         printf("non-io open test #3 passed.\n");
5119
5120         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5121
5122         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
5123
5124         status = cli_ntcreate(cli1, fname, 0,
5125                                DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5126                                FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5127                                FILE_OVERWRITE_IF, 0, 0, &fnum1);
5128         if (!NT_STATUS_IS_OK(status)) {
5129                 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5130                 return False;
5131         }
5132
5133         status = cli_ntcreate(cli2, fname, 0,
5134                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5135                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5136                               FILE_OPEN_IF, 0, 0, &fnum2);
5137         if (NT_STATUS_IS_OK(status)) {
5138                 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5139                 return False;
5140         }
5141
5142         printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5143
5144         status = cli_close(cli1, fnum1);
5145         if (!NT_STATUS_IS_OK(status)) {
5146                 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5147                 return False;
5148         }
5149
5150         printf("non-io open test #4 passed.\n");
5151
5152         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5153
5154         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
5155
5156         status = cli_ntcreate(cli1, fname, 0,
5157                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5158                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5159                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5160         if (!NT_STATUS_IS_OK(status)) {
5161                 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5162                 return False;
5163         }
5164
5165         status = cli_ntcreate(cli2, fname, 0,
5166                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5167                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5168                               FILE_OPEN_IF, 0, 0, &fnum2);
5169         if (!NT_STATUS_IS_OK(status)) {
5170                 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5171                 return False;
5172         }
5173
5174         status = cli_close(cli1, fnum1);
5175         if (!NT_STATUS_IS_OK(status)) {
5176                 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5177                 return False;
5178         }
5179
5180         status = cli_close(cli2, fnum2);
5181         if (!NT_STATUS_IS_OK(status)) {
5182                 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5183                 return False;
5184         }
5185
5186         printf("non-io open test #5 passed.\n");
5187
5188         printf("TEST #6 testing 1 non-io open, one io open\n");
5189
5190         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5191
5192         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5193                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5194                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5195         if (!NT_STATUS_IS_OK(status)) {
5196                 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5197                 return False;
5198         }
5199
5200         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5201                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
5202                               FILE_OPEN_IF, 0, 0, &fnum2);
5203         if (!NT_STATUS_IS_OK(status)) {
5204                 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5205                 return False;
5206         }
5207
5208         status = cli_close(cli1, fnum1);
5209         if (!NT_STATUS_IS_OK(status)) {
5210                 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5211                 return False;
5212         }
5213
5214         status = cli_close(cli2, fnum2);
5215         if (!NT_STATUS_IS_OK(status)) {
5216                 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5217                 return False;
5218         }
5219
5220         printf("non-io open test #6 passed.\n");
5221
5222         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
5223
5224         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5225
5226         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5227                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5228                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5229         if (!NT_STATUS_IS_OK(status)) {
5230                 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5231                 return False;
5232         }
5233
5234         status = cli_ntcreate(cli2, fname, 0,
5235                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5236                               FILE_ATTRIBUTE_NORMAL,
5237                               FILE_SHARE_READ|FILE_SHARE_DELETE,
5238                               FILE_OPEN_IF, 0, 0, &fnum2);
5239         if (NT_STATUS_IS_OK(status)) {
5240                 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5241                 return False;
5242         }
5243
5244         printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5245
5246         status = cli_close(cli1, fnum1);
5247         if (!NT_STATUS_IS_OK(status)) {
5248                 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5249                 return False;
5250         }
5251
5252         printf("non-io open test #7 passed.\n");
5253
5254         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5255
5256         printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
5257         status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
5258                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5259                                 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5260         if (!NT_STATUS_IS_OK(status)) {
5261                 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
5262                 correct = false;
5263                 goto out;
5264         }
5265
5266         /* Write to ensure we have to update the file time. */
5267         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5268                               NULL);
5269         if (!NT_STATUS_IS_OK(status)) {
5270                 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
5271                 correct = false;
5272                 goto out;
5273         }
5274
5275         status = cli_close(cli1, fnum1);
5276         if (!NT_STATUS_IS_OK(status)) {
5277                 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
5278                 correct = false;
5279         }
5280
5281   out:
5282
5283         if (!torture_close_connection(cli1)) {
5284                 correct = False;
5285         }
5286         if (!torture_close_connection(cli2)) {
5287                 correct = False;
5288         }
5289
5290         return correct;
5291 }
5292
5293 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
5294 {
5295         uint16 major, minor;
5296         uint32 caplow, caphigh;
5297         NTSTATUS status;
5298
5299         if (!SERVER_HAS_UNIX_CIFS(cli)) {
5300                 printf("Server doesn't support UNIX CIFS extensions.\n");
5301                 return NT_STATUS_NOT_SUPPORTED;
5302         }
5303
5304         status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
5305                                              &caphigh);
5306         if (!NT_STATUS_IS_OK(status)) {
5307                 printf("Server didn't return UNIX CIFS extensions: %s\n",
5308                        nt_errstr(status));
5309                 return status;
5310         }
5311
5312         status = cli_set_unix_extensions_capabilities(cli, major, minor,
5313                                                       caplow, caphigh);
5314         if (!NT_STATUS_IS_OK(status)) {
5315                 printf("Server doesn't support setting UNIX CIFS extensions: "
5316                        "%s.\n", nt_errstr(status));
5317                 return status;
5318         }
5319
5320         return NT_STATUS_OK;
5321 }
5322
5323 /*
5324   Test POSIX open /mkdir calls.
5325  */
5326 static bool run_simple_posix_open_test(int dummy)
5327 {
5328         static struct cli_state *cli1;
5329         const char *fname = "posix:file";
5330         const char *hname = "posix:hlink";
5331         const char *sname = "posix:symlink";
5332         const char *dname = "posix:dir";
5333         char buf[10];
5334         char namebuf[11];
5335         uint16_t fnum1 = (uint16_t)-1;
5336         SMB_STRUCT_STAT sbuf;
5337         bool correct = false;
5338         NTSTATUS status;
5339         size_t nread;
5340
5341         printf("Starting simple POSIX open test\n");
5342
5343         if (!torture_open_connection(&cli1, 0)) {
5344                 return false;
5345         }
5346
5347         cli_sockopt(cli1, sockops);
5348
5349         status = torture_setup_unix_extensions(cli1);
5350         if (!NT_STATUS_IS_OK(status)) {
5351                 return false;
5352         }
5353
5354         cli_setatr(cli1, fname, 0, 0);
5355         cli_posix_unlink(cli1, fname);
5356         cli_setatr(cli1, dname, 0, 0);
5357         cli_posix_rmdir(cli1, dname);
5358         cli_setatr(cli1, hname, 0, 0);
5359         cli_posix_unlink(cli1, hname);
5360         cli_setatr(cli1, sname, 0, 0);
5361         cli_posix_unlink(cli1, sname);
5362
5363         /* Create a directory. */
5364         status = cli_posix_mkdir(cli1, dname, 0777);
5365         if (!NT_STATUS_IS_OK(status)) {
5366                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
5367                 goto out;
5368         }
5369
5370         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5371                                 0600, &fnum1);
5372         if (!NT_STATUS_IS_OK(status)) {
5373                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5374                 goto out;
5375         }
5376
5377         /* Test ftruncate - set file size. */
5378         status = cli_ftruncate(cli1, fnum1, 1000);
5379         if (!NT_STATUS_IS_OK(status)) {
5380                 printf("ftruncate failed (%s)\n", nt_errstr(status));
5381                 goto out;
5382         }
5383
5384         /* Ensure st_size == 1000 */
5385         status = cli_posix_stat(cli1, fname, &sbuf);
5386         if (!NT_STATUS_IS_OK(status)) {
5387                 printf("stat failed (%s)\n", nt_errstr(status));
5388                 goto out;
5389         }
5390
5391         if (sbuf.st_ex_size != 1000) {
5392                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5393                 goto out;
5394         }
5395
5396         /* Test ftruncate - set file size back to zero. */
5397         status = cli_ftruncate(cli1, fnum1, 0);
5398         if (!NT_STATUS_IS_OK(status)) {
5399                 printf("ftruncate failed (%s)\n", nt_errstr(status));
5400                 goto out;
5401         }
5402
5403         status = cli_close(cli1, fnum1);
5404         if (!NT_STATUS_IS_OK(status)) {
5405                 printf("close failed (%s)\n", nt_errstr(status));
5406                 goto out;
5407         }
5408
5409         /* Now open the file again for read only. */
5410         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5411         if (!NT_STATUS_IS_OK(status)) {
5412                 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
5413                 goto out;
5414         }
5415
5416         /* Now unlink while open. */
5417         status = cli_posix_unlink(cli1, fname);
5418         if (!NT_STATUS_IS_OK(status)) {
5419                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5420                 goto out;
5421         }
5422
5423         status = cli_close(cli1, fnum1);
5424         if (!NT_STATUS_IS_OK(status)) {
5425                 printf("close(2) failed (%s)\n", nt_errstr(status));
5426                 goto out;
5427         }
5428
5429         /* Ensure the file has gone. */
5430         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5431         if (NT_STATUS_IS_OK(status)) {
5432                 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
5433                 goto out;
5434         }
5435
5436         /* Create again to test open with O_TRUNC. */
5437         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
5438         if (!NT_STATUS_IS_OK(status)) {
5439                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5440                 goto out;
5441         }
5442
5443         /* Test ftruncate - set file size. */
5444         status = cli_ftruncate(cli1, fnum1, 1000);
5445         if (!NT_STATUS_IS_OK(status)) {
5446                 printf("ftruncate failed (%s)\n", nt_errstr(status));
5447                 goto out;
5448         }
5449
5450         /* Ensure st_size == 1000 */
5451         status = cli_posix_stat(cli1, fname, &sbuf);
5452         if (!NT_STATUS_IS_OK(status)) {
5453                 printf("stat failed (%s)\n", nt_errstr(status));
5454                 goto out;
5455         }
5456
5457         if (sbuf.st_ex_size != 1000) {
5458                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5459                 goto out;
5460         }
5461
5462         status = cli_close(cli1, fnum1);
5463         if (!NT_STATUS_IS_OK(status)) {
5464                 printf("close(2) failed (%s)\n", nt_errstr(status));
5465                 goto out;
5466         }
5467
5468         /* Re-open with O_TRUNC. */
5469         status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
5470         if (!NT_STATUS_IS_OK(status)) {
5471                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5472                 goto out;
5473         }
5474
5475         /* Ensure st_size == 0 */
5476         status = cli_posix_stat(cli1, fname, &sbuf);
5477         if (!NT_STATUS_IS_OK(status)) {
5478                 printf("stat failed (%s)\n", nt_errstr(status));
5479                 goto out;
5480         }
5481
5482         if (sbuf.st_ex_size != 0) {
5483                 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
5484                 goto out;
5485         }
5486
5487         status = cli_close(cli1, fnum1);
5488         if (!NT_STATUS_IS_OK(status)) {
5489                 printf("close failed (%s)\n", nt_errstr(status));
5490                 goto out;
5491         }
5492
5493         status = cli_posix_unlink(cli1, fname);
5494         if (!NT_STATUS_IS_OK(status)) {
5495                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5496                 goto out;
5497         }
5498
5499         status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
5500         if (!NT_STATUS_IS_OK(status)) {
5501                 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
5502                         dname, nt_errstr(status));
5503                 goto out;
5504         }
5505
5506         cli_close(cli1, fnum1);
5507
5508         /* What happens when we try and POSIX open a directory for write ? */
5509         status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
5510         if (NT_STATUS_IS_OK(status)) {
5511                 printf("POSIX open of directory %s succeeded, should have failed.\n", fname);
5512                 goto out;
5513         } else {
5514                 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
5515                                 NT_STATUS_FILE_IS_A_DIRECTORY)) {
5516                         goto out;
5517                 }
5518         }
5519
5520         /* Create the file. */
5521         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5522                                 0600, &fnum1);
5523         if (!NT_STATUS_IS_OK(status)) {
5524                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5525                 goto out;
5526         }
5527
5528         /* Write some data into it. */
5529         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5530                               NULL);
5531         if (!NT_STATUS_IS_OK(status)) {
5532                 printf("cli_write failed: %s\n", nt_errstr(status));
5533                 goto out;
5534         }
5535
5536         cli_close(cli1, fnum1);
5537
5538         /* Now create a hardlink. */
5539         status = cli_posix_hardlink(cli1, fname, hname);
5540         if (!NT_STATUS_IS_OK(status)) {
5541                 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
5542                 goto out;
5543         }
5544
5545         /* Now create a symlink. */
5546         status = cli_posix_symlink(cli1, fname, sname);
5547         if (!NT_STATUS_IS_OK(status)) {
5548                 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
5549                 goto out;
5550         }
5551
5552         /* Open the hardlink for read. */
5553         status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
5554         if (!NT_STATUS_IS_OK(status)) {
5555                 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
5556                 goto out;
5557         }
5558
5559         status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
5560         if (!NT_STATUS_IS_OK(status)) {
5561                 printf("POSIX read of %s failed (%s)\n", hname,
5562                        nt_errstr(status));
5563                 goto out;
5564         } else if (nread != 10) {
5565                 printf("POSIX read of %s failed. Received %ld, expected %d\n",
5566                        hname, (unsigned long)nread, 10);
5567                 goto out;
5568         }
5569
5570         if (memcmp(buf, "TEST DATA\n", 10)) {
5571                 printf("invalid data read from hardlink\n");
5572                 goto out;
5573         }
5574
5575         /* Do a POSIX lock/unlock. */
5576         status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
5577         if (!NT_STATUS_IS_OK(status)) {
5578                 printf("POSIX lock failed %s\n", nt_errstr(status));
5579                 goto out;
5580         }
5581
5582         /* Punch a hole in the locked area. */
5583         status = cli_posix_unlock(cli1, fnum1, 10, 80);
5584         if (!NT_STATUS_IS_OK(status)) {
5585                 printf("POSIX unlock failed %s\n", nt_errstr(status));
5586                 goto out;
5587         }
5588
5589         cli_close(cli1, fnum1);
5590
5591         /* Open the symlink for read - this should fail. A POSIX
5592            client should not be doing opens on a symlink. */
5593         status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
5594         if (NT_STATUS_IS_OK(status)) {
5595                 printf("POSIX open of %s succeeded (should have failed)\n", sname);
5596                 goto out;
5597         } else {
5598                 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
5599                                 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
5600                         printf("POSIX open of %s should have failed "
5601                                 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
5602                                 "failed with %s instead.\n",
5603                                 sname, nt_errstr(status));
5604                         goto out;
5605                 }
5606         }
5607
5608         status = cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf));
5609         if (!NT_STATUS_IS_OK(status)) {
5610                 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
5611                 goto out;
5612         }
5613
5614         if (strcmp(namebuf, fname) != 0) {
5615                 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
5616                         sname, fname, namebuf);
5617                 goto out;
5618         }
5619
5620         status = cli_posix_rmdir(cli1, dname);
5621         if (!NT_STATUS_IS_OK(status)) {
5622                 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
5623                 goto out;
5624         }
5625
5626         printf("Simple POSIX open test passed\n");
5627         correct = true;
5628
5629   out:
5630
5631         if (fnum1 != (uint16_t)-1) {
5632                 cli_close(cli1, fnum1);
5633                 fnum1 = (uint16_t)-1;
5634         }
5635
5636         cli_setatr(cli1, sname, 0, 0);
5637         cli_posix_unlink(cli1, sname);
5638         cli_setatr(cli1, hname, 0, 0);
5639         cli_posix_unlink(cli1, hname);
5640         cli_setatr(cli1, fname, 0, 0);
5641         cli_posix_unlink(cli1, fname);
5642         cli_setatr(cli1, dname, 0, 0);
5643         cli_posix_rmdir(cli1, dname);
5644
5645         if (!torture_close_connection(cli1)) {
5646                 correct = false;
5647         }
5648
5649         return correct;
5650 }
5651
5652
5653 static uint32 open_attrs_table[] = {
5654                 FILE_ATTRIBUTE_NORMAL,
5655                 FILE_ATTRIBUTE_ARCHIVE,
5656                 FILE_ATTRIBUTE_READONLY,
5657                 FILE_ATTRIBUTE_HIDDEN,
5658                 FILE_ATTRIBUTE_SYSTEM,
5659
5660                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
5661                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
5662                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
5663                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5664                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5665                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5666
5667                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5668                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5669                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5670                 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
5671 };
5672
5673 struct trunc_open_results {
5674         unsigned int num;
5675         uint32 init_attr;
5676         uint32 trunc_attr;
5677         uint32 result_attr;
5678 };
5679
5680 static struct trunc_open_results attr_results[] = {
5681         { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5682         { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5683         { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5684         { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5685         { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5686         { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5687         { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5688         { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5689         { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5690         { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5691         { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5692         { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
5693         { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5694         { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5695         { 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 },
5696         { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5697         { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5698         { 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 },
5699         { 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 },
5700         { 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 },
5701         { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5702         { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5703         { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5704         { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5705         { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5706         { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
5707 };
5708
5709 static bool run_openattrtest(int dummy)
5710 {
5711         static struct cli_state *cli1;
5712         const char *fname = "\\openattr.file";
5713         uint16_t fnum1;
5714         bool correct = True;
5715         uint16 attr;
5716         unsigned int i, j, k, l;
5717         NTSTATUS status;
5718
5719         printf("starting open attr test\n");
5720
5721         if (!torture_open_connection(&cli1, 0)) {
5722                 return False;
5723         }
5724
5725         cli_sockopt(cli1, sockops);
5726
5727         for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32); i++) {
5728                 cli_setatr(cli1, fname, 0, 0);
5729                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5730
5731                 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
5732                                        open_attrs_table[i], FILE_SHARE_NONE,
5733                                        FILE_OVERWRITE_IF, 0, 0, &fnum1);
5734                 if (!NT_STATUS_IS_OK(status)) {
5735                         printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5736                         return False;
5737                 }
5738
5739                 status = cli_close(cli1, fnum1);
5740                 if (!NT_STATUS_IS_OK(status)) {
5741                         printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5742                         return False;
5743                 }
5744
5745                 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32); j++) {
5746                         status = cli_ntcreate(cli1, fname, 0,
5747                                               FILE_READ_DATA|FILE_WRITE_DATA,
5748                                               open_attrs_table[j],
5749                                               FILE_SHARE_NONE, FILE_OVERWRITE,
5750                                               0, 0, &fnum1);
5751                         if (!NT_STATUS_IS_OK(status)) {
5752                                 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5753                                         if (attr_results[l].num == k) {
5754                                                 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
5755                                                                 k, open_attrs_table[i],
5756                                                                 open_attrs_table[j],
5757                                                                 fname, NT_STATUS_V(status), nt_errstr(status));
5758                                                 correct = False;
5759                                         }
5760                                 }
5761
5762                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5763                                         printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
5764                                                         k, open_attrs_table[i], open_attrs_table[j],
5765                                                         nt_errstr(status));
5766                                         correct = False;
5767                                 }
5768 #if 0
5769                                 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
5770 #endif
5771                                 k++;
5772                                 continue;
5773                         }
5774
5775                         status = cli_close(cli1, fnum1);
5776                         if (!NT_STATUS_IS_OK(status)) {
5777                                 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
5778                                 return False;
5779                         }
5780
5781                         status = cli_getatr(cli1, fname, &attr, NULL, NULL);
5782                         if (!NT_STATUS_IS_OK(status)) {
5783                                 printf("getatr(2) failed (%s)\n", nt_errstr(status));
5784                                 return False;
5785                         }
5786
5787 #if 0
5788                         printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
5789                                         k,  open_attrs_table[i],  open_attrs_table[j], attr );
5790 #endif
5791
5792                         for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5793                                 if (attr_results[l].num == k) {
5794                                         if (attr != attr_results[l].result_attr ||
5795                                                         open_attrs_table[i] != attr_results[l].init_attr ||
5796                                                         open_attrs_table[j] != attr_results[l].trunc_attr) {
5797                                                 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
5798                                                 open_attrs_table[i],
5799                                                 open_attrs_table[j],
5800                                                 (unsigned int)attr,
5801                                                 attr_results[l].result_attr);
5802                                                 correct = False;
5803                                         }
5804                                         break;
5805                                 }
5806                         }
5807                         k++;
5808                 }
5809         }
5810
5811         cli_setatr(cli1, fname, 0, 0);
5812         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5813
5814         printf("open attr test %s.\n", correct ? "passed" : "failed");
5815
5816         if (!torture_close_connection(cli1)) {
5817                 correct = False;
5818         }
5819         return correct;
5820 }
5821
5822 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
5823                     const char *name, void *state)
5824 {
5825         int *matched = (int *)state;
5826         if (matched != NULL) {
5827                 *matched += 1;
5828         }
5829         return NT_STATUS_OK;
5830 }
5831
5832 /*
5833   test directory listing speed
5834  */
5835 static bool run_dirtest(int dummy)
5836 {
5837         int i;
5838         static struct cli_state *cli;
5839         uint16_t fnum;
5840         struct timeval core_start;
5841         bool correct = True;
5842         int matched;
5843
5844         printf("starting directory test\n");
5845
5846         if (!torture_open_connection(&cli, 0)) {
5847                 return False;
5848         }
5849
5850         cli_sockopt(cli, sockops);
5851
5852         srandom(0);
5853         for (i=0;i<torture_numops;i++) {
5854                 fstring fname;
5855                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5856                 if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
5857                         fprintf(stderr,"Failed to open %s\n", fname);
5858                         return False;
5859                 }
5860                 cli_close(cli, fnum);
5861         }
5862
5863         core_start = timeval_current();
5864
5865         matched = 0;
5866         cli_list(cli, "a*.*", 0, list_fn, &matched);
5867         printf("Matched %d\n", matched);
5868
5869         matched = 0;
5870         cli_list(cli, "b*.*", 0, list_fn, &matched);
5871         printf("Matched %d\n", matched);
5872
5873         matched = 0;
5874         cli_list(cli, "xyzabc", 0, list_fn, &matched);
5875         printf("Matched %d\n", matched);
5876
5877         printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
5878
5879         srandom(0);
5880         for (i=0;i<torture_numops;i++) {
5881                 fstring fname;
5882                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5883                 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5884         }
5885
5886         if (!torture_close_connection(cli)) {
5887                 correct = False;
5888         }
5889
5890         printf("finished dirtest\n");
5891
5892         return correct;
5893 }
5894
5895 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
5896                    void *state)
5897 {
5898         struct cli_state *pcli = (struct cli_state *)state;
5899         fstring fname;
5900         slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
5901
5902         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
5903                 return NT_STATUS_OK;
5904
5905         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
5906                 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
5907                         printf("del_fn: failed to rmdir %s\n,", fname );
5908         } else {
5909                 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
5910                         printf("del_fn: failed to unlink %s\n,", fname );
5911         }
5912         return NT_STATUS_OK;
5913 }
5914
5915
5916 /*
5917   sees what IOCTLs are supported
5918  */
5919 bool torture_ioctl_test(int dummy)
5920 {
5921         static struct cli_state *cli;
5922         uint16_t device, function;
5923         uint16_t fnum;
5924         const char *fname = "\\ioctl.dat";
5925         DATA_BLOB blob;
5926         NTSTATUS status;
5927
5928         if (!torture_open_connection(&cli, 0)) {
5929                 return False;
5930         }
5931
5932         printf("starting ioctl test\n");
5933
5934         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5935
5936         status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5937         if (!NT_STATUS_IS_OK(status)) {
5938                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5939                 return False;
5940         }
5941
5942         status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
5943         printf("ioctl device info: %s\n", nt_errstr(status));
5944
5945         status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
5946         printf("ioctl job info: %s\n", nt_errstr(status));
5947
5948         for (device=0;device<0x100;device++) {
5949                 printf("ioctl test with device = 0x%x\n", device);
5950                 for (function=0;function<0x100;function++) {
5951                         uint32 code = (device<<16) | function;
5952
5953                         status = cli_raw_ioctl(cli, fnum, code, &blob);
5954
5955                         if (NT_STATUS_IS_OK(status)) {
5956                                 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
5957                                        (int)blob.length);
5958                                 data_blob_free(&blob);
5959                         }
5960                 }
5961         }
5962
5963         if (!torture_close_connection(cli)) {
5964                 return False;
5965         }
5966
5967         return True;
5968 }
5969
5970
5971 /*
5972   tries varients of chkpath
5973  */
5974 bool torture_chkpath_test(int dummy)
5975 {
5976         static struct cli_state *cli;
5977         uint16_t fnum;
5978         bool ret;
5979         NTSTATUS status;
5980
5981         if (!torture_open_connection(&cli, 0)) {
5982                 return False;
5983         }
5984
5985         printf("starting chkpath test\n");
5986
5987         /* cleanup from an old run */
5988         cli_rmdir(cli, "\\chkpath.dir\\dir2");
5989         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5990         cli_rmdir(cli, "\\chkpath.dir");
5991
5992         status = cli_mkdir(cli, "\\chkpath.dir");
5993         if (!NT_STATUS_IS_OK(status)) {
5994                 printf("mkdir1 failed : %s\n", nt_errstr(status));
5995                 return False;
5996         }
5997
5998         status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
5999         if (!NT_STATUS_IS_OK(status)) {
6000                 printf("mkdir2 failed : %s\n", nt_errstr(status));
6001                 return False;
6002         }
6003
6004         status = cli_open(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
6005                           DENY_NONE, &fnum);
6006         if (!NT_STATUS_IS_OK(status)) {
6007                 printf("open1 failed (%s)\n", nt_errstr(status));
6008                 return False;
6009         }
6010         cli_close(cli, fnum);
6011
6012         status = cli_chkpath(cli, "\\chkpath.dir");
6013         if (!NT_STATUS_IS_OK(status)) {
6014                 printf("chkpath1 failed: %s\n", nt_errstr(status));
6015                 ret = False;
6016         }
6017
6018         status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
6019         if (!NT_STATUS_IS_OK(status)) {
6020                 printf("chkpath2 failed: %s\n", nt_errstr(status));
6021                 ret = False;
6022         }
6023
6024         status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
6025         if (!NT_STATUS_IS_OK(status)) {
6026                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
6027                                   NT_STATUS_NOT_A_DIRECTORY);
6028         } else {
6029                 printf("* chkpath on a file should fail\n");
6030                 ret = False;
6031         }
6032
6033         status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
6034         if (!NT_STATUS_IS_OK(status)) {
6035                 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
6036                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
6037         } else {
6038                 printf("* chkpath on a non existant file should fail\n");
6039                 ret = False;
6040         }
6041
6042         status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
6043         if (!NT_STATUS_IS_OK(status)) {
6044                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
6045                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
6046         } else {
6047                 printf("* chkpath on a non existent component should fail\n");
6048                 ret = False;
6049         }
6050
6051         cli_rmdir(cli, "\\chkpath.dir\\dir2");
6052         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6053         cli_rmdir(cli, "\\chkpath.dir");
6054
6055         if (!torture_close_connection(cli)) {
6056                 return False;
6057         }
6058
6059         return ret;
6060 }
6061
6062 static bool run_eatest(int dummy)
6063 {
6064         static struct cli_state *cli;
6065         const char *fname = "\\eatest.txt";
6066         bool correct = True;
6067         uint16_t fnum;
6068         int i;
6069         size_t num_eas;
6070         struct ea_struct *ea_list = NULL;
6071         TALLOC_CTX *mem_ctx = talloc_init("eatest");
6072         NTSTATUS status;
6073
6074         printf("starting eatest\n");
6075
6076         if (!torture_open_connection(&cli, 0)) {
6077                 talloc_destroy(mem_ctx);
6078                 return False;
6079         }
6080
6081         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6082
6083         status = cli_ntcreate(cli, fname, 0,
6084                               FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6085                               FILE_SHARE_NONE, FILE_OVERWRITE_IF,
6086                               0x4044, 0, &fnum);
6087         if (!NT_STATUS_IS_OK(status)) {
6088                 printf("open failed - %s\n", nt_errstr(status));
6089                 talloc_destroy(mem_ctx);
6090                 return False;
6091         }
6092
6093         for (i = 0; i < 10; i++) {
6094                 fstring ea_name, ea_val;
6095
6096                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
6097                 memset(ea_val, (char)i+1, i+1);
6098                 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
6099                 if (!NT_STATUS_IS_OK(status)) {
6100                         printf("ea_set of name %s failed - %s\n", ea_name,
6101                                nt_errstr(status));
6102                         talloc_destroy(mem_ctx);
6103                         return False;
6104                 }
6105         }
6106
6107         cli_close(cli, fnum);
6108         for (i = 0; i < 10; i++) {
6109                 fstring ea_name, ea_val;
6110
6111                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
6112                 memset(ea_val, (char)i+1, i+1);
6113                 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
6114                 if (!NT_STATUS_IS_OK(status)) {
6115                         printf("ea_set of name %s failed - %s\n", ea_name,
6116                                nt_errstr(status));
6117                         talloc_destroy(mem_ctx);
6118                         return False;
6119                 }
6120         }
6121
6122         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6123         if (!NT_STATUS_IS_OK(status)) {
6124                 printf("ea_get list failed - %s\n", nt_errstr(status));
6125                 correct = False;
6126         }
6127
6128         printf("num_eas = %d\n", (int)num_eas);
6129
6130         if (num_eas != 20) {
6131                 printf("Should be 20 EA's stored... failing.\n");
6132                 correct = False;
6133         }
6134
6135         for (i = 0; i < num_eas; i++) {
6136                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6137                 dump_data(0, ea_list[i].value.data,
6138                           ea_list[i].value.length);
6139         }
6140
6141         /* Setting EA's to zero length deletes them. Test this */
6142         printf("Now deleting all EA's - case indepenent....\n");
6143
6144 #if 1
6145         cli_set_ea_path(cli, fname, "", "", 0);
6146 #else
6147         for (i = 0; i < 20; i++) {
6148                 fstring ea_name;
6149                 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
6150                 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
6151                 if (!NT_STATUS_IS_OK(status)) {
6152                         printf("ea_set of name %s failed - %s\n", ea_name,
6153                                nt_errstr(status));
6154                         talloc_destroy(mem_ctx);
6155                         return False;
6156                 }
6157         }
6158 #endif
6159
6160         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6161         if (!NT_STATUS_IS_OK(status)) {
6162                 printf("ea_get list failed - %s\n", nt_errstr(status));
6163                 correct = False;
6164         }
6165
6166         printf("num_eas = %d\n", (int)num_eas);
6167         for (i = 0; i < num_eas; i++) {
6168                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6169                 dump_data(0, ea_list[i].value.data,
6170                           ea_list[i].value.length);
6171         }
6172
6173         if (num_eas != 0) {
6174                 printf("deleting EA's failed.\n");
6175                 correct = False;
6176         }
6177
6178         /* Try and delete a non existant EA. */
6179         status = cli_set_ea_path(cli, fname, "foo", "", 0);
6180         if (!NT_STATUS_IS_OK(status)) {
6181                 printf("deleting non-existant EA 'foo' should succeed. %s\n",
6182                        nt_errstr(status));
6183                 correct = False;
6184         }
6185
6186         talloc_destroy(mem_ctx);
6187         if (!torture_close_connection(cli)) {
6188                 correct = False;
6189         }
6190
6191         return correct;
6192 }
6193
6194 static bool run_dirtest1(int dummy)
6195 {
6196         int i;
6197         static struct cli_state *cli;
6198         uint16_t fnum;
6199         int num_seen;
6200         bool correct = True;
6201
6202         printf("starting directory test\n");
6203
6204         if (!torture_open_connection(&cli, 0)) {
6205                 return False;
6206         }
6207
6208         cli_sockopt(cli, sockops);
6209
6210         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6211         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6212         cli_rmdir(cli, "\\LISTDIR");
6213         cli_mkdir(cli, "\\LISTDIR");
6214
6215         /* Create 1000 files and 1000 directories. */
6216         for (i=0;i<1000;i++) {
6217                 fstring fname;
6218                 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
6219                 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6220                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum))) {
6221                         fprintf(stderr,"Failed to open %s\n", fname);
6222                         return False;
6223                 }
6224                 cli_close(cli, fnum);
6225         }
6226         for (i=0;i<1000;i++) {
6227                 fstring fname;
6228                 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
6229                 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
6230                         fprintf(stderr,"Failed to open %s\n", fname);
6231                         return False;
6232                 }
6233         }
6234
6235         /* Now ensure that doing an old list sees both files and directories. */
6236         num_seen = 0;
6237         cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6238         printf("num_seen = %d\n", num_seen );
6239         /* We should see 100 files + 1000 directories + . and .. */
6240         if (num_seen != 2002)
6241                 correct = False;
6242
6243         /* Ensure if we have the "must have" bits we only see the
6244          * relevent entries.
6245          */
6246         num_seen = 0;
6247         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6248         printf("num_seen = %d\n", num_seen );
6249         if (num_seen != 1002)
6250                 correct = False;
6251
6252         num_seen = 0;
6253         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6254         printf("num_seen = %d\n", num_seen );
6255         if (num_seen != 1000)
6256                 correct = False;
6257
6258         /* Delete everything. */
6259         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6260         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6261         cli_rmdir(cli, "\\LISTDIR");
6262
6263 #if 0
6264         printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
6265         printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
6266         printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
6267 #endif
6268
6269         if (!torture_close_connection(cli)) {
6270                 correct = False;
6271         }
6272
6273         printf("finished dirtest1\n");
6274
6275         return correct;
6276 }
6277
6278 static bool run_error_map_extract(int dummy) {
6279
6280         static struct cli_state *c_dos;
6281         static struct cli_state *c_nt;
6282         NTSTATUS status;
6283
6284         uint32 error;
6285
6286         uint32 errnum;
6287         uint8 errclass;
6288
6289         NTSTATUS nt_status;
6290
6291         fstring user;
6292
6293         /* NT-Error connection */
6294
6295         if (!(c_nt = open_nbt_connection())) {
6296                 return False;
6297         }
6298
6299         c_nt->use_spnego = False;
6300
6301         status = cli_negprot(c_nt);
6302
6303         if (!NT_STATUS_IS_OK(status)) {
6304                 printf("%s rejected the NT-error negprot (%s)\n", host,
6305                        nt_errstr(status));
6306                 cli_shutdown(c_nt);
6307                 return False;
6308         }
6309
6310         status = cli_session_setup(c_nt, "", "", 0, "", 0, workgroup);
6311         if (!NT_STATUS_IS_OK(status)) {
6312                 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
6313                 return False;
6314         }
6315
6316         /* DOS-Error connection */
6317
6318         force_dos_errors = true;
6319         if (!(c_dos = open_nbt_connection())) {
6320                 force_dos_errors = false;
6321                 return False;
6322         }
6323         force_dos_errors = false;
6324
6325         c_dos->use_spnego = 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         {NULL, NULL, 0}};
8866
8867
8868
8869 /****************************************************************************
8870 run a specified test or "ALL"
8871 ****************************************************************************/
8872 static bool run_test(const char *name)
8873 {
8874         bool ret = True;
8875         bool result = True;
8876         bool found = False;
8877         int i;
8878         double t;
8879         if (strequal(name,"ALL")) {
8880                 for (i=0;torture_ops[i].name;i++) {
8881                         run_test(torture_ops[i].name);
8882                 }
8883                 found = True;
8884         }
8885
8886         for (i=0;torture_ops[i].name;i++) {
8887                 fstr_sprintf(randomfname, "\\XX%x", 
8888                          (unsigned)random());
8889
8890                 if (strequal(name, torture_ops[i].name)) {
8891                         found = True;
8892                         printf("Running %s\n", name);
8893                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
8894                                 t = create_procs(torture_ops[i].fn, &result);
8895                                 if (!result) { 
8896                                         ret = False;
8897                                         printf("TEST %s FAILED!\n", name);
8898                                 }
8899                         } else {
8900                                 struct timeval start;
8901                                 start = timeval_current();
8902                                 if (!torture_ops[i].fn(0)) {
8903                                         ret = False;
8904                                         printf("TEST %s FAILED!\n", name);
8905                                 }
8906                                 t = timeval_elapsed(&start);
8907                         }
8908                         printf("%s took %g secs\n\n", name, t);
8909                 }
8910         }
8911
8912         if (!found) {
8913                 printf("Did not find a test named %s\n", name);
8914                 ret = False;
8915         }
8916
8917         return ret;
8918 }
8919
8920
8921 static void usage(void)
8922 {
8923         int i;
8924
8925         printf("WARNING samba4 test suite is much more complete nowadays.\n");
8926         printf("Please use samba4 torture.\n\n");
8927
8928         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
8929
8930         printf("\t-d debuglevel\n");
8931         printf("\t-U user%%pass\n");
8932         printf("\t-k               use kerberos\n");
8933         printf("\t-N numprocs\n");
8934         printf("\t-n my_netbios_name\n");
8935         printf("\t-W workgroup\n");
8936         printf("\t-o num_operations\n");
8937         printf("\t-O socket_options\n");
8938         printf("\t-m maximum protocol\n");
8939         printf("\t-L use oplocks\n");
8940         printf("\t-c CLIENT.TXT   specify client load file for NBENCH\n");
8941         printf("\t-A showall\n");
8942         printf("\t-p port\n");
8943         printf("\t-s seed\n");
8944         printf("\t-b unclist_filename   specify multiple shares for multiple connections\n");
8945         printf("\t-f filename   filename to test\n");
8946         printf("\n\n");
8947
8948         printf("tests are:");
8949         for (i=0;torture_ops[i].name;i++) {
8950                 printf(" %s", torture_ops[i].name);
8951         }
8952         printf("\n");
8953
8954         printf("default test is ALL\n");
8955
8956         exit(1);
8957 }
8958
8959 /****************************************************************************
8960   main program
8961 ****************************************************************************/
8962  int main(int argc,char *argv[])
8963 {
8964         int opt, i;
8965         char *p;
8966         int gotuser = 0;
8967         int gotpass = 0;
8968         bool correct = True;
8969         TALLOC_CTX *frame = talloc_stackframe();
8970         int seed = time(NULL);
8971
8972 #ifdef HAVE_SETBUFFER
8973         setbuffer(stdout, NULL, 0);
8974 #endif
8975
8976         setup_logging("smbtorture", DEBUG_STDOUT);
8977
8978         load_case_tables();
8979
8980         if (is_default_dyn_CONFIGFILE()) {
8981                 if(getenv("SMB_CONF_PATH")) {
8982                         set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
8983                 }
8984         }
8985         lp_load_global(get_dyn_CONFIGFILE());
8986         load_interfaces();
8987
8988         if (argc < 2) {
8989                 usage();
8990         }
8991
8992         for(p = argv[1]; *p; p++)
8993           if(*p == '\\')
8994             *p = '/';
8995
8996         if (strncmp(argv[1], "//", 2)) {
8997                 usage();
8998         }
8999
9000         fstrcpy(host, &argv[1][2]);
9001         p = strchr_m(&host[2],'/');
9002         if (!p) {
9003                 usage();
9004         }
9005         *p = 0;
9006         fstrcpy(share, p+1);
9007
9008         fstrcpy(myname, get_myname(talloc_tos()));
9009         if (!*myname) {
9010                 fprintf(stderr, "Failed to get my hostname.\n");
9011                 return 1;
9012         }
9013
9014         if (*username == 0 && getenv("LOGNAME")) {
9015           fstrcpy(username,getenv("LOGNAME"));
9016         }
9017
9018         argc--;
9019         argv++;
9020
9021         fstrcpy(workgroup, lp_workgroup());
9022
9023         while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
9024                != EOF) {
9025                 switch (opt) {
9026                 case 'p':
9027                         port_to_use = atoi(optarg);
9028                         break;
9029                 case 's':
9030                         seed = atoi(optarg);
9031                         break;
9032                 case 'W':
9033                         fstrcpy(workgroup,optarg);
9034                         break;
9035                 case 'm':
9036                         max_protocol = interpret_protocol(optarg, max_protocol);
9037                         break;
9038                 case 'N':
9039                         nprocs = atoi(optarg);
9040                         break;
9041                 case 'o':
9042                         torture_numops = atoi(optarg);
9043                         break;
9044                 case 'd':
9045                         lp_set_cmdline("log level", optarg);
9046                         break;
9047                 case 'O':
9048                         sockops = optarg;
9049                         break;
9050                 case 'L':
9051                         use_oplocks = True;
9052                         break;
9053                 case 'l':
9054                         local_path = optarg;
9055                         break;
9056                 case 'A':
9057                         torture_showall = True;
9058                         break;
9059                 case 'n':
9060                         fstrcpy(myname, optarg);
9061                         break;
9062                 case 'c':
9063                         client_txt = optarg;
9064                         break;
9065                 case 'e':
9066                         do_encrypt = true;
9067                         break;
9068                 case 'k':
9069 #ifdef HAVE_KRB5
9070                         use_kerberos = True;
9071 #else
9072                         d_printf("No kerberos support compiled in\n");
9073                         exit(1);
9074 #endif
9075                         break;
9076                 case 'U':
9077                         gotuser = 1;
9078                         fstrcpy(username,optarg);
9079                         p = strchr_m(username,'%');
9080                         if (p) {
9081                                 *p = 0;
9082                                 fstrcpy(password, p+1);
9083                                 gotpass = 1;
9084                         }
9085                         break;
9086                 case 'b':
9087                         fstrcpy(multishare_conn_fname, optarg);
9088                         use_multishare_conn = True;
9089                         break;
9090                 case 'B':
9091                         torture_blocksize = atoi(optarg);
9092                         break;
9093                 case 'f':
9094                         test_filename = SMB_STRDUP(optarg);
9095                         break;
9096                 default:
9097                         printf("Unknown option %c (%d)\n", (char)opt, opt);
9098                         usage();
9099                 }
9100         }
9101
9102         d_printf("using seed %d\n", seed);
9103
9104         srandom(seed);
9105
9106         if(use_kerberos && !gotuser) gotpass = True;
9107
9108         while (!gotpass) {
9109                 p = getpass("Password:");
9110                 if (p) {
9111                         fstrcpy(password, p);
9112                         gotpass = 1;
9113                 }
9114         }
9115
9116         printf("host=%s share=%s user=%s myname=%s\n", 
9117                host, share, username, myname);
9118
9119         if (argc == optind) {
9120                 correct = run_test("ALL");
9121         } else {
9122                 for (i=optind;i<argc;i++) {
9123                         if (!run_test(argv[i])) {
9124                                 correct = False;
9125                         }
9126                 }
9127         }
9128
9129         TALLOC_FREE(frame);
9130
9131         if (correct) {
9132                 return(0);
9133         } else {
9134                 return(1);
9135         }
9136 }