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