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