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