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