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