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