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