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