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