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