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