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