s3:libsmb: get rid of cli_negprot
[mat/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         smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_OK);
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 = smbXcli_negprot_send(ev, ev, cli->conn, cli->timeout,
3057                                            PROTOCOL_CORE, PROTOCOL_NT1);
3058                 if (req == NULL) {
3059                         TALLOC_FREE(ev);
3060                         return false;
3061                 }
3062                 if (!tevent_req_poll(req, ev)) {
3063                         d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3064                                   strerror(errno));
3065                         TALLOC_FREE(ev);
3066                         return false;
3067                 }
3068                 TALLOC_FREE(req);
3069         }
3070
3071         if (torture_close_connection(cli)) {
3072                 correct = False;
3073         }
3074
3075         printf("finished negprot nowait test\n");
3076
3077         return correct;
3078 }
3079
3080 /* send smb negprot commands, not reading the response */
3081 static bool run_bad_nbt_session(int dummy)
3082 {
3083         struct nmb_name called, calling;
3084         struct sockaddr_storage ss;
3085         NTSTATUS status;
3086         int fd;
3087         bool ret;
3088
3089         printf("starting bad nbt session test\n");
3090
3091         make_nmb_name(&calling, myname, 0x0);
3092         make_nmb_name(&called , host, 0x20);
3093
3094         if (!resolve_name(host, &ss, 0x20, true)) {
3095                 d_fprintf(stderr, "Could not resolve name %s\n", host);
3096                 return false;
3097         }
3098
3099         status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
3100         if (!NT_STATUS_IS_OK(status)) {
3101                 d_fprintf(stderr, "open_socket_out failed: %s\n",
3102                           nt_errstr(status));
3103                 return false;
3104         }
3105
3106         ret = cli_bad_session_request(fd, &calling, &called);
3107         close(fd);
3108         if (!ret) {
3109                 d_fprintf(stderr, "open_socket_out failed: %s\n",
3110                           nt_errstr(status));
3111                 return false;
3112         }
3113
3114         printf("finished bad nbt session test\n");
3115         return true;
3116 }
3117
3118 /* send random IPC commands */
3119 static bool run_randomipc(int dummy)
3120 {
3121         char *rparam = NULL;
3122         char *rdata = NULL;
3123         unsigned int rdrcnt,rprcnt;
3124         char param[1024];
3125         int api, param_len, i;
3126         struct cli_state *cli;
3127         bool correct = True;
3128         int count = 50000;
3129
3130         printf("starting random ipc test\n");
3131
3132         if (!torture_open_connection(&cli, 0)) {
3133                 return False;
3134         }
3135
3136         for (i=0;i<count;i++) {
3137                 api = sys_random() % 500;
3138                 param_len = (sys_random() % 64);
3139
3140                 rand_buf(param, param_len);
3141
3142                 SSVAL(param,0,api); 
3143
3144                 cli_api(cli, 
3145                         param, param_len, 8,  
3146                         NULL, 0, BUFFER_SIZE, 
3147                         &rparam, &rprcnt,     
3148                         &rdata, &rdrcnt);
3149                 if (i % 100 == 0) {
3150                         printf("%d/%d\r", i,count);
3151                 }
3152         }
3153         printf("%d/%d\n", i, count);
3154
3155         if (!torture_close_connection(cli)) {
3156                 correct = False;
3157         }
3158
3159         printf("finished random ipc test\n");
3160
3161         return correct;
3162 }
3163
3164
3165
3166 static void browse_callback(const char *sname, uint32 stype, 
3167                             const char *comment, void *state)
3168 {
3169         printf("\t%20.20s %08x %s\n", sname, stype, comment);
3170 }
3171
3172
3173
3174 /*
3175   This test checks the browse list code
3176
3177 */
3178 static bool run_browsetest(int dummy)
3179 {
3180         static struct cli_state *cli;
3181         bool correct = True;
3182
3183         printf("starting browse test\n");
3184
3185         if (!torture_open_connection(&cli, 0)) {
3186                 return False;
3187         }
3188
3189         printf("domain list:\n");
3190         cli_NetServerEnum(cli, cli->server_domain, 
3191                           SV_TYPE_DOMAIN_ENUM,
3192                           browse_callback, NULL);
3193
3194         printf("machine list:\n");
3195         cli_NetServerEnum(cli, cli->server_domain, 
3196                           SV_TYPE_ALL,
3197                           browse_callback, NULL);
3198
3199         if (!torture_close_connection(cli)) {
3200                 correct = False;
3201         }
3202
3203         printf("browse test finished\n");
3204
3205         return correct;
3206
3207 }
3208
3209
3210 /*
3211   This checks how the getatr calls works
3212 */
3213 static bool run_attrtest(int dummy)
3214 {
3215         struct cli_state *cli;
3216         uint16_t fnum;
3217         time_t t, t2;
3218         const char *fname = "\\attrib123456789.tst";
3219         bool correct = True;
3220         NTSTATUS status;
3221
3222         printf("starting attrib test\n");
3223
3224         if (!torture_open_connection(&cli, 0)) {
3225                 return False;
3226         }
3227
3228         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3229         cli_openx(cli, fname, 
3230                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3231         cli_close(cli, fnum);
3232
3233         status = cli_getatr(cli, fname, NULL, NULL, &t);
3234         if (!NT_STATUS_IS_OK(status)) {
3235                 printf("getatr failed (%s)\n", nt_errstr(status));
3236                 correct = False;
3237         }
3238
3239         if (abs(t - time(NULL)) > 60*60*24*10) {
3240                 printf("ERROR: SMBgetatr bug. time is %s",
3241                        ctime(&t));
3242                 t = time(NULL);
3243                 correct = True;
3244         }
3245
3246         t2 = t-60*60*24; /* 1 day ago */
3247
3248         status = cli_setatr(cli, fname, 0, t2);
3249         if (!NT_STATUS_IS_OK(status)) {
3250                 printf("setatr failed (%s)\n", nt_errstr(status));
3251                 correct = True;
3252         }
3253
3254         status = cli_getatr(cli, fname, NULL, NULL, &t);
3255         if (!NT_STATUS_IS_OK(status)) {
3256                 printf("getatr failed (%s)\n", nt_errstr(status));
3257                 correct = True;
3258         }
3259
3260         if (t != t2) {
3261                 printf("ERROR: getatr/setatr bug. times are\n%s",
3262                        ctime(&t));
3263                 printf("%s", ctime(&t2));
3264                 correct = True;
3265         }
3266
3267         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3268
3269         if (!torture_close_connection(cli)) {
3270                 correct = False;
3271         }
3272
3273         printf("attrib test finished\n");
3274
3275         return correct;
3276 }
3277
3278
3279 /*
3280   This checks a couple of trans2 calls
3281 */
3282 static bool run_trans2test(int dummy)
3283 {
3284         struct cli_state *cli;
3285         uint16_t fnum;
3286         off_t size;
3287         time_t c_time, a_time, m_time;
3288         struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
3289         const char *fname = "\\trans2.tst";
3290         const char *dname = "\\trans2";
3291         const char *fname2 = "\\trans2\\trans2.tst";
3292         char *pname;
3293         bool correct = True;
3294         NTSTATUS status;
3295         uint32_t fs_attr;
3296
3297         printf("starting trans2 test\n");
3298
3299         if (!torture_open_connection(&cli, 0)) {
3300                 return False;
3301         }
3302
3303         status = cli_get_fs_attr_info(cli, &fs_attr);
3304         if (!NT_STATUS_IS_OK(status)) {
3305                 printf("ERROR: cli_get_fs_attr_info returned %s\n",
3306                        nt_errstr(status));
3307                 correct = false;
3308         }
3309
3310         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3311         cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3312         status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
3313                                      &a_time_ts, &w_time_ts, &m_time_ts, NULL);
3314         if (!NT_STATUS_IS_OK(status)) {
3315                 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
3316                 correct = False;
3317         }
3318
3319         status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
3320         if (!NT_STATUS_IS_OK(status)) {
3321                 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
3322                 correct = False;
3323         }
3324
3325         if (strcmp(pname, fname)) {
3326                 printf("qfilename gave different name? [%s] [%s]\n",
3327                        fname, pname);
3328                 correct = False;
3329         }
3330
3331         cli_close(cli, fnum);
3332
3333         sleep(2);
3334
3335         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3336         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
3337                           &fnum);
3338         if (!NT_STATUS_IS_OK(status)) {
3339                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3340                 return False;
3341         }
3342         cli_close(cli, fnum);
3343
3344         status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
3345                                 NULL);
3346         if (!NT_STATUS_IS_OK(status)) {
3347                 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
3348                 correct = False;
3349         } else {
3350                 time_t t = time(NULL);
3351
3352                 if (c_time != m_time) {
3353                         printf("create time=%s", ctime(&c_time));
3354                         printf("modify time=%s", ctime(&m_time));
3355                         printf("This system appears to have sticky create times\n");
3356                 }
3357                 if ((abs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
3358                         printf("access time=%s", ctime(&a_time));
3359                         printf("This system appears to set a midnight access time\n");
3360                         correct = False;
3361                 }
3362
3363                 if (abs(m_time - t) > 60*60*24*7) {
3364                         printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
3365                         correct = False;
3366                 }
3367         }
3368
3369
3370         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3371         cli_openx(cli, fname, 
3372                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3373         cli_close(cli, fnum);
3374         status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
3375                                 &m_time_ts, &size, NULL, NULL);
3376         if (!NT_STATUS_IS_OK(status)) {
3377                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3378                 correct = False;
3379         } else {
3380                 if (w_time_ts.tv_sec < 60*60*24*2) {
3381                         printf("write time=%s", ctime(&w_time_ts.tv_sec));
3382                         printf("This system appears to set a initial 0 write time\n");
3383                         correct = False;
3384                 }
3385         }
3386
3387         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3388
3389
3390         /* check if the server updates the directory modification time
3391            when creating a new file */
3392         status = cli_mkdir(cli, dname);
3393         if (!NT_STATUS_IS_OK(status)) {
3394                 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
3395                 correct = False;
3396         }
3397         sleep(3);
3398         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3399                                 &w_time_ts, &m_time_ts, &size, NULL, NULL);
3400         if (!NT_STATUS_IS_OK(status)) {
3401                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3402                 correct = False;
3403         }
3404
3405         cli_openx(cli, fname2, 
3406                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3407         cli_writeall(cli, fnum,  0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
3408         cli_close(cli, fnum);
3409         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3410                                 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
3411         if (!NT_STATUS_IS_OK(status)) {
3412                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3413                 correct = False;
3414         } else {
3415                 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
3416                     == 0) {
3417                         printf("This system does not update directory modification times\n");
3418                         correct = False;
3419                 }
3420         }
3421         cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3422         cli_rmdir(cli, dname);
3423
3424         if (!torture_close_connection(cli)) {
3425                 correct = False;
3426         }
3427
3428         printf("trans2 test finished\n");
3429
3430         return correct;
3431 }
3432
3433 /*
3434   This checks new W2K calls.
3435 */
3436
3437 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
3438 {
3439         uint8_t *buf = NULL;
3440         uint32 len;
3441         NTSTATUS status;
3442
3443         status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
3444                                CLI_BUFFER_SIZE, NULL, &buf, &len);
3445         if (!NT_STATUS_IS_OK(status)) {
3446                 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
3447                        nt_errstr(status));
3448         } else {
3449                 printf("qfileinfo: level %d, len = %u\n", level, len);
3450                 dump_data(0, (uint8 *)buf, len);
3451                 printf("\n");
3452         }
3453         TALLOC_FREE(buf);
3454         return status;
3455 }
3456
3457 static bool run_w2ktest(int dummy)
3458 {
3459         struct cli_state *cli;
3460         uint16_t fnum;
3461         const char *fname = "\\w2ktest\\w2k.tst";
3462         int level;
3463         bool correct = True;
3464
3465         printf("starting w2k test\n");
3466
3467         if (!torture_open_connection(&cli, 0)) {
3468                 return False;
3469         }
3470
3471         cli_openx(cli, fname, 
3472                         O_RDWR | O_CREAT , DENY_NONE, &fnum);
3473
3474         for (level = 1004; level < 1040; level++) {
3475                 new_trans(cli, fnum, level);
3476         }
3477
3478         cli_close(cli, fnum);
3479
3480         if (!torture_close_connection(cli)) {
3481                 correct = False;
3482         }
3483
3484         printf("w2k test finished\n");
3485
3486         return correct;
3487 }
3488
3489
3490 /*
3491   this is a harness for some oplock tests
3492  */
3493 static bool run_oplock1(int dummy)
3494 {
3495         struct cli_state *cli1;
3496         const char *fname = "\\lockt1.lck";
3497         uint16_t fnum1;
3498         bool correct = True;
3499         NTSTATUS status;
3500
3501         printf("starting oplock test 1\n");
3502
3503         if (!torture_open_connection(&cli1, 0)) {
3504                 return False;
3505         }
3506
3507         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3508
3509         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3510
3511         cli1->use_oplocks = True;
3512
3513         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3514                           &fnum1);
3515         if (!NT_STATUS_IS_OK(status)) {
3516                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3517                 return False;
3518         }
3519
3520         cli1->use_oplocks = False;
3521
3522         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3523         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3524
3525         status = cli_close(cli1, fnum1);
3526         if (!NT_STATUS_IS_OK(status)) {
3527                 printf("close2 failed (%s)\n", nt_errstr(status));
3528                 return False;
3529         }
3530
3531         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3532         if (!NT_STATUS_IS_OK(status)) {
3533                 printf("unlink failed (%s)\n", nt_errstr(status));
3534                 return False;
3535         }
3536
3537         if (!torture_close_connection(cli1)) {
3538                 correct = False;
3539         }
3540
3541         printf("finished oplock test 1\n");
3542
3543         return correct;
3544 }
3545
3546 static bool run_oplock2(int dummy)
3547 {
3548         struct cli_state *cli1, *cli2;
3549         const char *fname = "\\lockt2.lck";
3550         uint16_t fnum1, fnum2;
3551         int saved_use_oplocks = use_oplocks;
3552         char buf[4];
3553         bool correct = True;
3554         volatile bool *shared_correct;
3555         size_t nread;
3556         NTSTATUS status;
3557
3558         shared_correct = (volatile bool *)shm_setup(sizeof(bool));
3559         *shared_correct = True;
3560
3561         use_level_II_oplocks = True;
3562         use_oplocks = True;
3563
3564         printf("starting oplock test 2\n");
3565
3566         if (!torture_open_connection(&cli1, 0)) {
3567                 use_level_II_oplocks = False;
3568                 use_oplocks = saved_use_oplocks;
3569                 return False;
3570         }
3571
3572         if (!torture_open_connection(&cli2, 1)) {
3573                 use_level_II_oplocks = False;
3574                 use_oplocks = saved_use_oplocks;
3575                 return False;
3576         }
3577
3578         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3579
3580         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3581         smbXcli_conn_set_sockopt(cli2->conn, sockops);
3582
3583         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3584                           &fnum1);
3585         if (!NT_STATUS_IS_OK(status)) {
3586                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3587                 return False;
3588         }
3589
3590         /* Don't need the globals any more. */
3591         use_level_II_oplocks = False;
3592         use_oplocks = saved_use_oplocks;
3593
3594         if (fork() == 0) {
3595                 /* Child code */
3596                 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
3597                 if (!NT_STATUS_IS_OK(status)) {
3598                         printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
3599                         *shared_correct = False;
3600                         exit(0);
3601                 }
3602
3603                 sleep(2);
3604
3605                 status = cli_close(cli2, fnum2);
3606                 if (!NT_STATUS_IS_OK(status)) {
3607                         printf("close2 failed (%s)\n", nt_errstr(status));
3608                         *shared_correct = False;
3609                 }
3610
3611                 exit(0);
3612         }
3613
3614         sleep(2);
3615
3616         /* Ensure cli1 processes the break. Empty file should always return 0
3617          * bytes.  */
3618         status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
3619         if (!NT_STATUS_IS_OK(status)) {
3620                 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
3621                 correct = false;
3622         } else if (nread != 0) {
3623                 printf("read on empty fnum1 failed. recv %ld expected %d\n",
3624                       (unsigned long)nread, 0);
3625                 correct = false;
3626         }
3627
3628         /* Should now be at level II. */
3629         /* Test if sending a write locks causes a break to none. */
3630         status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
3631         if (!NT_STATUS_IS_OK(status)) {
3632                 printf("lock failed (%s)\n", nt_errstr(status));
3633                 correct = False;
3634         }
3635
3636         cli_unlock(cli1, fnum1, 0, 4);
3637
3638         sleep(2);
3639
3640         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
3641         if (!NT_STATUS_IS_OK(status)) {
3642                 printf("lock failed (%s)\n", nt_errstr(status));
3643                 correct = False;
3644         }
3645
3646         cli_unlock(cli1, fnum1, 0, 4);
3647
3648         sleep(2);
3649
3650         cli_read(cli1, fnum1, buf, 0, 4, NULL);
3651
3652         status = cli_close(cli1, fnum1);
3653         if (!NT_STATUS_IS_OK(status)) {
3654                 printf("close1 failed (%s)\n", nt_errstr(status));
3655                 correct = False;
3656         }
3657
3658         sleep(4);
3659
3660         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3661         if (!NT_STATUS_IS_OK(status)) {
3662                 printf("unlink failed (%s)\n", nt_errstr(status));
3663                 correct = False;
3664         }
3665
3666         if (!torture_close_connection(cli1)) {
3667                 correct = False;
3668         }
3669
3670         if (!*shared_correct) {
3671                 correct = False;
3672         }
3673
3674         printf("finished oplock test 2\n");
3675
3676         return correct;
3677 }
3678
3679 struct oplock4_state {
3680         struct tevent_context *ev;
3681         struct cli_state *cli;
3682         bool *got_break;
3683         uint16_t *fnum2;
3684 };
3685
3686 static void oplock4_got_break(struct tevent_req *req);
3687 static void oplock4_got_open(struct tevent_req *req);
3688
3689 static bool run_oplock4(int dummy)
3690 {
3691         struct tevent_context *ev;
3692         struct cli_state *cli1, *cli2;
3693         struct tevent_req *oplock_req, *open_req;
3694         const char *fname = "\\lockt4.lck";
3695         const char *fname_ln = "\\lockt4_ln.lck";
3696         uint16_t fnum1, fnum2;
3697         int saved_use_oplocks = use_oplocks;
3698         NTSTATUS status;
3699         bool correct = true;
3700
3701         bool got_break;
3702
3703         struct oplock4_state *state;
3704
3705         printf("starting oplock test 4\n");
3706
3707         if (!torture_open_connection(&cli1, 0)) {
3708                 use_level_II_oplocks = false;
3709                 use_oplocks = saved_use_oplocks;
3710                 return false;
3711         }
3712
3713         if (!torture_open_connection(&cli2, 1)) {
3714                 use_level_II_oplocks = false;
3715                 use_oplocks = saved_use_oplocks;
3716                 return false;
3717         }
3718
3719         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3720         cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3721
3722         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3723         smbXcli_conn_set_sockopt(cli2->conn, sockops);
3724
3725         /* Create the file. */
3726         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3727                           &fnum1);
3728         if (!NT_STATUS_IS_OK(status)) {
3729                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3730                 return false;
3731         }
3732
3733         status = cli_close(cli1, fnum1);
3734         if (!NT_STATUS_IS_OK(status)) {
3735                 printf("close1 failed (%s)\n", nt_errstr(status));
3736                 return false;
3737         }
3738
3739         /* Now create a hardlink. */
3740         status = cli_nt_hardlink(cli1, fname, fname_ln);
3741         if (!NT_STATUS_IS_OK(status)) {
3742                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
3743                 return false;
3744         }
3745
3746         /* Prove that opening hardlinks cause deny modes to conflict. */
3747         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
3748         if (!NT_STATUS_IS_OK(status)) {
3749                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3750                 return false;
3751         }
3752
3753         status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
3754         if (NT_STATUS_IS_OK(status)) {
3755                 printf("open of %s succeeded - should fail with sharing violation.\n",
3756                         fname_ln);
3757                 return false;
3758         }
3759
3760         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3761                 printf("open of %s should fail with sharing violation. Got %s\n",
3762                         fname_ln, nt_errstr(status));
3763                 return false;
3764         }
3765
3766         status = cli_close(cli1, fnum1);
3767         if (!NT_STATUS_IS_OK(status)) {
3768                 printf("close1 failed (%s)\n", nt_errstr(status));
3769                 return false;
3770         }
3771
3772         cli1->use_oplocks = true;
3773         cli2->use_oplocks = true;
3774
3775         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3776         if (!NT_STATUS_IS_OK(status)) {
3777                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3778                 return false;
3779         }
3780
3781         ev = tevent_context_init(talloc_tos());
3782         if (ev == NULL) {
3783                 printf("tevent_context_init failed\n");
3784                 return false;
3785         }
3786
3787         state = talloc(ev, struct oplock4_state);
3788         if (state == NULL) {
3789                 printf("talloc failed\n");
3790                 return false;
3791         }
3792         state->ev = ev;
3793         state->cli = cli1;
3794         state->got_break = &got_break;
3795         state->fnum2 = &fnum2;
3796
3797         oplock_req = cli_smb_oplock_break_waiter_send(
3798                 talloc_tos(), ev, cli1);
3799         if (oplock_req == NULL) {
3800                 printf("cli_smb_oplock_break_waiter_send failed\n");
3801                 return false;
3802         }
3803         tevent_req_set_callback(oplock_req, oplock4_got_break, state);
3804
3805         open_req = cli_openx_send(
3806                 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
3807         if (open_req == NULL) {
3808                 printf("cli_openx_send failed\n");
3809                 return false;
3810         }
3811         tevent_req_set_callback(open_req, oplock4_got_open, state);
3812
3813         got_break = false;
3814         fnum2 = 0xffff;
3815
3816         while (!got_break || fnum2 == 0xffff) {
3817                 int ret;
3818                 ret = tevent_loop_once(ev);
3819                 if (ret == -1) {
3820                         printf("tevent_loop_once failed: %s\n",
3821                                strerror(errno));
3822                         return false;
3823                 }
3824         }
3825
3826         status = cli_close(cli2, fnum2);
3827         if (!NT_STATUS_IS_OK(status)) {
3828                 printf("close2 failed (%s)\n", nt_errstr(status));
3829                 correct = false;
3830         }
3831
3832         status = cli_close(cli1, fnum1);
3833         if (!NT_STATUS_IS_OK(status)) {
3834                 printf("close1 failed (%s)\n", nt_errstr(status));
3835                 correct = false;
3836         }
3837
3838         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3839         if (!NT_STATUS_IS_OK(status)) {
3840                 printf("unlink failed (%s)\n", nt_errstr(status));
3841                 correct = false;
3842         }
3843
3844         status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3845         if (!NT_STATUS_IS_OK(status)) {
3846                 printf("unlink failed (%s)\n", nt_errstr(status));
3847                 correct = false;
3848         }
3849
3850         if (!torture_close_connection(cli1)) {
3851                 correct = false;
3852         }
3853
3854         if (!got_break) {
3855                 correct = false;
3856         }
3857
3858         printf("finished oplock test 4\n");
3859
3860         return correct;
3861 }
3862
3863 static void oplock4_got_break(struct tevent_req *req)
3864 {
3865         struct oplock4_state *state = tevent_req_callback_data(
3866                 req, struct oplock4_state);
3867         uint16_t fnum;
3868         uint8_t level;
3869         NTSTATUS status;
3870
3871         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
3872         TALLOC_FREE(req);
3873         if (!NT_STATUS_IS_OK(status)) {
3874                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
3875                        nt_errstr(status));
3876                 return;
3877         }
3878         *state->got_break = true;
3879
3880         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
3881                                   NO_OPLOCK);
3882         if (req == NULL) {
3883                 printf("cli_oplock_ack_send failed\n");
3884                 return;
3885         }
3886 }
3887
3888 static void oplock4_got_open(struct tevent_req *req)
3889 {
3890         struct oplock4_state *state = tevent_req_callback_data(
3891                 req, struct oplock4_state);
3892         NTSTATUS status;
3893
3894         status = cli_openx_recv(req, state->fnum2);
3895         if (!NT_STATUS_IS_OK(status)) {
3896                 printf("cli_openx_recv returned %s\n", nt_errstr(status));
3897                 *state->fnum2 = 0xffff;
3898         }
3899 }
3900
3901 /*
3902   Test delete on close semantics.
3903  */
3904 static bool run_deletetest(int dummy)
3905 {
3906         struct cli_state *cli1 = NULL;
3907         struct cli_state *cli2 = NULL;
3908         const char *fname = "\\delete.file";
3909         uint16_t fnum1 = (uint16_t)-1;
3910         uint16_t fnum2 = (uint16_t)-1;
3911         bool correct = True;
3912         NTSTATUS status;
3913
3914         printf("starting delete test\n");
3915
3916         if (!torture_open_connection(&cli1, 0)) {
3917                 return False;
3918         }
3919
3920         smbXcli_conn_set_sockopt(cli1->conn, sockops);
3921
3922         /* Test 1 - this should delete the file on close. */
3923
3924         cli_setatr(cli1, fname, 0, 0);
3925         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3926
3927         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
3928                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
3929                               FILE_DELETE_ON_CLOSE, 0, &fnum1);
3930         if (!NT_STATUS_IS_OK(status)) {
3931                 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
3932                 correct = False;
3933                 goto fail;
3934         }
3935
3936         status = cli_close(cli1, fnum1);
3937         if (!NT_STATUS_IS_OK(status)) {
3938                 printf("[1] close failed (%s)\n", nt_errstr(status));
3939                 correct = False;
3940                 goto fail;
3941         }
3942
3943         if (NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1))) {
3944                 printf("[1] open of %s succeeded (should fail)\n", fname);
3945                 correct = False;
3946                 goto fail;
3947         }
3948
3949         printf("first delete on close test succeeded.\n");
3950
3951         /* Test 2 - this should delete the file on close. */
3952
3953         cli_setatr(cli1, fname, 0, 0);
3954         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3955
3956         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3957                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
3958                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
3959         if (!NT_STATUS_IS_OK(status)) {
3960                 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
3961                 correct = False;
3962                 goto fail;
3963         }
3964
3965         status = cli_nt_delete_on_close(cli1, fnum1, true);
3966         if (!NT_STATUS_IS_OK(status)) {
3967                 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
3968                 correct = False;
3969                 goto fail;
3970         }
3971
3972         status = cli_close(cli1, fnum1);
3973         if (!NT_STATUS_IS_OK(status)) {
3974                 printf("[2] close failed (%s)\n", nt_errstr(status));
3975                 correct = False;
3976                 goto fail;
3977         }
3978
3979         if (NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3980                 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
3981                 status = cli_close(cli1, fnum1);
3982                 if (!NT_STATUS_IS_OK(status)) {
3983                         printf("[2] close failed (%s)\n", nt_errstr(status));
3984                         correct = False;
3985                         goto fail;
3986                 }
3987                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3988         } else
3989                 printf("second delete on close test succeeded.\n");
3990
3991         /* Test 3 - ... */
3992         cli_setatr(cli1, fname, 0, 0);
3993         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3994
3995         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3996                               FILE_ATTRIBUTE_NORMAL,
3997                               FILE_SHARE_READ|FILE_SHARE_WRITE,
3998                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
3999         if (!NT_STATUS_IS_OK(status)) {
4000                 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
4001                 correct = False;
4002                 goto fail;
4003         }
4004
4005         /* This should fail with a sharing violation - open for delete is only compatible
4006            with SHARE_DELETE. */
4007
4008         if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4009                         FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, 0, &fnum2))) {
4010                 printf("[3] open  - 2 of %s succeeded - should have failed.\n", fname);
4011                 correct = False;
4012                 goto fail;
4013         }
4014
4015         /* This should succeed. */
4016         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4017                              FILE_ATTRIBUTE_NORMAL,
4018                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4019                              FILE_OPEN, 0, 0, &fnum2);
4020         if (!NT_STATUS_IS_OK(status)) {
4021                 printf("[3] open  - 2 of %s failed (%s)\n", fname, nt_errstr(status));
4022                 correct = False;
4023                 goto fail;
4024         }
4025
4026         status = cli_nt_delete_on_close(cli1, fnum1, true);
4027         if (!NT_STATUS_IS_OK(status)) {
4028                 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
4029                 correct = False;
4030                 goto fail;
4031         }
4032
4033         status = cli_close(cli1, fnum1);
4034         if (!NT_STATUS_IS_OK(status)) {
4035                 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
4036                 correct = False;
4037                 goto fail;
4038         }
4039
4040         status = cli_close(cli1, fnum2);
4041         if (!NT_STATUS_IS_OK(status)) {
4042                 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
4043                 correct = False;
4044                 goto fail;
4045         }
4046
4047         /* This should fail - file should no longer be there. */
4048
4049         if (NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
4050                 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
4051                 status = cli_close(cli1, fnum1);
4052                 if (!NT_STATUS_IS_OK(status)) {
4053                         printf("[3] close failed (%s)\n", nt_errstr(status));
4054                 }
4055                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4056                 correct = False;
4057                 goto fail;
4058         } else
4059                 printf("third delete on close test succeeded.\n");
4060
4061         /* Test 4 ... */
4062         cli_setatr(cli1, fname, 0, 0);
4063         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4064
4065         status = cli_ntcreate(cli1, fname, 0,
4066                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4067                               FILE_ATTRIBUTE_NORMAL,
4068                               FILE_SHARE_READ|FILE_SHARE_WRITE,
4069                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4070         if (!NT_STATUS_IS_OK(status)) {
4071                 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
4072                 correct = False;
4073                 goto fail;
4074         }
4075
4076         /* This should succeed. */
4077         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4078                              FILE_ATTRIBUTE_NORMAL,
4079                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4080                              FILE_OPEN, 0, 0, &fnum2);
4081         if (!NT_STATUS_IS_OK(status)) {
4082                 printf("[4] open  - 2 of %s failed (%s)\n", fname, nt_errstr(status));
4083                 correct = False;
4084                 goto fail;
4085         }
4086
4087         status = cli_close(cli1, fnum2);
4088         if (!NT_STATUS_IS_OK(status)) {
4089                 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
4090                 correct = False;
4091                 goto fail;
4092         }
4093
4094         status = cli_nt_delete_on_close(cli1, fnum1, true);
4095         if (!NT_STATUS_IS_OK(status)) {
4096                 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
4097                 correct = False;
4098                 goto fail;
4099         }
4100
4101         /* This should fail - no more opens once delete on close set. */
4102         if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4103                                    FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4104                                    FILE_OPEN, 0, 0, &fnum2))) {
4105                 printf("[4] open  - 3 of %s succeeded ! Should have failed.\n", fname );
4106                 correct = False;
4107                 goto fail;
4108         } else
4109                 printf("fourth delete on close test succeeded.\n");
4110
4111         status = cli_close(cli1, fnum1);
4112         if (!NT_STATUS_IS_OK(status)) {
4113                 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
4114                 correct = False;
4115                 goto fail;
4116         }
4117
4118         /* Test 5 ... */
4119         cli_setatr(cli1, fname, 0, 0);
4120         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4121
4122         status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
4123         if (!NT_STATUS_IS_OK(status)) {
4124                 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4125                 correct = False;
4126                 goto fail;
4127         }
4128
4129         /* This should fail - only allowed on NT opens with DELETE access. */
4130
4131         if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4132                 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
4133                 correct = False;
4134                 goto fail;
4135         }
4136
4137         status = cli_close(cli1, fnum1);
4138         if (!NT_STATUS_IS_OK(status)) {
4139                 printf("[5] close - 2 failed (%s)\n", nt_errstr(status));
4140                 correct = False;
4141                 goto fail;
4142         }
4143
4144         printf("fifth delete on close test succeeded.\n");
4145
4146         /* Test 6 ... */
4147         cli_setatr(cli1, fname, 0, 0);
4148         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4149
4150         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4151                              FILE_ATTRIBUTE_NORMAL,
4152                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4153                              FILE_OVERWRITE_IF, 0, 0, &fnum1);
4154         if (!NT_STATUS_IS_OK(status)) {
4155                 printf("[6] open of %s failed (%s)\n", fname,
4156                        nt_errstr(status));
4157                 correct = False;
4158                 goto fail;
4159         }
4160
4161         /* This should fail - only allowed on NT opens with DELETE access. */
4162
4163         if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4164                 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
4165                 correct = False;
4166                 goto fail;
4167         }
4168
4169         status = cli_close(cli1, fnum1);
4170         if (!NT_STATUS_IS_OK(status)) {
4171                 printf("[6] close - 2 failed (%s)\n", nt_errstr(status));
4172                 correct = False;
4173                 goto fail;
4174         }
4175
4176         printf("sixth delete on close test succeeded.\n");
4177
4178         /* Test 7 ... */
4179         cli_setatr(cli1, fname, 0, 0);
4180         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4181
4182         status = cli_ntcreate(cli1, fname, 0,
4183                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4184                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
4185                               0, 0, &fnum1);
4186         if (!NT_STATUS_IS_OK(status)) {
4187                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4188                 correct = False;
4189                 goto fail;
4190         }
4191
4192         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4193                 printf("[7] setting delete_on_close on file failed !\n");
4194                 correct = False;
4195                 goto fail;
4196         }
4197
4198         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, false))) {
4199                 printf("[7] unsetting delete_on_close on file failed !\n");
4200                 correct = False;
4201                 goto fail;
4202         }
4203
4204         status = cli_close(cli1, fnum1);
4205         if (!NT_STATUS_IS_OK(status)) {
4206                 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4207                 correct = False;
4208                 goto fail;
4209         }
4210
4211         /* This next open should succeed - we reset the flag. */
4212         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4213         if (!NT_STATUS_IS_OK(status)) {
4214                 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4215                 correct = False;
4216                 goto fail;
4217         }
4218
4219         status = cli_close(cli1, fnum1);
4220         if (!NT_STATUS_IS_OK(status)) {
4221                 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4222                 correct = False;
4223                 goto fail;
4224         }
4225
4226         printf("seventh delete on close test succeeded.\n");
4227
4228         /* Test 7 ... */
4229         cli_setatr(cli1, fname, 0, 0);
4230         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4231
4232         if (!torture_open_connection(&cli2, 1)) {
4233                 printf("[8] failed to open second connection.\n");
4234                 correct = False;
4235                 goto fail;
4236         }
4237
4238         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4239
4240         status = cli_ntcreate(cli1, fname, 0,
4241                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4242                              FILE_ATTRIBUTE_NORMAL,
4243                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4244                              FILE_OVERWRITE_IF, 0, 0, &fnum1);
4245         if (!NT_STATUS_IS_OK(status)) {
4246                 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4247                 correct = False;
4248                 goto fail;
4249         }
4250
4251         status = cli_ntcreate(cli2, fname, 0,
4252                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4253                              FILE_ATTRIBUTE_NORMAL,
4254                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4255                              FILE_OPEN, 0, 0, &fnum2);
4256         if (!NT_STATUS_IS_OK(status)) {
4257                 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4258                 correct = False;
4259                 goto fail;
4260         }
4261
4262         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4263                 printf("[8] setting delete_on_close on file failed !\n");
4264                 correct = False;
4265                 goto fail;
4266         }
4267
4268         status = cli_close(cli1, fnum1);
4269         if (!NT_STATUS_IS_OK(status)) {
4270                 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
4271                 correct = False;
4272                 goto fail;
4273         }
4274
4275         status = cli_close(cli2, fnum2);
4276         if (!NT_STATUS_IS_OK(status)) {
4277                 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
4278                 correct = False;
4279                 goto fail;
4280         }
4281
4282         /* This should fail.. */
4283         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4284         if (NT_STATUS_IS_OK(status)) {
4285                 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
4286                 goto fail;
4287                 correct = False;
4288         } else
4289                 printf("eighth delete on close test succeeded.\n");
4290
4291         /* This should fail - we need to set DELETE_ACCESS. */
4292         if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0,FILE_READ_DATA|FILE_WRITE_DATA,
4293                                    FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE, 0, &fnum1))) {
4294                 printf("[9] open of %s succeeded should have failed!\n", fname);
4295                 correct = False;
4296                 goto fail;
4297         }
4298
4299         printf("ninth delete on close test succeeded.\n");
4300
4301         status = cli_ntcreate(cli1, fname, 0,
4302                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4303                              FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4304                              FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
4305                              0, &fnum1);
4306         if (!NT_STATUS_IS_OK(status)) {
4307                 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
4308                 correct = False;
4309                 goto fail;
4310         }
4311
4312         /* This should delete the file. */
4313         status = cli_close(cli1, fnum1);
4314         if (!NT_STATUS_IS_OK(status)) {
4315                 printf("[10] close failed (%s)\n", nt_errstr(status));
4316                 correct = False;
4317                 goto fail;
4318         }
4319
4320         /* This should fail.. */
4321         if (NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
4322                 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
4323                 goto fail;
4324                 correct = False;
4325         } else
4326                 printf("tenth delete on close test succeeded.\n");
4327
4328         cli_setatr(cli1, fname, 0, 0);
4329         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4330
4331         /* What error do we get when attempting to open a read-only file with
4332            delete access ? */
4333
4334         /* Create a readonly file. */
4335         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4336                               FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
4337                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4338         if (!NT_STATUS_IS_OK(status)) {
4339                 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
4340                 correct = False;
4341                 goto fail;
4342         }
4343
4344         status = cli_close(cli1, fnum1);
4345         if (!NT_STATUS_IS_OK(status)) {
4346                 printf("[11] close failed (%s)\n", nt_errstr(status));
4347                 correct = False;
4348                 goto fail;
4349         }
4350
4351         /* Now try open for delete access. */
4352         status = cli_ntcreate(cli1, fname, 0,
4353                              FILE_READ_ATTRIBUTES|DELETE_ACCESS,
4354                              0,
4355                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4356                              FILE_OVERWRITE_IF, 0, 0, &fnum1);
4357         if (NT_STATUS_IS_OK(status)) {
4358                 printf("[11] open of %s succeeded should have been denied with ACCESS_DENIED!\n", fname);
4359                 cli_close(cli1, fnum1);
4360                 goto fail;
4361                 correct = False;
4362         } else {
4363                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
4364                         printf("[11] open of %s should have been denied with ACCESS_DENIED! Got error %s\n", fname, nt_errstr(status));
4365                         goto fail;
4366                         correct = False;
4367                 } else {
4368                         printf("eleventh delete on close test succeeded.\n");
4369                 }
4370         }
4371
4372         printf("finished delete test\n");
4373
4374   fail:
4375         /* FIXME: This will crash if we aborted before cli2 got
4376          * intialized, because these functions don't handle
4377          * uninitialized connections. */
4378
4379         if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
4380         if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
4381         cli_setatr(cli1, fname, 0, 0);
4382         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4383
4384         if (cli1 && !torture_close_connection(cli1)) {
4385                 correct = False;
4386         }
4387         if (cli2 && !torture_close_connection(cli2)) {
4388                 correct = False;
4389         }
4390         return correct;
4391 }
4392
4393 static bool run_deletetest_ln(int dummy)
4394 {
4395         struct cli_state *cli;
4396         const char *fname = "\\delete1";
4397         const char *fname_ln = "\\delete1_ln";
4398         uint16_t fnum;
4399         uint16_t fnum1;
4400         NTSTATUS status;
4401         bool correct = true;
4402         time_t t;
4403
4404         printf("starting deletetest-ln\n");
4405
4406         if (!torture_open_connection(&cli, 0)) {
4407                 return false;
4408         }
4409
4410         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4411         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4412
4413         smbXcli_conn_set_sockopt(cli->conn, sockops);
4414
4415         /* Create the file. */
4416         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
4417         if (!NT_STATUS_IS_OK(status)) {
4418                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4419                 return false;
4420         }
4421
4422         status = cli_close(cli, fnum);
4423         if (!NT_STATUS_IS_OK(status)) {
4424                 printf("close1 failed (%s)\n", nt_errstr(status));
4425                 return false;
4426         }
4427
4428         /* Now create a hardlink. */
4429         status = cli_nt_hardlink(cli, fname, fname_ln);
4430         if (!NT_STATUS_IS_OK(status)) {
4431                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4432                 return false;
4433         }
4434
4435         /* Open the original file. */
4436         status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
4437                         FILE_ATTRIBUTE_NORMAL,
4438                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4439                         FILE_OPEN_IF, 0, 0, &fnum);
4440         if (!NT_STATUS_IS_OK(status)) {
4441                 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
4442                 return false;
4443         }
4444
4445         /* Unlink the hard link path. */
4446         status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
4447                         FILE_ATTRIBUTE_NORMAL,
4448                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4449                         FILE_OPEN_IF, 0, 0, &fnum1);
4450         if (!NT_STATUS_IS_OK(status)) {
4451                 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
4452                 return false;
4453         }
4454         status = cli_nt_delete_on_close(cli, fnum1, true);
4455         if (!NT_STATUS_IS_OK(status)) {
4456                 d_printf("(%s) failed to set delete_on_close %s: %s\n",
4457                         __location__, fname_ln, nt_errstr(status));
4458                 return false;
4459         }
4460
4461         status = cli_close(cli, fnum1);
4462         if (!NT_STATUS_IS_OK(status)) {
4463                 printf("close %s failed (%s)\n",
4464                         fname_ln, nt_errstr(status));
4465                 return false;
4466         }
4467
4468         status = cli_close(cli, fnum);
4469         if (!NT_STATUS_IS_OK(status)) {
4470                 printf("close %s failed (%s)\n",
4471                         fname, nt_errstr(status));
4472                 return false;
4473         }
4474
4475         /* Ensure the original file is still there. */
4476         status = cli_getatr(cli, fname, NULL, NULL, &t);
4477         if (!NT_STATUS_IS_OK(status)) {
4478                 printf("%s getatr on file %s failed (%s)\n",
4479                         __location__,
4480                         fname,
4481                         nt_errstr(status));
4482                 correct = False;
4483         }
4484
4485         /* Ensure the link path is gone. */
4486         status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
4487         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4488                 printf("%s, getatr for file %s returned wrong error code %s "
4489                         "- should have been deleted\n",
4490                         __location__,
4491                         fname_ln, nt_errstr(status));
4492                 correct = False;
4493         }
4494
4495         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4496         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4497
4498         if (!torture_close_connection(cli)) {
4499                 correct = false;
4500         }
4501
4502         printf("finished deletetest-ln\n");
4503
4504         return correct;
4505 }
4506
4507 /*
4508   print out server properties
4509  */
4510 static bool run_properties(int dummy)
4511 {
4512         struct cli_state *cli;
4513         bool correct = True;
4514
4515         printf("starting properties test\n");
4516
4517         ZERO_STRUCT(cli);
4518
4519         if (!torture_open_connection(&cli, 0)) {
4520                 return False;
4521         }
4522
4523         smbXcli_conn_set_sockopt(cli->conn, sockops);
4524
4525         d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
4526
4527         if (!torture_close_connection(cli)) {
4528                 correct = False;
4529         }
4530
4531         return correct;
4532 }
4533
4534
4535
4536 /* FIRST_DESIRED_ACCESS   0xf019f */
4537 #define FIRST_DESIRED_ACCESS   FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
4538                                FILE_READ_EA|                           /* 0xf */ \
4539                                FILE_WRITE_EA|FILE_READ_ATTRIBUTES|     /* 0x90 */ \
4540                                FILE_WRITE_ATTRIBUTES|                  /* 0x100 */ \
4541                                DELETE_ACCESS|READ_CONTROL_ACCESS|\
4542                                WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS     /* 0xf0000 */
4543 /* SECOND_DESIRED_ACCESS  0xe0080 */
4544 #define SECOND_DESIRED_ACCESS  FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
4545                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4546                                WRITE_OWNER_ACCESS                      /* 0xe0000 */
4547
4548 #if 0
4549 #define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
4550                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4551                                FILE_READ_DATA|\
4552                                WRITE_OWNER_ACCESS                      /* */
4553 #endif
4554
4555 /*
4556   Test ntcreate calls made by xcopy
4557  */
4558 static bool run_xcopy(int dummy)
4559 {
4560         static struct cli_state *cli1;
4561         const char *fname = "\\test.txt";
4562         bool correct = True;
4563         uint16_t fnum1, fnum2;
4564         NTSTATUS status;
4565
4566         printf("starting xcopy test\n");
4567
4568         if (!torture_open_connection(&cli1, 0)) {
4569                 return False;
4570         }
4571
4572         status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
4573                               FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
4574                               FILE_OVERWRITE_IF, 0x4044, 0, &fnum1);
4575         if (!NT_STATUS_IS_OK(status)) {
4576                 printf("First open failed - %s\n", nt_errstr(status));
4577                 return False;
4578         }
4579
4580         status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
4581                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4582                              FILE_OPEN, 0x200000, 0, &fnum2);
4583         if (!NT_STATUS_IS_OK(status)) {
4584                 printf("second open failed - %s\n", nt_errstr(status));
4585                 return False;
4586         }
4587
4588         if (!torture_close_connection(cli1)) {
4589                 correct = False;
4590         }
4591
4592         return correct;
4593 }
4594
4595 /*
4596   Test rename on files open with share delete and no share delete.
4597  */
4598 static bool run_rename(int dummy)
4599 {
4600         static struct cli_state *cli1;
4601         const char *fname = "\\test.txt";
4602         const char *fname1 = "\\test1.txt";
4603         bool correct = True;
4604         uint16_t fnum1;
4605         uint16_t attr;
4606         NTSTATUS status;
4607
4608         printf("starting rename test\n");
4609
4610         if (!torture_open_connection(&cli1, 0)) {
4611                 return False;
4612         }
4613
4614         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4615         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4616
4617         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4618                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
4619                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4620         if (!NT_STATUS_IS_OK(status)) {
4621                 printf("First open failed - %s\n", nt_errstr(status));
4622                 return False;
4623         }
4624
4625         status = cli_rename(cli1, fname, fname1);
4626         if (!NT_STATUS_IS_OK(status)) {
4627                 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
4628         } else {
4629                 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
4630                 correct = False;
4631         }
4632
4633         status = cli_close(cli1, fnum1);
4634         if (!NT_STATUS_IS_OK(status)) {
4635                 printf("close - 1 failed (%s)\n", nt_errstr(status));
4636                 return False;
4637         }
4638
4639         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4640         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4641         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4642 #if 0
4643                               FILE_SHARE_DELETE|FILE_SHARE_NONE,
4644 #else
4645                               FILE_SHARE_DELETE|FILE_SHARE_READ,
4646 #endif
4647                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4648         if (!NT_STATUS_IS_OK(status)) {
4649                 printf("Second open failed - %s\n", nt_errstr(status));
4650                 return False;
4651         }
4652
4653         status = cli_rename(cli1, fname, fname1);
4654         if (!NT_STATUS_IS_OK(status)) {
4655                 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
4656                 correct = False;
4657         } else {
4658                 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
4659         }
4660
4661         status = cli_close(cli1, fnum1);
4662         if (!NT_STATUS_IS_OK(status)) {
4663                 printf("close - 2 failed (%s)\n", nt_errstr(status));
4664                 return False;
4665         }
4666
4667         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4668         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4669
4670         status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
4671                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4672                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4673         if (!NT_STATUS_IS_OK(status)) {
4674                 printf("Third open failed - %s\n", nt_errstr(status));
4675                 return False;
4676         }
4677
4678
4679 #if 0
4680   {
4681         uint16_t fnum2;
4682
4683         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
4684                                    FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4685                 printf("Fourth open failed - %s\n", cli_errstr(cli1));
4686                 return False;
4687         }
4688         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum2, true))) {
4689                 printf("[8] setting delete_on_close on file failed !\n");
4690                 return False;
4691         }
4692
4693         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
4694                 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
4695                 return False;
4696         }
4697   }
4698 #endif
4699
4700         status = cli_rename(cli1, fname, fname1);
4701         if (!NT_STATUS_IS_OK(status)) {
4702                 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
4703                 correct = False;
4704         } else {
4705                 printf("Third rename succeeded (SHARE_NONE)\n");
4706         }
4707
4708         status = cli_close(cli1, fnum1);
4709         if (!NT_STATUS_IS_OK(status)) {
4710                 printf("close - 3 failed (%s)\n", nt_errstr(status));
4711                 return False;
4712         }
4713
4714         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4715         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4716
4717         /*----*/
4718
4719         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4720                               FILE_ATTRIBUTE_NORMAL,
4721                               FILE_SHARE_READ | FILE_SHARE_WRITE,
4722                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4723         if (!NT_STATUS_IS_OK(status)) {
4724                 printf("Fourth open failed - %s\n", nt_errstr(status));
4725                 return False;
4726         }
4727
4728         status = cli_rename(cli1, fname, fname1);
4729         if (!NT_STATUS_IS_OK(status)) {
4730                 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
4731         } else {
4732                 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
4733                 correct = False;
4734         }
4735
4736         status = cli_close(cli1, fnum1);
4737         if (!NT_STATUS_IS_OK(status)) {
4738                 printf("close - 4 failed (%s)\n", nt_errstr(status));
4739                 return False;
4740         }
4741
4742         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4743         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4744
4745         /*--*/
4746
4747         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4748                          FILE_ATTRIBUTE_NORMAL,
4749                          FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4750                          FILE_OVERWRITE_IF, 0, 0, &fnum1);
4751         if (!NT_STATUS_IS_OK(status)) {
4752                 printf("Fifth open failed - %s\n", nt_errstr(status));
4753                 return False;
4754         }
4755
4756         status = cli_rename(cli1, fname, fname1);
4757         if (!NT_STATUS_IS_OK(status)) {
4758                 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
4759                 correct = False;
4760         } else {
4761                 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
4762         }
4763
4764         /*
4765          * Now check if the first name still exists ...
4766          */
4767
4768         /* if (!NT_STATUS_OP(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4769                                    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4770           printf("Opening original file after rename of open file fails: %s\n",
4771               cli_errstr(cli1));
4772         }
4773         else {
4774           printf("Opening original file after rename of open file works ...\n");
4775           (void)cli_close(cli1, fnum2);
4776           } */
4777
4778         /*--*/
4779         status = cli_close(cli1, fnum1);
4780         if (!NT_STATUS_IS_OK(status)) {
4781                 printf("close - 5 failed (%s)\n", nt_errstr(status));
4782                 return False;
4783         }
4784
4785         /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
4786         status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
4787         if (!NT_STATUS_IS_OK(status)) {
4788                 printf("getatr on file %s failed - %s ! \n",
4789                         fname1, nt_errstr(status));
4790                 correct = False;
4791         } else {
4792                 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
4793                         printf("Renamed file %s has wrong attr 0x%x "
4794                                 "(should be 0x%x)\n",
4795                                 fname1,
4796                                 attr,
4797                                 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
4798                         correct = False;
4799                 } else {
4800                         printf("Renamed file %s has archive bit set\n", fname1);
4801                 }
4802         }
4803
4804         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4805         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4806
4807         if (!torture_close_connection(cli1)) {
4808                 correct = False;
4809         }
4810
4811         return correct;
4812 }
4813
4814 static bool run_pipe_number(int dummy)
4815 {
4816         struct cli_state *cli1;
4817         const char *pipe_name = "\\SPOOLSS";
4818         uint16_t fnum;
4819         int num_pipes = 0;
4820         NTSTATUS status;
4821
4822         printf("starting pipenumber test\n");
4823         if (!torture_open_connection(&cli1, 0)) {
4824                 return False;
4825         }
4826
4827         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4828         while(1) {
4829                 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
4830                                       FILE_ATTRIBUTE_NORMAL,
4831                                       FILE_SHARE_READ|FILE_SHARE_WRITE,
4832                                       FILE_OPEN_IF, 0, 0, &fnum);
4833                 if (!NT_STATUS_IS_OK(status)) {
4834                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
4835                         break;
4836                 }
4837                 num_pipes++;
4838                 printf("\r%6d", num_pipes);
4839         }
4840
4841         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
4842         torture_close_connection(cli1);
4843         return True;
4844 }
4845
4846 /*
4847   Test open mode returns on read-only files.
4848  */
4849 static bool run_opentest(int dummy)
4850 {
4851         static struct cli_state *cli1;
4852         static struct cli_state *cli2;
4853         const char *fname = "\\readonly.file";
4854         uint16_t fnum1, fnum2;
4855         char buf[20];
4856         off_t fsize;
4857         bool correct = True;
4858         char *tmp_path;
4859         NTSTATUS status;
4860
4861         printf("starting open test\n");
4862
4863         if (!torture_open_connection(&cli1, 0)) {
4864                 return False;
4865         }
4866
4867         cli_setatr(cli1, fname, 0, 0);
4868         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4869
4870         smbXcli_conn_set_sockopt(cli1->conn, sockops);
4871
4872         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4873         if (!NT_STATUS_IS_OK(status)) {
4874                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4875                 return False;
4876         }
4877
4878         status = cli_close(cli1, fnum1);
4879         if (!NT_STATUS_IS_OK(status)) {
4880                 printf("close2 failed (%s)\n", nt_errstr(status));
4881                 return False;
4882         }
4883
4884         status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
4885         if (!NT_STATUS_IS_OK(status)) {
4886                 printf("cli_setatr failed (%s)\n", nt_errstr(status));
4887                 return False;
4888         }
4889
4890         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4891         if (!NT_STATUS_IS_OK(status)) {
4892                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4893                 return False;
4894         }
4895
4896         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
4897         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4898
4899         if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
4900                         NT_STATUS_ACCESS_DENIED)) {
4901                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
4902         }
4903
4904         printf("finished open test 1\n");
4905
4906         cli_close(cli1, fnum1);
4907
4908         /* Now try not readonly and ensure ERRbadshare is returned. */
4909
4910         cli_setatr(cli1, fname, 0, 0);
4911
4912         status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4913         if (!NT_STATUS_IS_OK(status)) {
4914                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4915                 return False;
4916         }
4917
4918         /* This will fail - but the error should be ERRshare. */
4919         status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4920
4921         if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
4922                         NT_STATUS_SHARING_VIOLATION)) {
4923                 printf("correct error code ERRDOS/ERRbadshare returned\n");
4924         }
4925
4926         status = cli_close(cli1, fnum1);
4927         if (!NT_STATUS_IS_OK(status)) {
4928                 printf("close2 failed (%s)\n", nt_errstr(status));
4929                 return False;
4930         }
4931
4932         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4933
4934         printf("finished open test 2\n");
4935
4936         /* Test truncate open disposition on file opened for read. */
4937         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4938         if (!NT_STATUS_IS_OK(status)) {
4939                 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
4940                 return False;
4941         }
4942
4943         /* write 20 bytes. */
4944
4945         memset(buf, '\0', 20);
4946
4947         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
4948         if (!NT_STATUS_IS_OK(status)) {
4949                 printf("write failed (%s)\n", nt_errstr(status));
4950                 correct = False;
4951         }
4952
4953         status = cli_close(cli1, fnum1);
4954         if (!NT_STATUS_IS_OK(status)) {
4955                 printf("(3) close1 failed (%s)\n", nt_errstr(status));
4956                 return False;
4957         }
4958
4959         /* Ensure size == 20. */
4960         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
4961         if (!NT_STATUS_IS_OK(status)) {
4962                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
4963                 return False;
4964         }
4965
4966         if (fsize != 20) {
4967                 printf("(3) file size != 20\n");
4968                 return False;
4969         }
4970
4971         /* Now test if we can truncate a file opened for readonly. */
4972         status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
4973         if (!NT_STATUS_IS_OK(status)) {
4974                 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
4975                 return False;
4976         }
4977
4978         status = cli_close(cli1, fnum1);
4979         if (!NT_STATUS_IS_OK(status)) {
4980                 printf("close2 failed (%s)\n", nt_errstr(status));
4981                 return False;
4982         }
4983
4984         /* Ensure size == 0. */
4985         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
4986         if (!NT_STATUS_IS_OK(status)) {
4987                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
4988                 return False;
4989         }
4990
4991         if (fsize != 0) {
4992                 printf("(3) file size != 0\n");
4993                 return False;
4994         }
4995         printf("finished open test 3\n");
4996
4997         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4998
4999         printf("Do ctemp tests\n");
5000         status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
5001         if (!NT_STATUS_IS_OK(status)) {
5002                 printf("ctemp failed (%s)\n", nt_errstr(status));
5003                 return False;
5004         }
5005
5006         printf("ctemp gave path %s\n", tmp_path);
5007         status = cli_close(cli1, fnum1);
5008         if (!NT_STATUS_IS_OK(status)) {
5009                 printf("close of temp failed (%s)\n", nt_errstr(status));
5010         }
5011
5012         status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5013         if (!NT_STATUS_IS_OK(status)) {
5014                 printf("unlink of temp failed (%s)\n", nt_errstr(status));
5015         }
5016
5017         /* Test the non-io opens... */
5018
5019         if (!torture_open_connection(&cli2, 1)) {
5020                 return False;
5021         }
5022
5023         cli_setatr(cli2, fname, 0, 0);
5024         cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5025
5026         smbXcli_conn_set_sockopt(cli2->conn, sockops);
5027
5028         printf("TEST #1 testing 2 non-io opens (no delete)\n");
5029         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5030                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5031                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5032         if (!NT_STATUS_IS_OK(status)) {
5033                 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5034                 return False;
5035         }
5036
5037         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5038                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5039                               FILE_OPEN_IF, 0, 0, &fnum2);
5040         if (!NT_STATUS_IS_OK(status)) {
5041                 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5042                 return False;
5043         }
5044
5045         status = cli_close(cli1, fnum1);
5046         if (!NT_STATUS_IS_OK(status)) {
5047                 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5048                 return False;
5049         }
5050
5051         status = cli_close(cli2, fnum2);
5052         if (!NT_STATUS_IS_OK(status)) {
5053                 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5054                 return False;
5055         }
5056
5057         printf("non-io open test #1 passed.\n");
5058
5059         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5060
5061         printf("TEST #2 testing 2 non-io opens (first with delete)\n");
5062
5063         status = cli_ntcreate(cli1, fname, 0,
5064                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5065                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5066                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5067         if (!NT_STATUS_IS_OK(status)) {
5068                 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5069                 return False;
5070         }
5071
5072         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5073                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5074                               FILE_OPEN_IF, 0, 0, &fnum2);
5075         if (!NT_STATUS_IS_OK(status)) {
5076                 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5077                 return False;
5078         }
5079
5080         status = cli_close(cli1, fnum1);
5081         if (!NT_STATUS_IS_OK(status)) {
5082                 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5083                 return False;
5084         }
5085
5086         status = cli_close(cli2, fnum2);
5087         if (!NT_STATUS_IS_OK(status)) {
5088                 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5089                 return False;
5090         }
5091
5092         printf("non-io open test #2 passed.\n");
5093
5094         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5095
5096         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
5097
5098         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5099                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5100                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5101         if (!NT_STATUS_IS_OK(status)) {
5102                 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5103                 return False;
5104         }
5105
5106         status = cli_ntcreate(cli2, fname, 0,
5107                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5108                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5109                               FILE_OPEN_IF, 0, 0, &fnum2);
5110         if (!NT_STATUS_IS_OK(status)) {
5111                 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5112                 return False;
5113         }
5114
5115         status = cli_close(cli1, fnum1);
5116         if (!NT_STATUS_IS_OK(status)) {
5117                 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5118                 return False;
5119         }
5120
5121         status = cli_close(cli2, fnum2);
5122         if (!NT_STATUS_IS_OK(status)) {
5123                 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5124                 return False;
5125         }
5126
5127         printf("non-io open test #3 passed.\n");
5128
5129         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5130
5131         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
5132
5133         status = cli_ntcreate(cli1, fname, 0,
5134                                DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5135                                FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5136                                FILE_OVERWRITE_IF, 0, 0, &fnum1);
5137         if (!NT_STATUS_IS_OK(status)) {
5138                 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5139                 return False;
5140         }
5141
5142         status = cli_ntcreate(cli2, fname, 0,
5143                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5144                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5145                               FILE_OPEN_IF, 0, 0, &fnum2);
5146         if (NT_STATUS_IS_OK(status)) {
5147                 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5148                 return False;
5149         }
5150
5151         printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5152
5153         status = cli_close(cli1, fnum1);
5154         if (!NT_STATUS_IS_OK(status)) {
5155                 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5156                 return False;
5157         }
5158
5159         printf("non-io open test #4 passed.\n");
5160
5161         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5162
5163         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
5164
5165         status = cli_ntcreate(cli1, fname, 0,
5166                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5167                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5168                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5169         if (!NT_STATUS_IS_OK(status)) {
5170                 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5171                 return False;
5172         }
5173
5174         status = cli_ntcreate(cli2, fname, 0,
5175                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5176                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5177                               FILE_OPEN_IF, 0, 0, &fnum2);
5178         if (!NT_STATUS_IS_OK(status)) {
5179                 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5180                 return False;
5181         }
5182
5183         status = cli_close(cli1, fnum1);
5184         if (!NT_STATUS_IS_OK(status)) {
5185                 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5186                 return False;
5187         }
5188
5189         status = cli_close(cli2, fnum2);
5190         if (!NT_STATUS_IS_OK(status)) {
5191                 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5192                 return False;
5193         }
5194
5195         printf("non-io open test #5 passed.\n");
5196
5197         printf("TEST #6 testing 1 non-io open, one io open\n");
5198
5199         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5200
5201         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5202                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5203                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5204         if (!NT_STATUS_IS_OK(status)) {
5205                 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5206                 return False;
5207         }
5208
5209         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5210                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
5211                               FILE_OPEN_IF, 0, 0, &fnum2);
5212         if (!NT_STATUS_IS_OK(status)) {
5213                 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5214                 return False;
5215         }
5216
5217         status = cli_close(cli1, fnum1);
5218         if (!NT_STATUS_IS_OK(status)) {
5219                 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5220                 return False;
5221         }
5222
5223         status = cli_close(cli2, fnum2);
5224         if (!NT_STATUS_IS_OK(status)) {
5225                 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5226                 return False;
5227         }
5228
5229         printf("non-io open test #6 passed.\n");
5230
5231         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
5232
5233         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5234
5235         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5236                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5237                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5238         if (!NT_STATUS_IS_OK(status)) {
5239                 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5240                 return False;
5241         }
5242
5243         status = cli_ntcreate(cli2, fname, 0,
5244                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5245                               FILE_ATTRIBUTE_NORMAL,
5246                               FILE_SHARE_READ|FILE_SHARE_DELETE,
5247                               FILE_OPEN_IF, 0, 0, &fnum2);
5248         if (NT_STATUS_IS_OK(status)) {
5249                 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5250                 return False;
5251         }
5252
5253         printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5254
5255         status = cli_close(cli1, fnum1);
5256         if (!NT_STATUS_IS_OK(status)) {
5257                 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5258                 return False;
5259         }
5260
5261         printf("non-io open test #7 passed.\n");
5262
5263         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5264
5265         printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
5266         status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
5267                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5268                                 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5269         if (!NT_STATUS_IS_OK(status)) {
5270                 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
5271                 correct = false;
5272                 goto out;
5273         }
5274
5275         /* Write to ensure we have to update the file time. */
5276         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5277                               NULL);
5278         if (!NT_STATUS_IS_OK(status)) {
5279                 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
5280                 correct = false;
5281                 goto out;
5282         }
5283
5284         status = cli_close(cli1, fnum1);
5285         if (!NT_STATUS_IS_OK(status)) {
5286                 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
5287                 correct = false;
5288         }
5289
5290   out:
5291
5292         if (!torture_close_connection(cli1)) {
5293                 correct = False;
5294         }
5295         if (!torture_close_connection(cli2)) {
5296                 correct = False;
5297         }
5298
5299         return correct;
5300 }
5301
5302 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
5303 {
5304         uint16 major, minor;
5305         uint32 caplow, caphigh;
5306         NTSTATUS status;
5307
5308         if (!SERVER_HAS_UNIX_CIFS(cli)) {
5309                 printf("Server doesn't support UNIX CIFS extensions.\n");
5310                 return NT_STATUS_NOT_SUPPORTED;
5311         }
5312
5313         status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
5314                                              &caphigh);
5315         if (!NT_STATUS_IS_OK(status)) {
5316                 printf("Server didn't return UNIX CIFS extensions: %s\n",
5317                        nt_errstr(status));
5318                 return status;
5319         }
5320
5321         status = cli_set_unix_extensions_capabilities(cli, major, minor,
5322                                                       caplow, caphigh);
5323         if (!NT_STATUS_IS_OK(status)) {
5324                 printf("Server doesn't support setting UNIX CIFS extensions: "
5325                        "%s.\n", nt_errstr(status));
5326                 return status;
5327         }
5328
5329         return NT_STATUS_OK;
5330 }
5331
5332 /*
5333   Test POSIX open /mkdir calls.
5334  */
5335 static bool run_simple_posix_open_test(int dummy)
5336 {
5337         static struct cli_state *cli1;
5338         const char *fname = "posix:file";
5339         const char *hname = "posix:hlink";
5340         const char *sname = "posix:symlink";
5341         const char *dname = "posix:dir";
5342         char buf[10];
5343         char namebuf[11];
5344         uint16_t fnum1 = (uint16_t)-1;
5345         SMB_STRUCT_STAT sbuf;
5346         bool correct = false;
5347         NTSTATUS status;
5348         size_t nread;
5349
5350         printf("Starting simple POSIX open test\n");
5351
5352         if (!torture_open_connection(&cli1, 0)) {
5353                 return false;
5354         }
5355
5356         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5357
5358         status = torture_setup_unix_extensions(cli1);
5359         if (!NT_STATUS_IS_OK(status)) {
5360                 return false;
5361         }
5362
5363         cli_setatr(cli1, fname, 0, 0);
5364         cli_posix_unlink(cli1, fname);
5365         cli_setatr(cli1, dname, 0, 0);
5366         cli_posix_rmdir(cli1, dname);
5367         cli_setatr(cli1, hname, 0, 0);
5368         cli_posix_unlink(cli1, hname);
5369         cli_setatr(cli1, sname, 0, 0);
5370         cli_posix_unlink(cli1, sname);
5371
5372         /* Create a directory. */
5373         status = cli_posix_mkdir(cli1, dname, 0777);
5374         if (!NT_STATUS_IS_OK(status)) {
5375                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
5376                 goto out;
5377         }
5378
5379         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5380                                 0600, &fnum1);
5381         if (!NT_STATUS_IS_OK(status)) {
5382                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5383                 goto out;
5384         }
5385
5386         /* Test ftruncate - set file size. */
5387         status = cli_ftruncate(cli1, fnum1, 1000);
5388         if (!NT_STATUS_IS_OK(status)) {
5389                 printf("ftruncate failed (%s)\n", nt_errstr(status));
5390                 goto out;
5391         }
5392
5393         /* Ensure st_size == 1000 */
5394         status = cli_posix_stat(cli1, fname, &sbuf);
5395         if (!NT_STATUS_IS_OK(status)) {
5396                 printf("stat failed (%s)\n", nt_errstr(status));
5397                 goto out;
5398         }
5399
5400         if (sbuf.st_ex_size != 1000) {
5401                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5402                 goto out;
5403         }
5404
5405         /* Test ftruncate - set file size back to zero. */
5406         status = cli_ftruncate(cli1, fnum1, 0);
5407         if (!NT_STATUS_IS_OK(status)) {
5408                 printf("ftruncate failed (%s)\n", nt_errstr(status));
5409                 goto out;
5410         }
5411
5412         status = cli_close(cli1, fnum1);
5413         if (!NT_STATUS_IS_OK(status)) {
5414                 printf("close failed (%s)\n", nt_errstr(status));
5415                 goto out;
5416         }
5417
5418         /* Now open the file again for read only. */
5419         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5420         if (!NT_STATUS_IS_OK(status)) {
5421                 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
5422                 goto out;
5423         }
5424
5425         /* Now unlink while open. */
5426         status = cli_posix_unlink(cli1, fname);
5427         if (!NT_STATUS_IS_OK(status)) {
5428                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5429                 goto out;
5430         }
5431
5432         status = cli_close(cli1, fnum1);
5433         if (!NT_STATUS_IS_OK(status)) {
5434                 printf("close(2) failed (%s)\n", nt_errstr(status));
5435                 goto out;
5436         }
5437
5438         /* Ensure the file has gone. */
5439         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5440         if (NT_STATUS_IS_OK(status)) {
5441                 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
5442                 goto out;
5443         }
5444
5445         /* Create again to test open with O_TRUNC. */
5446         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
5447         if (!NT_STATUS_IS_OK(status)) {
5448                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5449                 goto out;
5450         }
5451
5452         /* Test ftruncate - set file size. */
5453         status = cli_ftruncate(cli1, fnum1, 1000);
5454         if (!NT_STATUS_IS_OK(status)) {
5455                 printf("ftruncate failed (%s)\n", nt_errstr(status));
5456                 goto out;
5457         }
5458
5459         /* Ensure st_size == 1000 */
5460         status = cli_posix_stat(cli1, fname, &sbuf);
5461         if (!NT_STATUS_IS_OK(status)) {
5462                 printf("stat failed (%s)\n", nt_errstr(status));
5463                 goto out;
5464         }
5465
5466         if (sbuf.st_ex_size != 1000) {
5467                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5468                 goto out;
5469         }
5470
5471         status = cli_close(cli1, fnum1);
5472         if (!NT_STATUS_IS_OK(status)) {
5473                 printf("close(2) failed (%s)\n", nt_errstr(status));
5474                 goto out;
5475         }
5476
5477         /* Re-open with O_TRUNC. */
5478         status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
5479         if (!NT_STATUS_IS_OK(status)) {
5480                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5481                 goto out;
5482         }
5483
5484         /* Ensure st_size == 0 */
5485         status = cli_posix_stat(cli1, fname, &sbuf);
5486         if (!NT_STATUS_IS_OK(status)) {
5487                 printf("stat failed (%s)\n", nt_errstr(status));
5488                 goto out;
5489         }
5490
5491         if (sbuf.st_ex_size != 0) {
5492                 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
5493                 goto out;
5494         }
5495
5496         status = cli_close(cli1, fnum1);
5497         if (!NT_STATUS_IS_OK(status)) {
5498                 printf("close failed (%s)\n", nt_errstr(status));
5499                 goto out;
5500         }
5501
5502         status = cli_posix_unlink(cli1, fname);
5503         if (!NT_STATUS_IS_OK(status)) {
5504                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5505                 goto out;
5506         }
5507
5508         status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
5509         if (!NT_STATUS_IS_OK(status)) {
5510                 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
5511                         dname, nt_errstr(status));
5512                 goto out;
5513         }
5514
5515         cli_close(cli1, fnum1);
5516
5517         /* What happens when we try and POSIX open a directory for write ? */
5518         status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
5519         if (NT_STATUS_IS_OK(status)) {
5520                 printf("POSIX open of directory %s succeeded, should have failed.\n", fname);
5521                 goto out;
5522         } else {
5523                 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
5524                                 NT_STATUS_FILE_IS_A_DIRECTORY)) {
5525                         goto out;
5526                 }
5527         }
5528
5529         /* Create the file. */
5530         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5531                                 0600, &fnum1);
5532         if (!NT_STATUS_IS_OK(status)) {
5533                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5534                 goto out;
5535         }
5536
5537         /* Write some data into it. */
5538         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5539                               NULL);
5540         if (!NT_STATUS_IS_OK(status)) {
5541                 printf("cli_write failed: %s\n", nt_errstr(status));
5542                 goto out;
5543         }
5544
5545         cli_close(cli1, fnum1);
5546
5547         /* Now create a hardlink. */
5548         status = cli_posix_hardlink(cli1, fname, hname);
5549         if (!NT_STATUS_IS_OK(status)) {
5550                 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
5551                 goto out;
5552         }
5553
5554         /* Now create a symlink. */
5555         status = cli_posix_symlink(cli1, fname, sname);
5556         if (!NT_STATUS_IS_OK(status)) {
5557                 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
5558                 goto out;
5559         }
5560
5561         /* Open the hardlink for read. */
5562         status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
5563         if (!NT_STATUS_IS_OK(status)) {
5564                 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
5565                 goto out;
5566         }
5567
5568         status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
5569         if (!NT_STATUS_IS_OK(status)) {
5570                 printf("POSIX read of %s failed (%s)\n", hname,
5571                        nt_errstr(status));
5572                 goto out;
5573         } else if (nread != 10) {
5574                 printf("POSIX read of %s failed. Received %ld, expected %d\n",
5575                        hname, (unsigned long)nread, 10);
5576                 goto out;
5577         }
5578
5579         if (memcmp(buf, "TEST DATA\n", 10)) {
5580                 printf("invalid data read from hardlink\n");
5581                 goto out;
5582         }
5583
5584         /* Do a POSIX lock/unlock. */
5585         status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
5586         if (!NT_STATUS_IS_OK(status)) {
5587                 printf("POSIX lock failed %s\n", nt_errstr(status));
5588                 goto out;
5589         }
5590
5591         /* Punch a hole in the locked area. */
5592         status = cli_posix_unlock(cli1, fnum1, 10, 80);
5593         if (!NT_STATUS_IS_OK(status)) {
5594                 printf("POSIX unlock failed %s\n", nt_errstr(status));
5595                 goto out;
5596         }
5597
5598         cli_close(cli1, fnum1);
5599
5600         /* Open the symlink for read - this should fail. A POSIX
5601            client should not be doing opens on a symlink. */
5602         status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
5603         if (NT_STATUS_IS_OK(status)) {
5604                 printf("POSIX open of %s succeeded (should have failed)\n", sname);
5605                 goto out;
5606         } else {
5607                 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
5608                                 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
5609                         printf("POSIX open of %s should have failed "
5610                                 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
5611                                 "failed with %s instead.\n",
5612                                 sname, nt_errstr(status));
5613                         goto out;
5614                 }
5615         }
5616
5617         status = cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf));
5618         if (!NT_STATUS_IS_OK(status)) {
5619                 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
5620                 goto out;
5621         }
5622
5623         if (strcmp(namebuf, fname) != 0) {
5624                 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
5625                         sname, fname, namebuf);
5626                 goto out;
5627         }
5628
5629         status = cli_posix_rmdir(cli1, dname);
5630         if (!NT_STATUS_IS_OK(status)) {
5631                 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
5632                 goto out;
5633         }
5634
5635         printf("Simple POSIX open test passed\n");
5636         correct = true;
5637
5638   out:
5639
5640         if (fnum1 != (uint16_t)-1) {
5641                 cli_close(cli1, fnum1);
5642                 fnum1 = (uint16_t)-1;
5643         }
5644
5645         cli_setatr(cli1, sname, 0, 0);
5646         cli_posix_unlink(cli1, sname);
5647         cli_setatr(cli1, hname, 0, 0);
5648         cli_posix_unlink(cli1, hname);
5649         cli_setatr(cli1, fname, 0, 0);
5650         cli_posix_unlink(cli1, fname);
5651         cli_setatr(cli1, dname, 0, 0);
5652         cli_posix_rmdir(cli1, dname);
5653
5654         if (!torture_close_connection(cli1)) {
5655                 correct = false;
5656         }
5657
5658         return correct;
5659 }
5660
5661
5662 static uint32 open_attrs_table[] = {
5663                 FILE_ATTRIBUTE_NORMAL,
5664                 FILE_ATTRIBUTE_ARCHIVE,
5665                 FILE_ATTRIBUTE_READONLY,
5666                 FILE_ATTRIBUTE_HIDDEN,
5667                 FILE_ATTRIBUTE_SYSTEM,
5668
5669                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
5670                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
5671                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
5672                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5673                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5674                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5675
5676                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5677                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5678                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5679                 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
5680 };
5681
5682 struct trunc_open_results {
5683         unsigned int num;
5684         uint32 init_attr;
5685         uint32 trunc_attr;
5686         uint32 result_attr;
5687 };
5688
5689 static struct trunc_open_results attr_results[] = {
5690         { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5691         { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5692         { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5693         { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5694         { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5695         { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5696         { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5697         { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5698         { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5699         { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5700         { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5701         { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
5702         { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5703         { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5704         { 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 },
5705         { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5706         { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5707         { 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 },
5708         { 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 },
5709         { 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 },
5710         { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5711         { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5712         { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5713         { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5714         { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5715         { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
5716 };
5717
5718 static bool run_openattrtest(int dummy)
5719 {
5720         static struct cli_state *cli1;
5721         const char *fname = "\\openattr.file";
5722         uint16_t fnum1;
5723         bool correct = True;
5724         uint16 attr;
5725         unsigned int i, j, k, l;
5726         NTSTATUS status;
5727
5728         printf("starting open attr test\n");
5729
5730         if (!torture_open_connection(&cli1, 0)) {
5731                 return False;
5732         }
5733
5734         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5735
5736         for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32); i++) {
5737                 cli_setatr(cli1, fname, 0, 0);
5738                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5739
5740                 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
5741                                        open_attrs_table[i], FILE_SHARE_NONE,
5742                                        FILE_OVERWRITE_IF, 0, 0, &fnum1);
5743                 if (!NT_STATUS_IS_OK(status)) {
5744                         printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5745                         return False;
5746                 }
5747
5748                 status = cli_close(cli1, fnum1);
5749                 if (!NT_STATUS_IS_OK(status)) {
5750                         printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5751                         return False;
5752                 }
5753
5754                 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32); j++) {
5755                         status = cli_ntcreate(cli1, fname, 0,
5756                                               FILE_READ_DATA|FILE_WRITE_DATA,
5757                                               open_attrs_table[j],
5758                                               FILE_SHARE_NONE, FILE_OVERWRITE,
5759                                               0, 0, &fnum1);
5760                         if (!NT_STATUS_IS_OK(status)) {
5761                                 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5762                                         if (attr_results[l].num == k) {
5763                                                 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
5764                                                                 k, open_attrs_table[i],
5765                                                                 open_attrs_table[j],
5766                                                                 fname, NT_STATUS_V(status), nt_errstr(status));
5767                                                 correct = False;
5768                                         }
5769                                 }
5770
5771                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5772                                         printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
5773                                                         k, open_attrs_table[i], open_attrs_table[j],
5774                                                         nt_errstr(status));
5775                                         correct = False;
5776                                 }
5777 #if 0
5778                                 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
5779 #endif
5780                                 k++;
5781                                 continue;
5782                         }
5783
5784                         status = cli_close(cli1, fnum1);
5785                         if (!NT_STATUS_IS_OK(status)) {
5786                                 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
5787                                 return False;
5788                         }
5789
5790                         status = cli_getatr(cli1, fname, &attr, NULL, NULL);
5791                         if (!NT_STATUS_IS_OK(status)) {
5792                                 printf("getatr(2) failed (%s)\n", nt_errstr(status));
5793                                 return False;
5794                         }
5795
5796 #if 0
5797                         printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
5798                                         k,  open_attrs_table[i],  open_attrs_table[j], attr );
5799 #endif
5800
5801                         for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5802                                 if (attr_results[l].num == k) {
5803                                         if (attr != attr_results[l].result_attr ||
5804                                                         open_attrs_table[i] != attr_results[l].init_attr ||
5805                                                         open_attrs_table[j] != attr_results[l].trunc_attr) {
5806                                                 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
5807                                                 open_attrs_table[i],
5808                                                 open_attrs_table[j],
5809                                                 (unsigned int)attr,
5810                                                 attr_results[l].result_attr);
5811                                                 correct = False;
5812                                         }
5813                                         break;
5814                                 }
5815                         }
5816                         k++;
5817                 }
5818         }
5819
5820         cli_setatr(cli1, fname, 0, 0);
5821         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5822
5823         printf("open attr test %s.\n", correct ? "passed" : "failed");
5824
5825         if (!torture_close_connection(cli1)) {
5826                 correct = False;
5827         }
5828         return correct;
5829 }
5830
5831 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
5832                     const char *name, void *state)
5833 {
5834         int *matched = (int *)state;
5835         if (matched != NULL) {
5836                 *matched += 1;
5837         }
5838         return NT_STATUS_OK;
5839 }
5840
5841 /*
5842   test directory listing speed
5843  */
5844 static bool run_dirtest(int dummy)
5845 {
5846         int i;
5847         static struct cli_state *cli;
5848         uint16_t fnum;
5849         struct timeval core_start;
5850         bool correct = True;
5851         int matched;
5852
5853         printf("starting directory test\n");
5854
5855         if (!torture_open_connection(&cli, 0)) {
5856                 return False;
5857         }
5858
5859         smbXcli_conn_set_sockopt(cli->conn, sockops);
5860
5861         srandom(0);
5862         for (i=0;i<torture_numops;i++) {
5863                 fstring fname;
5864                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5865                 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
5866                         fprintf(stderr,"Failed to open %s\n", fname);
5867                         return False;
5868                 }
5869                 cli_close(cli, fnum);
5870         }
5871
5872         core_start = timeval_current();
5873
5874         matched = 0;
5875         cli_list(cli, "a*.*", 0, list_fn, &matched);
5876         printf("Matched %d\n", matched);
5877
5878         matched = 0;
5879         cli_list(cli, "b*.*", 0, list_fn, &matched);
5880         printf("Matched %d\n", matched);
5881
5882         matched = 0;
5883         cli_list(cli, "xyzabc", 0, list_fn, &matched);
5884         printf("Matched %d\n", matched);
5885
5886         printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
5887
5888         srandom(0);
5889         for (i=0;i<torture_numops;i++) {
5890                 fstring fname;
5891                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5892                 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5893         }
5894
5895         if (!torture_close_connection(cli)) {
5896                 correct = False;
5897         }
5898
5899         printf("finished dirtest\n");
5900
5901         return correct;
5902 }
5903
5904 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
5905                    void *state)
5906 {
5907         struct cli_state *pcli = (struct cli_state *)state;
5908         fstring fname;
5909         slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
5910
5911         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
5912                 return NT_STATUS_OK;
5913
5914         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
5915                 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
5916                         printf("del_fn: failed to rmdir %s\n,", fname );
5917         } else {
5918                 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
5919                         printf("del_fn: failed to unlink %s\n,", fname );
5920         }
5921         return NT_STATUS_OK;
5922 }
5923
5924
5925 /*
5926   sees what IOCTLs are supported
5927  */
5928 bool torture_ioctl_test(int dummy)
5929 {
5930         static struct cli_state *cli;
5931         uint16_t device, function;
5932         uint16_t fnum;
5933         const char *fname = "\\ioctl.dat";
5934         DATA_BLOB blob;
5935         NTSTATUS status;
5936
5937         if (!torture_open_connection(&cli, 0)) {
5938                 return False;
5939         }
5940
5941         printf("starting ioctl test\n");
5942
5943         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5944
5945         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5946         if (!NT_STATUS_IS_OK(status)) {
5947                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5948                 return False;
5949         }
5950
5951         status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
5952         printf("ioctl device info: %s\n", nt_errstr(status));
5953
5954         status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
5955         printf("ioctl job info: %s\n", nt_errstr(status));
5956
5957         for (device=0;device<0x100;device++) {
5958                 printf("ioctl test with device = 0x%x\n", device);
5959                 for (function=0;function<0x100;function++) {
5960                         uint32 code = (device<<16) | function;
5961
5962                         status = cli_raw_ioctl(cli, fnum, code, &blob);
5963
5964                         if (NT_STATUS_IS_OK(status)) {
5965                                 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
5966                                        (int)blob.length);
5967                                 data_blob_free(&blob);
5968                         }
5969                 }
5970         }
5971
5972         if (!torture_close_connection(cli)) {
5973                 return False;
5974         }
5975
5976         return True;
5977 }
5978
5979
5980 /*
5981   tries varients of chkpath
5982  */
5983 bool torture_chkpath_test(int dummy)
5984 {
5985         static struct cli_state *cli;
5986         uint16_t fnum;
5987         bool ret;
5988         NTSTATUS status;
5989
5990         if (!torture_open_connection(&cli, 0)) {
5991                 return False;
5992         }
5993
5994         printf("starting chkpath test\n");
5995
5996         /* cleanup from an old run */
5997         cli_rmdir(cli, "\\chkpath.dir\\dir2");
5998         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5999         cli_rmdir(cli, "\\chkpath.dir");
6000
6001         status = cli_mkdir(cli, "\\chkpath.dir");
6002         if (!NT_STATUS_IS_OK(status)) {
6003                 printf("mkdir1 failed : %s\n", nt_errstr(status));
6004                 return False;
6005         }
6006
6007         status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
6008         if (!NT_STATUS_IS_OK(status)) {
6009                 printf("mkdir2 failed : %s\n", nt_errstr(status));
6010                 return False;
6011         }
6012
6013         status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
6014                           DENY_NONE, &fnum);
6015         if (!NT_STATUS_IS_OK(status)) {
6016                 printf("open1 failed (%s)\n", nt_errstr(status));
6017                 return False;
6018         }
6019         cli_close(cli, fnum);
6020
6021         status = cli_chkpath(cli, "\\chkpath.dir");
6022         if (!NT_STATUS_IS_OK(status)) {
6023                 printf("chkpath1 failed: %s\n", nt_errstr(status));
6024                 ret = False;
6025         }
6026
6027         status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
6028         if (!NT_STATUS_IS_OK(status)) {
6029                 printf("chkpath2 failed: %s\n", nt_errstr(status));
6030                 ret = False;
6031         }
6032
6033         status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
6034         if (!NT_STATUS_IS_OK(status)) {
6035                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
6036                                   NT_STATUS_NOT_A_DIRECTORY);
6037         } else {
6038                 printf("* chkpath on a file should fail\n");
6039                 ret = False;
6040         }
6041
6042         status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
6043         if (!NT_STATUS_IS_OK(status)) {
6044                 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
6045                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
6046         } else {
6047                 printf("* chkpath on a non existant file should fail\n");
6048                 ret = False;
6049         }
6050
6051         status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
6052         if (!NT_STATUS_IS_OK(status)) {
6053                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
6054                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
6055         } else {
6056                 printf("* chkpath on a non existent component should fail\n");
6057                 ret = False;
6058         }
6059
6060         cli_rmdir(cli, "\\chkpath.dir\\dir2");
6061         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6062         cli_rmdir(cli, "\\chkpath.dir");
6063
6064         if (!torture_close_connection(cli)) {
6065                 return False;
6066         }
6067
6068         return ret;
6069 }
6070
6071 static bool run_eatest(int dummy)
6072 {
6073         static struct cli_state *cli;
6074         const char *fname = "\\eatest.txt";
6075         bool correct = True;
6076         uint16_t fnum;
6077         int i;
6078         size_t num_eas;
6079         struct ea_struct *ea_list = NULL;
6080         TALLOC_CTX *mem_ctx = talloc_init("eatest");
6081         NTSTATUS status;
6082
6083         printf("starting eatest\n");
6084
6085         if (!torture_open_connection(&cli, 0)) {
6086                 talloc_destroy(mem_ctx);
6087                 return False;
6088         }
6089
6090         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6091
6092         status = cli_ntcreate(cli, fname, 0,
6093                               FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6094                               FILE_SHARE_NONE, FILE_OVERWRITE_IF,
6095                               0x4044, 0, &fnum);
6096         if (!NT_STATUS_IS_OK(status)) {
6097                 printf("open failed - %s\n", nt_errstr(status));
6098                 talloc_destroy(mem_ctx);
6099                 return False;
6100         }
6101
6102         for (i = 0; i < 10; i++) {
6103                 fstring ea_name, ea_val;
6104
6105                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
6106                 memset(ea_val, (char)i+1, i+1);
6107                 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
6108                 if (!NT_STATUS_IS_OK(status)) {
6109                         printf("ea_set of name %s failed - %s\n", ea_name,
6110                                nt_errstr(status));
6111                         talloc_destroy(mem_ctx);
6112                         return False;
6113                 }
6114         }
6115
6116         cli_close(cli, fnum);
6117         for (i = 0; i < 10; i++) {
6118                 fstring ea_name, ea_val;
6119
6120                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
6121                 memset(ea_val, (char)i+1, i+1);
6122                 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
6123                 if (!NT_STATUS_IS_OK(status)) {
6124                         printf("ea_set of name %s failed - %s\n", ea_name,
6125                                nt_errstr(status));
6126                         talloc_destroy(mem_ctx);
6127                         return False;
6128                 }
6129         }
6130
6131         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6132         if (!NT_STATUS_IS_OK(status)) {
6133                 printf("ea_get list failed - %s\n", nt_errstr(status));
6134                 correct = False;
6135         }
6136
6137         printf("num_eas = %d\n", (int)num_eas);
6138
6139         if (num_eas != 20) {
6140                 printf("Should be 20 EA's stored... failing.\n");
6141                 correct = False;
6142         }
6143
6144         for (i = 0; i < num_eas; i++) {
6145                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6146                 dump_data(0, ea_list[i].value.data,
6147                           ea_list[i].value.length);
6148         }
6149
6150         /* Setting EA's to zero length deletes them. Test this */
6151         printf("Now deleting all EA's - case indepenent....\n");
6152
6153 #if 1
6154         cli_set_ea_path(cli, fname, "", "", 0);
6155 #else
6156         for (i = 0; i < 20; i++) {
6157                 fstring ea_name;
6158                 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
6159                 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
6160                 if (!NT_STATUS_IS_OK(status)) {
6161                         printf("ea_set of name %s failed - %s\n", ea_name,
6162                                nt_errstr(status));
6163                         talloc_destroy(mem_ctx);
6164                         return False;
6165                 }
6166         }
6167 #endif
6168
6169         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6170         if (!NT_STATUS_IS_OK(status)) {
6171                 printf("ea_get list failed - %s\n", nt_errstr(status));
6172                 correct = False;
6173         }
6174
6175         printf("num_eas = %d\n", (int)num_eas);
6176         for (i = 0; i < num_eas; i++) {
6177                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6178                 dump_data(0, ea_list[i].value.data,
6179                           ea_list[i].value.length);
6180         }
6181
6182         if (num_eas != 0) {
6183                 printf("deleting EA's failed.\n");
6184                 correct = False;
6185         }
6186
6187         /* Try and delete a non existant EA. */
6188         status = cli_set_ea_path(cli, fname, "foo", "", 0);
6189         if (!NT_STATUS_IS_OK(status)) {
6190                 printf("deleting non-existant EA 'foo' should succeed. %s\n",
6191                        nt_errstr(status));
6192                 correct = False;
6193         }
6194
6195         talloc_destroy(mem_ctx);
6196         if (!torture_close_connection(cli)) {
6197                 correct = False;
6198         }
6199
6200         return correct;
6201 }
6202
6203 static bool run_dirtest1(int dummy)
6204 {
6205         int i;
6206         static struct cli_state *cli;
6207         uint16_t fnum;
6208         int num_seen;
6209         bool correct = True;
6210
6211         printf("starting directory test\n");
6212
6213         if (!torture_open_connection(&cli, 0)) {
6214                 return False;
6215         }
6216
6217         smbXcli_conn_set_sockopt(cli->conn, sockops);
6218
6219         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6220         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6221         cli_rmdir(cli, "\\LISTDIR");
6222         cli_mkdir(cli, "\\LISTDIR");
6223
6224         /* Create 1000 files and 1000 directories. */
6225         for (i=0;i<1000;i++) {
6226                 fstring fname;
6227                 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
6228                 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6229                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum))) {
6230                         fprintf(stderr,"Failed to open %s\n", fname);
6231                         return False;
6232                 }
6233                 cli_close(cli, fnum);
6234         }
6235         for (i=0;i<1000;i++) {
6236                 fstring fname;
6237                 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
6238                 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
6239                         fprintf(stderr,"Failed to open %s\n", fname);
6240                         return False;
6241                 }
6242         }
6243
6244         /* Now ensure that doing an old list sees both files and directories. */
6245         num_seen = 0;
6246         cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6247         printf("num_seen = %d\n", num_seen );
6248         /* We should see 100 files + 1000 directories + . and .. */
6249         if (num_seen != 2002)
6250                 correct = False;
6251
6252         /* Ensure if we have the "must have" bits we only see the
6253          * relevent entries.
6254          */
6255         num_seen = 0;
6256         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6257         printf("num_seen = %d\n", num_seen );
6258         if (num_seen != 1002)
6259                 correct = False;
6260
6261         num_seen = 0;
6262         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6263         printf("num_seen = %d\n", num_seen );
6264         if (num_seen != 1000)
6265                 correct = False;
6266
6267         /* Delete everything. */
6268         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6269         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6270         cli_rmdir(cli, "\\LISTDIR");
6271
6272 #if 0
6273         printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
6274         printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
6275         printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
6276 #endif
6277
6278         if (!torture_close_connection(cli)) {
6279                 correct = False;
6280         }
6281
6282         printf("finished dirtest1\n");
6283
6284         return correct;
6285 }
6286
6287 static bool run_error_map_extract(int dummy) {
6288
6289         static struct cli_state *c_dos;
6290         static struct cli_state *c_nt;
6291         NTSTATUS status;
6292
6293         uint32 error;
6294
6295         uint32 errnum;
6296         uint8 errclass;
6297
6298         NTSTATUS nt_status;
6299
6300         fstring user;
6301
6302         /* NT-Error connection */
6303
6304         disable_spnego = true;
6305         if (!(c_nt = open_nbt_connection())) {
6306                 disable_spnego = false;
6307                 return False;
6308         }
6309         disable_spnego = false;
6310
6311         status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
6312                                  PROTOCOL_NT1);
6313
6314         if (!NT_STATUS_IS_OK(status)) {
6315                 printf("%s rejected the NT-error negprot (%s)\n", host,
6316                        nt_errstr(status));
6317                 cli_shutdown(c_nt);
6318                 return False;
6319         }
6320
6321         status = cli_session_setup(c_nt, "", "", 0, "", 0, workgroup);
6322         if (!NT_STATUS_IS_OK(status)) {
6323                 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
6324                 return False;
6325         }
6326
6327         /* DOS-Error connection */
6328
6329         disable_spnego = true;
6330         force_dos_errors = true;
6331         if (!(c_dos = open_nbt_connection())) {
6332                 disable_spnego = false;
6333                 force_dos_errors = false;
6334                 return False;
6335         }
6336         disable_spnego = false;
6337         force_dos_errors = false;
6338
6339         status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
6340                                  PROTOCOL_NT1);
6341         if (!NT_STATUS_IS_OK(status)) {
6342                 printf("%s rejected the DOS-error negprot (%s)\n", host,
6343                        nt_errstr(status));
6344                 cli_shutdown(c_dos);
6345                 return False;
6346         }
6347
6348         status = cli_session_setup(c_dos, "", "", 0, "", 0, workgroup);
6349         if (!NT_STATUS_IS_OK(status)) {
6350                 printf("%s rejected the DOS-error initial session setup (%s)\n",
6351                         host, nt_errstr(status));
6352                 return False;
6353         }
6354
6355         c_nt->map_dos_errors = false;
6356         c_dos->map_dos_errors = false;
6357
6358         for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
6359                 fstr_sprintf(user, "%X", error);
6360
6361                 status = cli_session_setup(c_nt, user,
6362                                            password, strlen(password),
6363                                            password, strlen(password),
6364                                            workgroup);
6365                 if (NT_STATUS_IS_OK(status)) {
6366                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
6367                 }
6368
6369                 /* Case #1: 32-bit NT errors */
6370                 if (!NT_STATUS_IS_DOS(status)) {
6371                         nt_status = status;
6372                 } else {
6373                         printf("/** Dos error on NT connection! (%s) */\n", 
6374                                nt_errstr(status));
6375                         nt_status = NT_STATUS(0xc0000000);
6376                 }
6377
6378                 status = cli_session_setup(c_dos, user,
6379                                            password, strlen(password),
6380                                            password, strlen(password),
6381                                            workgroup);
6382                 if (NT_STATUS_IS_OK(status)) {
6383                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
6384                 }
6385
6386                 /* Case #1: 32-bit NT errors */
6387                 if (NT_STATUS_IS_DOS(status)) {
6388                         printf("/** NT error on DOS connection! (%s) */\n", 
6389                                nt_errstr(status));
6390                         errnum = errclass = 0;
6391                 } else {
6392                         errclass = NT_STATUS_DOS_CLASS(status);
6393                         errnum = NT_STATUS_DOS_CODE(status);
6394                 }
6395
6396                 if (NT_STATUS_V(nt_status) != error) { 
6397                         printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n", 
6398                                get_nt_error_c_code(talloc_tos(), NT_STATUS(error)), 
6399                                get_nt_error_c_code(talloc_tos(), nt_status));
6400                 }
6401
6402                 printf("\t{%s,\t%s,\t%s},\n", 
6403                        smb_dos_err_class(errclass), 
6404                        smb_dos_err_name(errclass, errnum), 
6405                        get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
6406         }
6407         return True;
6408 }
6409
6410 static bool run_sesssetup_bench(int dummy)
6411 {
6412         static struct cli_state *c;
6413         const char *fname = "\\file.dat";
6414         uint16_t fnum;
6415         NTSTATUS status;
6416         int i;
6417
6418         if (!torture_open_connection(&c, 0)) {
6419                 return false;
6420         }
6421
6422         status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6423                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6424                               FILE_DELETE_ON_CLOSE, 0, &fnum);
6425         if (!NT_STATUS_IS_OK(status)) {
6426                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
6427                 return false;
6428         }
6429
6430         for (i=0; i<torture_numops; i++) {
6431                 status = cli_session_setup(
6432                         c, username,
6433                         password, strlen(password),
6434                         password, strlen(password),
6435                         workgroup);
6436                 if (!NT_STATUS_IS_OK(status)) {
6437                         d_printf("(%s) cli_session_setup failed: %s\n",
6438                                  __location__, nt_errstr(status));
6439                         return false;
6440                 }
6441
6442                 d_printf("\r%d   ", (int)cli_state_get_uid(c));
6443
6444                 status = cli_ulogoff(c);
6445                 if (!NT_STATUS_IS_OK(status)) {
6446                         d_printf("(%s) cli_ulogoff failed: %s\n",
6447                                  __location__, nt_errstr(status));
6448                         return false;
6449                 }
6450         }
6451
6452         return true;
6453 }
6454
6455 static bool subst_test(const char *str, const char *user, const char *domain,
6456                        uid_t uid, gid_t gid, const char *expected)
6457 {
6458         char *subst;
6459         bool result = true;
6460
6461         subst = talloc_sub_specified(talloc_tos(), str, user, domain, uid, gid);
6462
6463         if (strcmp(subst, expected) != 0) {
6464                 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
6465                        "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
6466                        expected);
6467                 result = false;
6468         }
6469
6470         TALLOC_FREE(subst);
6471         return result;
6472 }
6473
6474 static void chain1_open_completion(struct tevent_req *req)
6475 {
6476         uint16_t fnum;
6477         NTSTATUS status;
6478         status = cli_openx_recv(req, &fnum);
6479         TALLOC_FREE(req);
6480
6481         d_printf("cli_openx_recv returned %s: %d\n",
6482                  nt_errstr(status),
6483                  NT_STATUS_IS_OK(status) ? fnum : -1);
6484 }
6485
6486 static void chain1_write_completion(struct tevent_req *req)
6487 {
6488         size_t written;
6489         NTSTATUS status;
6490         status = cli_write_andx_recv(req, &written);
6491         TALLOC_FREE(req);
6492
6493         d_printf("cli_write_andx_recv returned %s: %d\n",
6494                  nt_errstr(status),
6495                  NT_STATUS_IS_OK(status) ? (int)written : -1);
6496 }
6497
6498 static void chain1_close_completion(struct tevent_req *req)
6499 {
6500         NTSTATUS status;
6501         bool *done = (bool *)tevent_req_callback_data_void(req);
6502
6503         status = cli_close_recv(req);
6504         *done = true;
6505
6506         TALLOC_FREE(req);
6507
6508         d_printf("cli_close returned %s\n", nt_errstr(status));
6509 }
6510
6511 static bool run_chain1(int dummy)
6512 {
6513         struct cli_state *cli1;
6514         struct event_context *evt = event_context_init(NULL);
6515         struct tevent_req *reqs[3], *smbreqs[3];
6516         bool done = false;
6517         const char *str = "foobar";
6518         NTSTATUS status;
6519
6520         printf("starting chain1 test\n");
6521         if (!torture_open_connection(&cli1, 0)) {
6522                 return False;
6523         }
6524
6525         smbXcli_conn_set_sockopt(cli1->conn, sockops);
6526
6527         reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, "\\test",
6528                                   O_CREAT|O_RDWR, 0, &smbreqs[0]);
6529         if (reqs[0] == NULL) return false;
6530         tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
6531
6532
6533         reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
6534                                         (const uint8_t *)str, 0, strlen(str)+1,
6535                                         smbreqs, 1, &smbreqs[1]);
6536         if (reqs[1] == NULL) return false;
6537         tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
6538
6539         reqs[2] = cli_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
6540         if (reqs[2] == NULL) return false;
6541         tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
6542
6543         status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
6544         if (!NT_STATUS_IS_OK(status)) {
6545                 return false;
6546         }
6547
6548         while (!done) {
6549                 tevent_loop_once(evt);
6550         }
6551
6552         torture_close_connection(cli1);
6553         return True;
6554 }
6555
6556 static void chain2_sesssetup_completion(struct tevent_req *req)
6557 {
6558         NTSTATUS status;
6559         status = cli_session_setup_guest_recv(req);
6560         d_printf("sesssetup returned %s\n", nt_errstr(status));
6561 }
6562
6563 static void chain2_tcon_completion(struct tevent_req *req)
6564 {
6565         bool *done = (bool *)tevent_req_callback_data_void(req);
6566         NTSTATUS status;
6567         status = cli_tcon_andx_recv(req);
6568         d_printf("tcon_and_x returned %s\n", nt_errstr(status));
6569         *done = true;
6570 }
6571
6572 static bool run_chain2(int dummy)
6573 {
6574         struct cli_state *cli1;
6575         struct event_context *evt = event_context_init(NULL);
6576         struct tevent_req *reqs[2], *smbreqs[2];
6577         bool done = false;
6578         NTSTATUS status;
6579
6580         printf("starting chain2 test\n");
6581         status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
6582                                       port_to_use, SMB_SIGNING_DEFAULT, 0);
6583         if (!NT_STATUS_IS_OK(status)) {
6584                 return False;
6585         }
6586
6587         smbXcli_conn_set_sockopt(cli1->conn, sockops);
6588
6589         reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
6590                                                  &smbreqs[0]);
6591         if (reqs[0] == NULL) return false;
6592         tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
6593
6594         reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
6595                                        "?????", NULL, 0, &smbreqs[1]);
6596         if (reqs[1] == NULL) return false;
6597         tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
6598
6599         status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
6600         if (!NT_STATUS_IS_OK(status)) {
6601                 return false;
6602         }
6603
6604         while (!done) {
6605                 tevent_loop_once(evt);
6606         }
6607
6608         torture_close_connection(cli1);
6609         return True;
6610 }
6611
6612
6613 struct torture_createdel_state {
6614         struct tevent_context *ev;
6615         struct cli_state *cli;
6616 };
6617
6618 static void torture_createdel_created(struct tevent_req *subreq);
6619 static void torture_createdel_closed(struct tevent_req *subreq);
6620
6621 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
6622                                                  struct tevent_context *ev,
6623                                                  struct cli_state *cli,
6624                                                  const char *name)
6625 {
6626         struct tevent_req *req, *subreq;
6627         struct torture_createdel_state *state;
6628
6629         req = tevent_req_create(mem_ctx, &state,
6630                                 struct torture_createdel_state);
6631         if (req == NULL) {
6632                 return NULL;
6633         }
6634         state->ev = ev;
6635         state->cli = cli;
6636
6637         subreq = cli_ntcreate_send(
6638                 state, ev, cli, name, 0,
6639                 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
6640                 FILE_ATTRIBUTE_NORMAL,
6641                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6642                 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
6643
6644         if (tevent_req_nomem(subreq, req)) {
6645                 return tevent_req_post(req, ev);
6646         }
6647         tevent_req_set_callback(subreq, torture_createdel_created, req);
6648         return req;
6649 }
6650
6651 static void torture_createdel_created(struct tevent_req *subreq)
6652 {
6653         struct tevent_req *req = tevent_req_callback_data(
6654                 subreq, struct tevent_req);
6655         struct torture_createdel_state *state = tevent_req_data(
6656                 req, struct torture_createdel_state);
6657         NTSTATUS status;
6658         uint16_t fnum;
6659
6660         status = cli_ntcreate_recv(subreq, &fnum);
6661         TALLOC_FREE(subreq);
6662         if (!NT_STATUS_IS_OK(status)) {
6663                 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
6664                            nt_errstr(status)));
6665                 tevent_req_nterror(req, status);
6666                 return;
6667         }
6668
6669         subreq = cli_close_send(state, state->ev, state->cli, fnum);
6670         if (tevent_req_nomem(subreq, req)) {
6671                 return;
6672         }
6673         tevent_req_set_callback(subreq, torture_createdel_closed, req);
6674 }
6675
6676 static void torture_createdel_closed(struct tevent_req *subreq)
6677 {
6678         struct tevent_req *req = tevent_req_callback_data(
6679                 subreq, struct tevent_req);
6680         NTSTATUS status;
6681
6682         status = cli_close_recv(subreq);
6683         if (!NT_STATUS_IS_OK(status)) {
6684                 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
6685                 tevent_req_nterror(req, status);
6686                 return;
6687         }
6688         tevent_req_done(req);
6689 }
6690
6691 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
6692 {
6693         return tevent_req_simple_recv_ntstatus(req);
6694 }
6695
6696 struct torture_createdels_state {
6697         struct tevent_context *ev;
6698         struct cli_state *cli;
6699         const char *base_name;
6700         int sent;
6701         int received;
6702         int num_files;
6703         struct tevent_req **reqs;
6704 };
6705
6706 static void torture_createdels_done(struct tevent_req *subreq);
6707
6708 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
6709                                                   struct tevent_context *ev,
6710                                                   struct cli_state *cli,
6711                                                   const char *base_name,
6712                                                   int num_parallel,
6713                                                   int num_files)
6714 {
6715         struct tevent_req *req;
6716         struct torture_createdels_state *state;
6717         int i;
6718
6719         req = tevent_req_create(mem_ctx, &state,
6720                                 struct torture_createdels_state);
6721         if (req == NULL) {
6722                 return NULL;
6723         }
6724         state->ev = ev;
6725         state->cli = cli;
6726         state->base_name = talloc_strdup(state, base_name);
6727         if (tevent_req_nomem(state->base_name, req)) {
6728                 return tevent_req_post(req, ev);
6729         }
6730         state->num_files = MAX(num_parallel, num_files);
6731         state->sent = 0;
6732         state->received = 0;
6733
6734         state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
6735         if (tevent_req_nomem(state->reqs, req)) {
6736                 return tevent_req_post(req, ev);
6737         }
6738
6739         for (i=0; i<num_parallel; i++) {
6740                 char *name;
6741
6742                 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6743                                        state->sent);
6744                 if (tevent_req_nomem(name, req)) {
6745                         return tevent_req_post(req, ev);
6746                 }
6747                 state->reqs[i] = torture_createdel_send(
6748                         state->reqs, state->ev, state->cli, name);
6749                 if (tevent_req_nomem(state->reqs[i], req)) {
6750                         return tevent_req_post(req, ev);
6751                 }
6752                 name = talloc_move(state->reqs[i], &name);
6753                 tevent_req_set_callback(state->reqs[i],
6754                                         torture_createdels_done, req);
6755                 state->sent += 1;
6756         }
6757         return req;
6758 }
6759
6760 static void torture_createdels_done(struct tevent_req *subreq)
6761 {
6762         struct tevent_req *req = tevent_req_callback_data(
6763                 subreq, struct tevent_req);
6764         struct torture_createdels_state *state = tevent_req_data(
6765                 req, struct torture_createdels_state);
6766         size_t num_parallel = talloc_array_length(state->reqs);
6767         NTSTATUS status;
6768         char *name;
6769         int i;
6770
6771         status = torture_createdel_recv(subreq);
6772         if (!NT_STATUS_IS_OK(status)){
6773                 DEBUG(10, ("torture_createdel_recv returned %s\n",
6774                            nt_errstr(status)));
6775                 TALLOC_FREE(subreq);
6776                 tevent_req_nterror(req, status);
6777                 return;
6778         }
6779
6780         for (i=0; i<num_parallel; i++) {
6781                 if (subreq == state->reqs[i]) {
6782                         break;
6783                 }
6784         }
6785         if (i == num_parallel) {
6786                 DEBUG(10, ("received something we did not send\n"));
6787                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
6788                 return;
6789         }
6790         TALLOC_FREE(state->reqs[i]);
6791
6792         if (state->sent >= state->num_files) {
6793                 tevent_req_done(req);
6794                 return;
6795         }
6796
6797         name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6798                                state->sent);
6799         if (tevent_req_nomem(name, req)) {
6800                 return;
6801         }
6802         state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
6803                                                 state->cli, name);
6804         if (tevent_req_nomem(state->reqs[i], req)) {
6805                 return;
6806         }
6807         name = talloc_move(state->reqs[i], &name);
6808         tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
6809         state->sent += 1;
6810 }
6811
6812 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
6813 {
6814         return tevent_req_simple_recv_ntstatus(req);
6815 }
6816
6817 struct swallow_notify_state {
6818         struct tevent_context *ev;
6819         struct cli_state *cli;
6820         uint16_t fnum;
6821         uint32_t completion_filter;
6822         bool recursive;
6823         bool (*fn)(uint32_t action, const char *name, void *priv);
6824         void *priv;
6825 };
6826
6827 static void swallow_notify_done(struct tevent_req *subreq);
6828
6829 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
6830                                               struct tevent_context *ev,
6831                                               struct cli_state *cli,
6832                                               uint16_t fnum,
6833                                               uint32_t completion_filter,
6834                                               bool recursive,
6835                                               bool (*fn)(uint32_t action,
6836                                                          const char *name,
6837                                                          void *priv),
6838                                               void *priv)
6839 {
6840         struct tevent_req *req, *subreq;
6841         struct swallow_notify_state *state;
6842
6843         req = tevent_req_create(mem_ctx, &state,
6844                                 struct swallow_notify_state);
6845         if (req == NULL) {
6846                 return NULL;
6847         }
6848         state->ev = ev;
6849         state->cli = cli;
6850         state->fnum = fnum;
6851         state->completion_filter = completion_filter;
6852         state->recursive = recursive;
6853         state->fn = fn;
6854         state->priv = priv;
6855
6856         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6857                                  0xffff, state->completion_filter,
6858                                  state->recursive);
6859         if (tevent_req_nomem(subreq, req)) {
6860                 return tevent_req_post(req, ev);
6861         }
6862         tevent_req_set_callback(subreq, swallow_notify_done, req);
6863         return req;
6864 }
6865
6866 static void swallow_notify_done(struct tevent_req *subreq)
6867 {
6868         struct tevent_req *req = tevent_req_callback_data(
6869                 subreq, struct tevent_req);
6870         struct swallow_notify_state *state = tevent_req_data(
6871                 req, struct swallow_notify_state);
6872         NTSTATUS status;
6873         uint32_t i, num_changes;
6874         struct notify_change *changes;
6875
6876         status = cli_notify_recv(subreq, state, &num_changes, &changes);
6877         TALLOC_FREE(subreq);
6878         if (!NT_STATUS_IS_OK(status)) {
6879                 DEBUG(10, ("cli_notify_recv returned %s\n",
6880                            nt_errstr(status)));
6881                 tevent_req_nterror(req, status);
6882                 return;
6883         }
6884
6885         for (i=0; i<num_changes; i++) {
6886                 state->fn(changes[i].action, changes[i].name, state->priv);
6887         }
6888         TALLOC_FREE(changes);
6889
6890         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6891                                  0xffff, state->completion_filter,
6892                                  state->recursive);
6893         if (tevent_req_nomem(subreq, req)) {
6894                 return;
6895         }
6896         tevent_req_set_callback(subreq, swallow_notify_done, req);
6897 }
6898
6899 static bool print_notifies(uint32_t action, const char *name, void *priv)
6900 {
6901         if (DEBUGLEVEL > 5) {
6902                 d_printf("%d %s\n", (int)action, name);
6903         }
6904         return true;
6905 }
6906
6907 static void notify_bench_done(struct tevent_req *req)
6908 {
6909         int *num_finished = (int *)tevent_req_callback_data_void(req);
6910         *num_finished += 1;
6911 }
6912
6913 static bool run_notify_bench(int dummy)
6914 {
6915         const char *dname = "\\notify-bench";
6916         struct tevent_context *ev;
6917         NTSTATUS status;
6918         uint16_t dnum;
6919         struct tevent_req *req1;
6920         struct tevent_req *req2 = NULL;
6921         int i, num_unc_names;
6922         int num_finished = 0;
6923
6924         printf("starting notify-bench test\n");
6925
6926         if (use_multishare_conn) {
6927                 char **unc_list;
6928                 unc_list = file_lines_load(multishare_conn_fname,
6929                                            &num_unc_names, 0, NULL);
6930                 if (!unc_list || num_unc_names <= 0) {
6931                         d_printf("Failed to load unc names list from '%s'\n",
6932                                  multishare_conn_fname);
6933                         return false;
6934                 }
6935                 TALLOC_FREE(unc_list);
6936         } else {
6937                 num_unc_names = 1;
6938         }
6939
6940         ev = tevent_context_init(talloc_tos());
6941         if (ev == NULL) {
6942                 d_printf("tevent_context_init failed\n");
6943                 return false;
6944         }
6945
6946         for (i=0; i<num_unc_names; i++) {
6947                 struct cli_state *cli;
6948                 char *base_fname;
6949
6950                 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
6951                                              dname, i);
6952                 if (base_fname == NULL) {
6953                         return false;
6954                 }
6955
6956                 if (!torture_open_connection(&cli, i)) {
6957                         return false;
6958                 }
6959
6960                 status = cli_ntcreate(cli, dname, 0,
6961                                       MAXIMUM_ALLOWED_ACCESS,
6962                                       0, FILE_SHARE_READ|FILE_SHARE_WRITE|
6963                                       FILE_SHARE_DELETE,
6964                                       FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
6965                                       &dnum);
6966
6967                 if (!NT_STATUS_IS_OK(status)) {
6968                         d_printf("Could not create %s: %s\n", dname,
6969                                  nt_errstr(status));
6970                         return false;
6971                 }
6972
6973                 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
6974                                            FILE_NOTIFY_CHANGE_FILE_NAME |
6975                                            FILE_NOTIFY_CHANGE_DIR_NAME |
6976                                            FILE_NOTIFY_CHANGE_ATTRIBUTES |
6977                                            FILE_NOTIFY_CHANGE_LAST_WRITE,
6978                                            false, print_notifies, NULL);
6979                 if (req1 == NULL) {
6980                         d_printf("Could not create notify request\n");
6981                         return false;
6982                 }
6983
6984                 req2 = torture_createdels_send(talloc_tos(), ev, cli,
6985                                                base_fname, 10, torture_numops);
6986                 if (req2 == NULL) {
6987                         d_printf("Could not create createdels request\n");
6988                         return false;
6989                 }
6990                 TALLOC_FREE(base_fname);
6991
6992                 tevent_req_set_callback(req2, notify_bench_done,
6993                                         &num_finished);
6994         }
6995
6996         while (num_finished < num_unc_names) {
6997                 int ret;
6998                 ret = tevent_loop_once(ev);
6999                 if (ret != 0) {
7000                         d_printf("tevent_loop_once failed\n");
7001                         return false;
7002                 }
7003         }
7004
7005         if (!tevent_req_poll(req2, ev)) {
7006                 d_printf("tevent_req_poll failed\n");
7007         }
7008
7009         status = torture_createdels_recv(req2);
7010         d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
7011
7012         return true;
7013 }
7014
7015 static bool run_mangle1(int dummy)
7016 {
7017         struct cli_state *cli;
7018         const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
7019         uint16_t fnum;
7020         fstring alt_name;
7021         NTSTATUS status;
7022         time_t change_time, access_time, write_time;
7023         off_t size;
7024         uint16_t mode;
7025
7026         printf("starting mangle1 test\n");
7027         if (!torture_open_connection(&cli, 0)) {
7028                 return False;
7029         }
7030
7031         smbXcli_conn_set_sockopt(cli->conn, sockops);
7032
7033         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
7034                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
7035                               0, 0, &fnum);
7036         if (!NT_STATUS_IS_OK(status)) {
7037                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
7038                 return false;
7039         }
7040         cli_close(cli, fnum);
7041
7042         status = cli_qpathinfo_alt_name(cli, fname, alt_name);
7043         if (!NT_STATUS_IS_OK(status)) {
7044                 d_printf("cli_qpathinfo_alt_name failed: %s\n",
7045                          nt_errstr(status));
7046                 return false;
7047         }
7048         d_printf("alt_name: %s\n", alt_name);
7049
7050         status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
7051         if (!NT_STATUS_IS_OK(status)) {
7052                 d_printf("cli_openx(%s) failed: %s\n", alt_name,
7053                          nt_errstr(status));
7054                 return false;
7055         }
7056         cli_close(cli, fnum);
7057
7058         status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
7059                                 &write_time, &size, &mode);
7060         if (!NT_STATUS_IS_OK(status)) {
7061                 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
7062                          nt_errstr(status));
7063                 return false;
7064         }
7065
7066         return true;
7067 }
7068
7069 static size_t null_source(uint8_t *buf, size_t n, void *priv)
7070 {
7071         size_t *to_pull = (size_t *)priv;
7072         size_t thistime = *to_pull;
7073
7074         thistime = MIN(thistime, n);
7075         if (thistime == 0) {
7076                 return 0;
7077         }
7078
7079         memset(buf, 0, thistime);
7080         *to_pull -= thistime;
7081         return thistime;
7082 }
7083
7084 static bool run_windows_write(int dummy)
7085 {
7086         struct cli_state *cli1;
7087         uint16_t fnum;
7088         int i;
7089         bool ret = false;
7090         const char *fname = "\\writetest.txt";
7091         struct timeval start_time;
7092         double seconds;
7093         double kbytes;
7094         NTSTATUS status;
7095
7096         printf("starting windows_write test\n");
7097         if (!torture_open_connection(&cli1, 0)) {
7098                 return False;
7099         }
7100
7101         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
7102         if (!NT_STATUS_IS_OK(status)) {
7103                 printf("open failed (%s)\n", nt_errstr(status));
7104                 return False;
7105         }
7106
7107         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7108
7109         start_time = timeval_current();
7110
7111         for (i=0; i<torture_numops; i++) {
7112                 uint8_t c = 0;
7113                 off_t start = i * torture_blocksize;
7114                 size_t to_pull = torture_blocksize - 1;
7115
7116                 status = cli_writeall(cli1, fnum, 0, &c,
7117                                       start + torture_blocksize - 1, 1, NULL);
7118                 if (!NT_STATUS_IS_OK(status)) {
7119                         printf("cli_write failed: %s\n", nt_errstr(status));
7120                         goto fail;
7121                 }
7122
7123                 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
7124                                   null_source, &to_pull);
7125                 if (!NT_STATUS_IS_OK(status)) {
7126                         printf("cli_push returned: %s\n", nt_errstr(status));
7127                         goto fail;
7128                 }
7129         }
7130
7131         seconds = timeval_elapsed(&start_time);
7132         kbytes = (double)torture_blocksize * torture_numops;
7133         kbytes /= 1024;
7134
7135         printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
7136                (double)seconds, (int)(kbytes/seconds));
7137
7138         ret = true;
7139  fail:
7140         cli_close(cli1, fnum);
7141         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7142         torture_close_connection(cli1);
7143         return ret;
7144 }
7145
7146 static bool run_cli_echo(int dummy)
7147 {
7148         struct cli_state *cli;
7149         NTSTATUS status;
7150
7151         printf("starting cli_echo test\n");
7152         if (!torture_open_connection(&cli, 0)) {
7153                 return false;
7154         }
7155         smbXcli_conn_set_sockopt(cli->conn, sockops);
7156
7157         status = cli_echo(cli, 5, data_blob_const("hello", 5));
7158
7159         d_printf("cli_echo returned %s\n", nt_errstr(status));
7160
7161         torture_close_connection(cli);
7162         return NT_STATUS_IS_OK(status);
7163 }
7164
7165 static bool run_uid_regression_test(int dummy)
7166 {
7167         static struct cli_state *cli;
7168         int16_t old_vuid;
7169         int16_t old_cnum;
7170         bool correct = True;
7171         NTSTATUS status;
7172
7173         printf("starting uid regression test\n");
7174
7175         if (!torture_open_connection(&cli, 0)) {
7176                 return False;
7177         }
7178
7179         smbXcli_conn_set_sockopt(cli->conn, sockops);
7180
7181         /* Ok - now save then logoff our current user. */
7182         old_vuid = cli_state_get_uid(cli);
7183
7184         status = cli_ulogoff(cli);
7185         if (!NT_STATUS_IS_OK(status)) {
7186                 d_printf("(%s) cli_ulogoff failed: %s\n",
7187                          __location__, nt_errstr(status));
7188                 correct = false;
7189                 goto out;
7190         }
7191
7192         cli_state_set_uid(cli, old_vuid);
7193
7194         /* Try an operation. */
7195         status = cli_mkdir(cli, "\\uid_reg_test");
7196         if (NT_STATUS_IS_OK(status)) {
7197                 d_printf("(%s) cli_mkdir succeeded\n",
7198                          __location__);
7199                 correct = false;
7200                 goto out;
7201         } else {
7202                 /* Should be bad uid. */
7203                 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
7204                                  NT_STATUS_USER_SESSION_DELETED)) {
7205                         correct = false;
7206                         goto out;
7207                 }
7208         }
7209
7210         old_cnum = cli_state_get_tid(cli);
7211
7212         /* Now try a SMBtdis with the invald vuid set to zero. */
7213         cli_state_set_uid(cli, 0);
7214
7215         /* This should succeed. */
7216         status = cli_tdis(cli);
7217
7218         if (NT_STATUS_IS_OK(status)) {
7219                 d_printf("First tdis with invalid vuid should succeed.\n");
7220         } else {
7221                 d_printf("First tdis failed (%s)\n", nt_errstr(status));
7222                 correct = false;
7223                 goto out;
7224         }
7225
7226         cli_state_set_uid(cli, old_vuid);
7227         cli_state_set_tid(cli, old_cnum);
7228
7229         /* This should fail. */
7230         status = cli_tdis(cli);
7231         if (NT_STATUS_IS_OK(status)) {
7232                 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
7233                 correct = false;
7234                 goto out;
7235         } else {
7236                 /* Should be bad tid. */
7237                 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
7238                                 NT_STATUS_NETWORK_NAME_DELETED)) {
7239                         correct = false;
7240                         goto out;
7241                 }
7242         }
7243
7244         cli_rmdir(cli, "\\uid_reg_test");
7245
7246   out:
7247
7248         cli_shutdown(cli);
7249         return correct;
7250 }
7251
7252
7253 static const char *illegal_chars = "*\\/?<>|\":";
7254 static char force_shortname_chars[] = " +,.[];=\177";
7255
7256 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
7257                              const char *mask, void *state)
7258 {
7259         struct cli_state *pcli = (struct cli_state *)state;
7260         fstring fname;
7261         NTSTATUS status = NT_STATUS_OK;
7262
7263         slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
7264
7265         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
7266                 return NT_STATUS_OK;
7267
7268         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
7269                 status = cli_rmdir(pcli, fname);
7270                 if (!NT_STATUS_IS_OK(status)) {
7271                         printf("del_fn: failed to rmdir %s\n,", fname );
7272                 }
7273         } else {
7274                 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7275                 if (!NT_STATUS_IS_OK(status)) {
7276                         printf("del_fn: failed to unlink %s\n,", fname );
7277                 }
7278         }
7279         return status;
7280 }
7281
7282 struct sn_state {
7283         int matched;
7284         int i;
7285         bool val;
7286 };
7287
7288 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
7289                               const char *name, void *state)
7290 {
7291         struct sn_state *s = (struct sn_state  *)state;
7292         int i = s->i;
7293
7294 #if 0
7295         printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
7296                 i, finfo->name, finfo->short_name);
7297 #endif
7298
7299         if (strchr(force_shortname_chars, i)) {
7300                 if (!finfo->short_name) {
7301                         /* Shortname not created when it should be. */
7302                         d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
7303                                 __location__, finfo->name, i);
7304                         s->val = true;
7305                 }
7306         } else if (finfo->short_name){
7307                 /* Shortname created when it should not be. */
7308                 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
7309                         __location__, finfo->short_name, finfo->name);
7310                 s->val = true;
7311         }
7312         s->matched += 1;
7313         return NT_STATUS_OK;
7314 }
7315
7316 static bool run_shortname_test(int dummy)
7317 {
7318         static struct cli_state *cli;
7319         bool correct = True;
7320         int i;
7321         struct sn_state s;
7322         char fname[40];
7323         NTSTATUS status;
7324
7325         printf("starting shortname test\n");
7326
7327         if (!torture_open_connection(&cli, 0)) {
7328                 return False;
7329         }
7330
7331         smbXcli_conn_set_sockopt(cli->conn, sockops);
7332
7333         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7334         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7335         cli_rmdir(cli, "\\shortname");
7336
7337         status = cli_mkdir(cli, "\\shortname");
7338         if (!NT_STATUS_IS_OK(status)) {
7339                 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
7340                         __location__, nt_errstr(status));
7341                 correct = false;
7342                 goto out;
7343         }
7344
7345         if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
7346                 correct = false;
7347                 goto out;
7348         }
7349         if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
7350                 correct = false;
7351                 goto out;
7352         }
7353
7354         s.val = false;
7355
7356         for (i = 32; i < 128; i++) {
7357                 uint16_t fnum = (uint16_t)-1;
7358
7359                 s.i = i;
7360
7361                 if (strchr(illegal_chars, i)) {
7362                         continue;
7363                 }
7364                 fname[15] = i;
7365
7366                 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
7367                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum);
7368                 if (!NT_STATUS_IS_OK(status)) {
7369                         d_printf("(%s) cli_nt_create of %s failed: %s\n",
7370                                 __location__, fname, nt_errstr(status));
7371                         correct = false;
7372                         goto out;
7373                 }
7374                 cli_close(cli, fnum);
7375
7376                 s.matched = 0;
7377                 status = cli_list(cli, "\\shortname\\test*.*", 0,
7378                                   shortname_list_fn, &s);
7379                 if (s.matched != 1) {
7380                         d_printf("(%s) failed to list %s: %s\n",
7381                                 __location__, fname, nt_errstr(status));
7382                         correct = false;
7383                         goto out;
7384                 }
7385
7386                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7387                 if (!NT_STATUS_IS_OK(status)) {
7388                         d_printf("(%s) failed to delete %s: %s\n",
7389                                 __location__, fname, nt_errstr(status));
7390                         correct = false;
7391                         goto out;
7392                 }
7393
7394                 if (s.val) {
7395                         correct = false;
7396                         goto out;
7397                 }
7398         }
7399
7400   out:
7401
7402         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7403         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7404         cli_rmdir(cli, "\\shortname");
7405         torture_close_connection(cli);
7406         return correct;
7407 }
7408
7409 static void pagedsearch_cb(struct tevent_req *req)
7410 {
7411         int rc;
7412         struct tldap_message *msg;
7413         char *dn;
7414
7415         rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
7416         if (rc != TLDAP_SUCCESS) {
7417                 d_printf("tldap_search_paged_recv failed: %s\n",
7418                          tldap_err2string(rc));
7419                 return;
7420         }
7421         if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
7422                 TALLOC_FREE(msg);
7423                 return;
7424         }
7425         if (!tldap_entry_dn(msg, &dn)) {
7426                 d_printf("tldap_entry_dn failed\n");
7427                 return;
7428         }
7429         d_printf("%s\n", dn);
7430         TALLOC_FREE(msg);
7431 }
7432
7433 static bool run_tldap(int dummy)
7434 {
7435         struct tldap_context *ld;
7436         int fd, rc;
7437         NTSTATUS status;
7438         struct sockaddr_storage addr;
7439         struct tevent_context *ev;
7440         struct tevent_req *req;
7441         char *basedn;
7442         const char *filter;
7443
7444         if (!resolve_name(host, &addr, 0, false)) {
7445                 d_printf("could not find host %s\n", host);
7446                 return false;
7447         }
7448         status = open_socket_out(&addr, 389, 9999, &fd);
7449         if (!NT_STATUS_IS_OK(status)) {
7450                 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
7451                 return false;
7452         }
7453
7454         ld = tldap_context_create(talloc_tos(), fd);
7455         if (ld == NULL) {
7456                 close(fd);
7457                 d_printf("tldap_context_create failed\n");
7458                 return false;
7459         }
7460
7461         rc = tldap_fetch_rootdse(ld);
7462         if (rc != TLDAP_SUCCESS) {
7463                 d_printf("tldap_fetch_rootdse failed: %s\n",
7464                          tldap_errstr(talloc_tos(), ld, rc));
7465                 return false;
7466         }
7467
7468         basedn = tldap_talloc_single_attribute(
7469                 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
7470         if (basedn == NULL) {
7471                 d_printf("no defaultNamingContext\n");
7472                 return false;
7473         }
7474         d_printf("defaultNamingContext: %s\n", basedn);
7475
7476         ev = tevent_context_init(talloc_tos());
7477         if (ev == NULL) {
7478                 d_printf("tevent_context_init failed\n");
7479                 return false;
7480         }
7481
7482         req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
7483                                       TLDAP_SCOPE_SUB, "(objectclass=*)",
7484                                       NULL, 0, 0,
7485                                       NULL, 0, NULL, 0, 0, 0, 0, 5);
7486         if (req == NULL) {
7487                 d_printf("tldap_search_paged_send failed\n");
7488                 return false;
7489         }
7490         tevent_req_set_callback(req, pagedsearch_cb, NULL);
7491
7492         tevent_req_poll(req, ev);
7493
7494         TALLOC_FREE(req);
7495
7496         /* test search filters against rootDSE */
7497         filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
7498                    "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
7499
7500         rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
7501                           NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
7502                           talloc_tos(), NULL, NULL);
7503         if (rc != TLDAP_SUCCESS) {
7504                 d_printf("tldap_search with complex filter failed: %s\n",
7505                          tldap_errstr(talloc_tos(), ld, rc));
7506                 return false;
7507         }
7508
7509         TALLOC_FREE(ld);
7510         return true;
7511 }
7512
7513 /* Torture test to ensure no regression of :
7514 https://bugzilla.samba.org/show_bug.cgi?id=7084
7515 */
7516
7517 static bool run_dir_createtime(int dummy)
7518 {
7519         struct cli_state *cli;
7520         const char *dname = "\\testdir";
7521         const char *fname = "\\testdir\\testfile";
7522         NTSTATUS status;
7523         struct timespec create_time;
7524         struct timespec create_time1;
7525         uint16_t fnum;
7526         bool ret = false;
7527
7528         if (!torture_open_connection(&cli, 0)) {
7529                 return false;
7530         }
7531
7532         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7533         cli_rmdir(cli, dname);
7534
7535         status = cli_mkdir(cli, dname);
7536         if (!NT_STATUS_IS_OK(status)) {
7537                 printf("mkdir failed: %s\n", nt_errstr(status));
7538                 goto out;
7539         }
7540
7541         status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
7542                                 NULL, NULL, NULL);
7543         if (!NT_STATUS_IS_OK(status)) {
7544                 printf("cli_qpathinfo2 returned %s\n",
7545                        nt_errstr(status));
7546                 goto out;
7547         }
7548
7549         /* Sleep 3 seconds, then create a file. */
7550         sleep(3);
7551
7552         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
7553                          DENY_NONE, &fnum);
7554         if (!NT_STATUS_IS_OK(status)) {
7555                 printf("cli_openx failed: %s\n", nt_errstr(status));
7556                 goto out;
7557         }
7558
7559         status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
7560                                 NULL, NULL, NULL);
7561         if (!NT_STATUS_IS_OK(status)) {
7562                 printf("cli_qpathinfo2 (2) returned %s\n",
7563                        nt_errstr(status));
7564                 goto out;
7565         }
7566
7567         if (timespec_compare(&create_time1, &create_time)) {
7568                 printf("run_dir_createtime: create time was updated (error)\n");
7569         } else {
7570                 printf("run_dir_createtime: create time was not updated (correct)\n");
7571                 ret = true;
7572         }
7573
7574   out:
7575
7576         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7577         cli_rmdir(cli, dname);
7578         if (!torture_close_connection(cli)) {
7579                 ret = false;
7580         }
7581         return ret;
7582 }
7583
7584
7585 static bool run_streamerror(int dummy)
7586 {
7587         struct cli_state *cli;
7588         const char *dname = "\\testdir";
7589         const char *streamname =
7590                 "testdir:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
7591         NTSTATUS status;
7592         time_t change_time, access_time, write_time;
7593         off_t size;
7594         uint16_t mode, fnum;
7595         bool ret = true;
7596
7597         if (!torture_open_connection(&cli, 0)) {
7598                 return false;
7599         }
7600
7601         cli_unlink(cli, "\\testdir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7602         cli_rmdir(cli, dname);
7603
7604         status = cli_mkdir(cli, dname);
7605         if (!NT_STATUS_IS_OK(status)) {
7606                 printf("mkdir failed: %s\n", nt_errstr(status));
7607                 return false;
7608         }
7609
7610         status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
7611                                 &write_time, &size, &mode);
7612         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7613                 printf("pathinfo returned %s, expected "
7614                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
7615                        nt_errstr(status));
7616                 ret = false;
7617         }
7618
7619         status = cli_ntcreate(cli, streamname, 0x16,
7620                               FILE_READ_DATA|FILE_READ_EA|
7621                               FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
7622                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7623                               FILE_OPEN, 0, 0, &fnum);
7624
7625         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7626                 printf("ntcreate returned %s, expected "
7627                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
7628                        nt_errstr(status));
7629                 ret = false;
7630         }
7631
7632
7633         cli_rmdir(cli, dname);
7634         return ret;
7635 }
7636
7637 static bool run_local_substitute(int dummy)
7638 {
7639         bool ok = true;
7640
7641         ok &= subst_test("%U", "bla", "", -1, -1, "bla");
7642         ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
7643         ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
7644         ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
7645         ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
7646         ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
7647         ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
7648         ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
7649
7650         /* Different captialization rules in sub_basic... */
7651
7652         ok &=  (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
7653                        "blaDOM") == 0);
7654
7655         return ok;
7656 }
7657
7658 static bool run_local_base64(int dummy)
7659 {
7660         int i;
7661         bool ret = true;
7662
7663         for (i=1; i<2000; i++) {
7664                 DATA_BLOB blob1, blob2;
7665                 char *b64;
7666
7667                 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
7668                 blob1.length = i;
7669                 generate_random_buffer(blob1.data, blob1.length);
7670
7671                 b64 = base64_encode_data_blob(talloc_tos(), blob1);
7672                 if (b64 == NULL) {
7673                         d_fprintf(stderr, "base64_encode_data_blob failed "
7674                                   "for %d bytes\n", i);
7675                         ret = false;
7676                 }
7677                 blob2 = base64_decode_data_blob(b64);
7678                 TALLOC_FREE(b64);
7679
7680                 if (data_blob_cmp(&blob1, &blob2)) {
7681                         d_fprintf(stderr, "data_blob_cmp failed for %d "
7682                                   "bytes\n", i);
7683                         ret = false;
7684                 }
7685                 TALLOC_FREE(blob1.data);
7686                 data_blob_free(&blob2);
7687         }
7688         return ret;
7689 }
7690
7691 static bool run_local_gencache(int dummy)
7692 {
7693         char *val;
7694         time_t tm;
7695         DATA_BLOB blob;
7696
7697         if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
7698                 d_printf("%s: gencache_set() failed\n", __location__);
7699                 return False;
7700         }
7701
7702         if (!gencache_get("foo", NULL, NULL)) {
7703                 d_printf("%s: gencache_get() failed\n", __location__);
7704                 return False;
7705         }
7706
7707         if (!gencache_get("foo", &val, &tm)) {
7708                 d_printf("%s: gencache_get() failed\n", __location__);
7709                 return False;
7710         }
7711
7712         if (strcmp(val, "bar") != 0) {
7713                 d_printf("%s: gencache_get() returned %s, expected %s\n",
7714                          __location__, val, "bar");
7715                 SAFE_FREE(val);
7716                 return False;
7717         }
7718
7719         SAFE_FREE(val);
7720
7721         if (!gencache_del("foo")) {
7722                 d_printf("%s: gencache_del() failed\n", __location__);
7723                 return False;
7724         }
7725         if (gencache_del("foo")) {
7726                 d_printf("%s: second gencache_del() succeeded\n",
7727                          __location__);
7728                 return False;
7729         }
7730
7731         if (gencache_get("foo", &val, &tm)) {
7732                 d_printf("%s: gencache_get() on deleted entry "
7733                          "succeeded\n", __location__);
7734                 return False;
7735         }
7736
7737         blob = data_blob_string_const_null("bar");
7738         tm = time(NULL) + 60;
7739
7740         if (!gencache_set_data_blob("foo", &blob, tm)) {
7741                 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
7742                 return False;
7743         }
7744
7745         if (!gencache_get_data_blob("foo", &blob, NULL, NULL)) {
7746                 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
7747                 return False;
7748         }
7749
7750         if (strcmp((const char *)blob.data, "bar") != 0) {
7751                 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
7752                          __location__, (const char *)blob.data, "bar");
7753                 data_blob_free(&blob);
7754                 return False;
7755         }
7756
7757         data_blob_free(&blob);
7758
7759         if (!gencache_del("foo")) {
7760                 d_printf("%s: gencache_del() failed\n", __location__);
7761                 return False;
7762         }
7763         if (gencache_del("foo")) {
7764                 d_printf("%s: second gencache_del() succeeded\n",
7765                          __location__);
7766                 return False;
7767         }
7768
7769         if (gencache_get_data_blob("foo", &blob, NULL, NULL)) {
7770                 d_printf("%s: gencache_get_data_blob() on deleted entry "
7771                          "succeeded\n", __location__);
7772                 return False;
7773         }
7774
7775         return True;
7776 }
7777
7778 static bool rbt_testval(struct db_context *db, const char *key,
7779                         const char *value)
7780 {
7781         struct db_record *rec;
7782         TDB_DATA data = string_tdb_data(value);
7783         bool ret = false;
7784         NTSTATUS status;
7785         TDB_DATA dbvalue;
7786
7787         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
7788         if (rec == NULL) {
7789                 d_fprintf(stderr, "fetch_locked failed\n");
7790                 goto done;
7791         }
7792         status = dbwrap_record_store(rec, data, 0);
7793         if (!NT_STATUS_IS_OK(status)) {
7794                 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
7795                 goto done;
7796         }
7797         TALLOC_FREE(rec);
7798
7799         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
7800         if (rec == NULL) {
7801                 d_fprintf(stderr, "second fetch_locked failed\n");
7802                 goto done;
7803         }
7804
7805         dbvalue = dbwrap_record_get_value(rec);
7806         if ((dbvalue.dsize != data.dsize)
7807             || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
7808                 d_fprintf(stderr, "Got wrong data back\n");
7809                 goto done;
7810         }
7811
7812         ret = true;
7813  done:
7814         TALLOC_FREE(rec);
7815         return ret;
7816 }
7817
7818 static bool run_local_rbtree(int dummy)
7819 {
7820         struct db_context *db;
7821         bool ret = false;
7822         int i;
7823
7824         db = db_open_rbt(NULL);
7825
7826         if (db == NULL) {
7827                 d_fprintf(stderr, "db_open_rbt failed\n");
7828                 return false;
7829         }
7830
7831         for (i=0; i<1000; i++) {
7832                 char *key, *value;
7833
7834                 if (asprintf(&key, "key%ld", random()) == -1) {
7835                         goto done;
7836                 }
7837                 if (asprintf(&value, "value%ld", random()) == -1) {
7838                         SAFE_FREE(key);
7839                         goto done;
7840                 }
7841
7842                 if (!rbt_testval(db, key, value)) {
7843                         SAFE_FREE(key);
7844                         SAFE_FREE(value);
7845                         goto done;
7846                 }
7847
7848                 SAFE_FREE(value);
7849                 if (asprintf(&value, "value%ld", random()) == -1) {
7850                         SAFE_FREE(key);
7851                         goto done;
7852                 }
7853
7854                 if (!rbt_testval(db, key, value)) {
7855                         SAFE_FREE(key);
7856                         SAFE_FREE(value);
7857                         goto done;
7858                 }
7859
7860                 SAFE_FREE(key);
7861                 SAFE_FREE(value);
7862         }
7863
7864         ret = true;
7865
7866  done:
7867         TALLOC_FREE(db);
7868         return ret;
7869 }
7870
7871
7872 /*
7873   local test for character set functions
7874
7875   This is a very simple test for the functionality in convert_string_error()
7876  */
7877 static bool run_local_convert_string(int dummy)
7878 {
7879         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
7880         const char *test_strings[2] = { "March", "M\303\244rz" };
7881         char dst[7];
7882         int i;
7883
7884         for (i=0; i<2; i++) {
7885                 const char *str = test_strings[i];
7886                 int len = strlen(str);
7887                 size_t converted_size;
7888                 bool ret;
7889
7890                 memset(dst, 'X', sizeof(dst));
7891
7892                 /* first try with real source length */
7893                 ret = convert_string_error(CH_UNIX, CH_UTF8,
7894                                            str, len,
7895                                            dst, sizeof(dst),
7896                                            &converted_size);
7897                 if (ret != true) {
7898                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
7899                         goto failed;
7900                 }
7901
7902                 if (converted_size != len) {
7903                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
7904                                   str, len, (int)converted_size);
7905                         goto failed;
7906                 }
7907
7908                 if (strncmp(str, dst, converted_size) != 0) {
7909                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
7910                         goto failed;
7911                 }
7912
7913                 if (strlen(str) != converted_size) {
7914                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
7915                                   (int)strlen(str), (int)converted_size);
7916                         goto failed;
7917                 }
7918
7919                 if (dst[converted_size] != 'X') {
7920                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
7921                         goto failed;
7922                 }
7923
7924                 /* now with srclen==-1, this causes the nul to be
7925                  * converted too */
7926                 ret = convert_string_error(CH_UNIX, CH_UTF8,
7927                                            str, -1,
7928                                            dst, sizeof(dst),
7929                                            &converted_size);
7930                 if (ret != true) {
7931                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
7932                         goto failed;
7933                 }
7934
7935                 if (converted_size != len+1) {
7936                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
7937                                   str, len, (int)converted_size);
7938                         goto failed;
7939                 }
7940
7941                 if (strncmp(str, dst, converted_size) != 0) {
7942                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
7943                         goto failed;
7944                 }
7945
7946                 if (len+1 != converted_size) {
7947                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
7948                                   len+1, (int)converted_size);
7949                         goto failed;
7950                 }
7951
7952                 if (dst[converted_size] != 'X') {
7953                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
7954                         goto failed;
7955                 }
7956
7957         }
7958
7959
7960         TALLOC_FREE(tmp_ctx);
7961         return true;
7962 failed:
7963         TALLOC_FREE(tmp_ctx);
7964         return false;
7965 }
7966
7967
7968 struct talloc_dict_test {
7969         int content;
7970 };
7971
7972 static int talloc_dict_traverse_fn(DATA_BLOB key, void *data, void *priv)
7973 {
7974         int *count = (int *)priv;
7975         *count += 1;
7976         return 0;
7977 }
7978
7979 static bool run_local_talloc_dict(int dummy)
7980 {
7981         struct talloc_dict *dict;
7982         struct talloc_dict_test *t;
7983         int key, count, res;
7984         bool ok;
7985
7986         dict = talloc_dict_init(talloc_tos());
7987         if (dict == NULL) {
7988                 return false;
7989         }
7990
7991         t = talloc(talloc_tos(), struct talloc_dict_test);
7992         if (t == NULL) {
7993                 return false;
7994         }
7995
7996         key = 1;
7997         t->content = 1;
7998         ok = talloc_dict_set(dict, data_blob_const(&key, sizeof(key)), &t);
7999         if (!ok) {
8000                 return false;
8001         }
8002
8003         count = 0;
8004         res = talloc_dict_traverse(dict, talloc_dict_traverse_fn, &count);
8005         if (res == -1) {
8006                 return false;
8007         }
8008
8009         if (count != 1) {
8010                 return false;
8011         }
8012
8013         if (count != res) {
8014                 return false;
8015         }
8016
8017         TALLOC_FREE(dict);
8018
8019         return true;
8020 }
8021
8022 static bool run_local_string_to_sid(int dummy) {
8023         struct dom_sid sid;
8024
8025         if (string_to_sid(&sid, "S--1-5-32-545")) {
8026                 printf("allowing S--1-5-32-545\n");
8027                 return false;
8028         }
8029         if (string_to_sid(&sid, "S-1-5-32-+545")) {
8030                 printf("allowing S-1-5-32-+545\n");
8031                 return false;
8032         }
8033         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")) {
8034                 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
8035                 return false;
8036         }
8037         if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
8038                 printf("allowing S-1-5-32-545-abc\n");
8039                 return false;
8040         }
8041         if (!string_to_sid(&sid, "S-1-5-32-545")) {
8042                 printf("could not parse S-1-5-32-545\n");
8043                 return false;
8044         }
8045         if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
8046                 printf("mis-parsed S-1-5-32-545 as %s\n",
8047                        sid_string_tos(&sid));
8048                 return false;
8049         }
8050         return true;
8051 }
8052
8053 static bool run_local_binary_to_sid(int dummy) {
8054         struct dom_sid *sid = talloc(NULL, struct dom_sid);
8055         static const char good_binary_sid[] = {
8056                 0x1, /* revision number */
8057                 15, /* num auths */
8058                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8059                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8060                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8061                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8062                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8063                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8064                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8065                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8066                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8067                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8068                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8069                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8070                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8071                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8072                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8073                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8074         };
8075
8076         static const char long_binary_sid[] = {
8077                 0x1, /* revision number */
8078                 15, /* num auths */
8079                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8080                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8081                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8082                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8083                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8084                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8085                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8086                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8087                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8088                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8089                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8090                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8091                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8092                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8093                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8094                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8095                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
8096                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
8097                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
8098         };
8099
8100         static const char long_binary_sid2[] = {
8101                 0x1, /* revision number */
8102                 32, /* num auths */
8103                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8104                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8105                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8106                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8107                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8108                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8109                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8110                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8111                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8112                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8113                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8114                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8115                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8116                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8117                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8118                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8119                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
8120                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
8121                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
8122                 0x1, 0x1, 0x1, 0x1, /* auth[18] */
8123                 0x1, 0x1, 0x1, 0x1, /* auth[19] */
8124                 0x1, 0x1, 0x1, 0x1, /* auth[20] */
8125                 0x1, 0x1, 0x1, 0x1, /* auth[21] */
8126                 0x1, 0x1, 0x1, 0x1, /* auth[22] */
8127                 0x1, 0x1, 0x1, 0x1, /* auth[23] */
8128                 0x1, 0x1, 0x1, 0x1, /* auth[24] */
8129                 0x1, 0x1, 0x1, 0x1, /* auth[25] */
8130                 0x1, 0x1, 0x1, 0x1, /* auth[26] */
8131                 0x1, 0x1, 0x1, 0x1, /* auth[27] */
8132                 0x1, 0x1, 0x1, 0x1, /* auth[28] */
8133                 0x1, 0x1, 0x1, 0x1, /* auth[29] */
8134                 0x1, 0x1, 0x1, 0x1, /* auth[30] */
8135                 0x1, 0x1, 0x1, 0x1, /* auth[31] */
8136         };
8137
8138         if (!sid_parse(good_binary_sid, sizeof(good_binary_sid), sid)) {
8139                 return false;
8140         }
8141         if (sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid)) {
8142                 return false;
8143         }
8144         if (sid_parse(long_binary_sid, sizeof(long_binary_sid), sid)) {
8145                 return false;
8146         }
8147         return true;
8148 }
8149
8150 /* Split a path name into filename and stream name components. Canonicalise
8151  * such that an implicit $DATA token is always explicit.
8152  *
8153  * The "specification" of this function can be found in the
8154  * run_local_stream_name() function in torture.c, I've tried those
8155  * combinations against a W2k3 server.
8156  */
8157
8158 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
8159                                        char **pbase, char **pstream)
8160 {
8161         char *base = NULL;
8162         char *stream = NULL;
8163         char *sname; /* stream name */
8164         const char *stype; /* stream type */
8165
8166         DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
8167
8168         sname = strchr_m(fname, ':');
8169
8170         if (lp_posix_pathnames() || (sname == NULL)) {
8171                 if (pbase != NULL) {
8172                         base = talloc_strdup(mem_ctx, fname);
8173                         NT_STATUS_HAVE_NO_MEMORY(base);
8174                 }
8175                 goto done;
8176         }
8177
8178         if (pbase != NULL) {
8179                 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
8180                 NT_STATUS_HAVE_NO_MEMORY(base);
8181         }
8182
8183         sname += 1;
8184
8185         stype = strchr_m(sname, ':');
8186
8187         if (stype == NULL) {
8188                 sname = talloc_strdup(mem_ctx, sname);
8189                 stype = "$DATA";
8190         }
8191         else {
8192                 if (strcasecmp_m(stype, ":$DATA") != 0) {
8193                         /*
8194                          * If there is an explicit stream type, so far we only
8195                          * allow $DATA. Is there anything else allowed? -- vl
8196                          */
8197                         DEBUG(10, ("[%s] is an invalid stream type\n", stype));
8198                         TALLOC_FREE(base);
8199                         return NT_STATUS_OBJECT_NAME_INVALID;
8200                 }
8201                 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
8202                 stype += 1;
8203         }
8204
8205         if (sname == NULL) {
8206                 TALLOC_FREE(base);
8207                 return NT_STATUS_NO_MEMORY;
8208         }
8209
8210         if (sname[0] == '\0') {
8211                 /*
8212                  * no stream name, so no stream
8213                  */
8214                 goto done;
8215         }
8216
8217         if (pstream != NULL) {
8218                 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
8219                 if (stream == NULL) {
8220                         TALLOC_FREE(sname);
8221                         TALLOC_FREE(base);
8222                         return NT_STATUS_NO_MEMORY;
8223                 }
8224                 /*
8225                  * upper-case the type field
8226                  */
8227                 strupper_m(strchr_m(stream, ':')+1);
8228         }
8229
8230  done:
8231         if (pbase != NULL) {
8232                 *pbase = base;
8233         }
8234         if (pstream != NULL) {
8235                 *pstream = stream;
8236         }
8237         return NT_STATUS_OK;
8238 }
8239
8240 static bool test_stream_name(const char *fname, const char *expected_base,
8241                              const char *expected_stream,
8242                              NTSTATUS expected_status)
8243 {
8244         NTSTATUS status;
8245         char *base = NULL;
8246         char *stream = NULL;
8247
8248         status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
8249         if (!NT_STATUS_EQUAL(status, expected_status)) {
8250                 goto error;
8251         }
8252
8253         if (!NT_STATUS_IS_OK(status)) {
8254                 return true;
8255         }
8256
8257         if (base == NULL) goto error;
8258
8259         if (strcmp(expected_base, base) != 0) goto error;
8260
8261         if ((expected_stream != NULL) && (stream == NULL)) goto error;
8262         if ((expected_stream == NULL) && (stream != NULL)) goto error;
8263
8264         if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
8265                 goto error;
8266
8267         TALLOC_FREE(base);
8268         TALLOC_FREE(stream);
8269         return true;
8270
8271  error:
8272         d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
8273                   fname, expected_base ? expected_base : "<NULL>",
8274                   expected_stream ? expected_stream : "<NULL>",
8275                   nt_errstr(expected_status));
8276         d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
8277                   base ? base : "<NULL>", stream ? stream : "<NULL>",
8278                   nt_errstr(status));
8279         TALLOC_FREE(base);
8280         TALLOC_FREE(stream);
8281         return false;
8282 }
8283
8284 static bool run_local_stream_name(int dummy)
8285 {
8286         bool ret = true;
8287
8288         ret &= test_stream_name(
8289                 "bla", "bla", NULL, NT_STATUS_OK);
8290         ret &= test_stream_name(
8291                 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
8292         ret &= test_stream_name(
8293                 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8294         ret &= test_stream_name(
8295                 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
8296         ret &= test_stream_name(
8297                 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8298         ret &= test_stream_name(
8299                 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
8300         ret &= test_stream_name(
8301                 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
8302         ret &= test_stream_name(
8303                 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
8304
8305         return ret;
8306 }
8307
8308 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
8309 {
8310         if (a.length != b.length) {
8311                 printf("a.length=%d != b.length=%d\n",
8312                        (int)a.length, (int)b.length);
8313                 return false;
8314         }
8315         if (memcmp(a.data, b.data, a.length) != 0) {
8316                 printf("a.data and b.data differ\n");
8317                 return false;
8318         }
8319         return true;
8320 }
8321
8322 static bool run_local_memcache(int dummy)
8323 {
8324         struct memcache *cache;
8325         DATA_BLOB k1, k2;
8326         DATA_BLOB d1, d2, d3;
8327         DATA_BLOB v1, v2, v3;
8328
8329         TALLOC_CTX *mem_ctx;
8330         char *str1, *str2;
8331         size_t size1, size2;
8332         bool ret = false;
8333
8334         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
8335
8336         if (cache == NULL) {
8337                 printf("memcache_init failed\n");
8338                 return false;
8339         }
8340
8341         d1 = data_blob_const("d1", 2);
8342         d2 = data_blob_const("d2", 2);
8343         d3 = data_blob_const("d3", 2);
8344
8345         k1 = data_blob_const("d1", 2);
8346         k2 = data_blob_const("d2", 2);
8347
8348         memcache_add(cache, STAT_CACHE, k1, d1);
8349         memcache_add(cache, GETWD_CACHE, k2, d2);
8350
8351         if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
8352                 printf("could not find k1\n");
8353                 return false;
8354         }
8355         if (!data_blob_equal(d1, v1)) {
8356                 return false;
8357         }
8358
8359         if (!memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8360                 printf("could not find k2\n");
8361                 return false;
8362         }
8363         if (!data_blob_equal(d2, v2)) {
8364                 return false;
8365         }
8366
8367         memcache_add(cache, STAT_CACHE, k1, d3);
8368
8369         if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
8370                 printf("could not find replaced k1\n");
8371                 return false;
8372         }
8373         if (!data_blob_equal(d3, v3)) {
8374                 return false;
8375         }
8376
8377         memcache_add(cache, GETWD_CACHE, k1, d1);
8378
8379         if (memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8380                 printf("Did find k2, should have been purged\n");
8381                 return false;
8382         }
8383
8384         TALLOC_FREE(cache);
8385
8386         cache = memcache_init(NULL, 0);
8387
8388         mem_ctx = talloc_init("foo");
8389
8390         str1 = talloc_strdup(mem_ctx, "string1");
8391         str2 = talloc_strdup(mem_ctx, "string2");
8392
8393         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8394                             data_blob_string_const("torture"), &str1);
8395         size1 = talloc_total_size(cache);
8396
8397         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8398                             data_blob_string_const("torture"), &str2);
8399         size2 = talloc_total_size(cache);
8400
8401         printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
8402
8403         if (size2 > size1) {
8404                 printf("memcache leaks memory!\n");
8405                 goto fail;
8406         }
8407
8408         ret = true;
8409  fail:
8410         TALLOC_FREE(cache);
8411         return ret;
8412 }
8413
8414 static void wbclient_done(struct tevent_req *req)
8415 {
8416         wbcErr wbc_err;
8417         struct winbindd_response *wb_resp;
8418         int *i = (int *)tevent_req_callback_data_void(req);
8419
8420         wbc_err = wb_trans_recv(req, req, &wb_resp);
8421         TALLOC_FREE(req);
8422         *i += 1;
8423         d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
8424 }
8425
8426 static bool run_local_wbclient(int dummy)
8427 {
8428         struct event_context *ev;
8429         struct wb_context **wb_ctx;
8430         struct winbindd_request wb_req;
8431         bool result = false;
8432         int i, j;
8433
8434         BlockSignals(True, SIGPIPE);
8435
8436         ev = tevent_context_init_byname(talloc_tos(), "epoll");
8437         if (ev == NULL) {
8438                 goto fail;
8439         }
8440
8441         wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
8442         if (wb_ctx == NULL) {
8443                 goto fail;
8444         }
8445
8446         ZERO_STRUCT(wb_req);
8447         wb_req.cmd = WINBINDD_PING;
8448
8449         d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
8450
8451         for (i=0; i<torture_nprocs; i++) {
8452                 wb_ctx[i] = wb_context_init(ev, NULL);
8453                 if (wb_ctx[i] == NULL) {
8454                         goto fail;
8455                 }
8456                 for (j=0; j<torture_numops; j++) {
8457                         struct tevent_req *req;
8458                         req = wb_trans_send(ev, ev, wb_ctx[i],
8459                                             (j % 2) == 0, &wb_req);
8460                         if (req == NULL) {
8461                                 goto fail;
8462                         }
8463                         tevent_req_set_callback(req, wbclient_done, &i);
8464                 }
8465         }
8466
8467         i = 0;
8468
8469         while (i < torture_nprocs * torture_numops) {
8470                 tevent_loop_once(ev);
8471         }
8472
8473         result = true;
8474  fail:
8475         TALLOC_FREE(ev);
8476         return result;
8477 }
8478
8479 static void getaddrinfo_finished(struct tevent_req *req)
8480 {
8481         char *name = (char *)tevent_req_callback_data_void(req);
8482         struct addrinfo *ainfo;
8483         int res;
8484
8485         res = getaddrinfo_recv(req, &ainfo);
8486         if (res != 0) {
8487                 d_printf("gai(%s) returned %s\n", name, gai_strerror(res));
8488                 return;
8489         }
8490         d_printf("gai(%s) succeeded\n", name);
8491         freeaddrinfo(ainfo);
8492 }
8493
8494 static bool run_getaddrinfo_send(int dummy)
8495 {
8496         TALLOC_CTX *frame = talloc_stackframe();
8497         struct fncall_context *ctx;
8498         struct tevent_context *ev;
8499         bool result = false;
8500         const char *names[4] = { "www.samba.org", "notfound.samba.org",
8501                                  "www.slashdot.org", "heise.de" };
8502         struct tevent_req *reqs[4];
8503         int i;
8504
8505         ev = event_context_init(frame);
8506         if (ev == NULL) {
8507                 goto fail;
8508         }
8509
8510         ctx = fncall_context_init(frame, 4);
8511
8512         for (i=0; i<ARRAY_SIZE(names); i++) {
8513                 reqs[i] = getaddrinfo_send(frame, ev, ctx, names[i], NULL,
8514                                            NULL);
8515                 if (reqs[i] == NULL) {
8516                         goto fail;
8517                 }
8518                 tevent_req_set_callback(reqs[i], getaddrinfo_finished,
8519                                         discard_const_p(void, names[i]));
8520         }
8521
8522         for (i=0; i<ARRAY_SIZE(reqs); i++) {
8523                 tevent_loop_once(ev);
8524         }
8525
8526         result = true;
8527 fail:
8528         TALLOC_FREE(frame);
8529         return result;
8530 }
8531
8532 static bool dbtrans_inc(struct db_context *db)
8533 {
8534         struct db_record *rec;
8535         uint32_t val;
8536         bool ret = false;
8537         NTSTATUS status;
8538         TDB_DATA value;
8539
8540         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
8541         if (rec == NULL) {
8542                 printf(__location__ "fetch_lock failed\n");
8543                 return false;
8544         }
8545
8546         value = dbwrap_record_get_value(rec);
8547
8548         if (value.dsize != sizeof(uint32_t)) {
8549                 printf(__location__ "value.dsize = %d\n",
8550                        (int)value.dsize);
8551                 goto fail;
8552         }
8553
8554         memcpy(&val, value.dptr, sizeof(val));
8555         val += 1;
8556
8557         status = dbwrap_record_store(
8558                 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
8559         if (!NT_STATUS_IS_OK(status)) {
8560                 printf(__location__ "store failed: %s\n",
8561                        nt_errstr(status));
8562                 goto fail;
8563         }
8564
8565         ret = true;
8566 fail:
8567         TALLOC_FREE(rec);
8568         return ret;
8569 }
8570
8571 static bool run_local_dbtrans(int dummy)
8572 {
8573         struct db_context *db;
8574         struct db_record *rec;
8575         NTSTATUS status;
8576         uint32_t initial;
8577         int res;
8578         TDB_DATA value;
8579
8580         db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
8581                      O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1);
8582         if (db == NULL) {
8583                 printf("Could not open transtest.db\n");
8584                 return false;
8585         }
8586
8587         res = dbwrap_transaction_start(db);
8588         if (res != 0) {
8589                 printf(__location__ "transaction_start failed\n");
8590                 return false;
8591         }
8592
8593         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
8594         if (rec == NULL) {
8595                 printf(__location__ "fetch_lock failed\n");
8596                 return false;
8597         }
8598
8599         value = dbwrap_record_get_value(rec);
8600
8601         if (value.dptr == NULL) {
8602                 initial = 0;
8603                 status = dbwrap_record_store(
8604                         rec, make_tdb_data((uint8_t *)&initial,
8605                                            sizeof(initial)),
8606                         0);
8607                 if (!NT_STATUS_IS_OK(status)) {
8608                         printf(__location__ "store returned %s\n",
8609                                nt_errstr(status));
8610                         return false;
8611                 }
8612         }
8613
8614         TALLOC_FREE(rec);
8615
8616         res = dbwrap_transaction_commit(db);
8617         if (res != 0) {
8618                 printf(__location__ "transaction_commit failed\n");
8619                 return false;
8620         }
8621
8622         while (true) {
8623                 uint32_t val, val2;
8624                 int i;
8625
8626                 res = dbwrap_transaction_start(db);
8627                 if (res != 0) {
8628                         printf(__location__ "transaction_start failed\n");
8629                         break;
8630                 }
8631
8632                 status = dbwrap_fetch_uint32(db, "transtest", &val);
8633                 if (!NT_STATUS_IS_OK(status)) {
8634                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
8635                                nt_errstr(status));
8636                         break;
8637                 }
8638
8639                 for (i=0; i<10; i++) {
8640                         if (!dbtrans_inc(db)) {
8641                                 return false;
8642                         }
8643                 }
8644
8645                 status = dbwrap_fetch_uint32(db, "transtest", &val2);
8646                 if (!NT_STATUS_IS_OK(status)) {
8647                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
8648                                nt_errstr(status));
8649                         break;
8650                 }
8651
8652                 if (val2 != val + 10) {
8653                         printf(__location__ "val=%d, val2=%d\n",
8654                                (int)val, (int)val2);
8655                         break;
8656                 }
8657
8658                 printf("val2=%d\r", val2);
8659
8660                 res = dbwrap_transaction_commit(db);
8661                 if (res != 0) {
8662                         printf(__location__ "transaction_commit failed\n");
8663                         break;
8664                 }
8665         }
8666
8667         TALLOC_FREE(db);
8668         return true;
8669 }
8670
8671 /*
8672  * Just a dummy test to be run under a debugger. There's no real way
8673  * to inspect the tevent_select specific function from outside of
8674  * tevent_select.c.
8675  */
8676
8677 static bool run_local_tevent_select(int dummy)
8678 {
8679         struct tevent_context *ev;
8680         struct tevent_fd *fd1, *fd2;
8681         bool result = false;
8682
8683         ev = tevent_context_init_byname(NULL, "select");
8684         if (ev == NULL) {
8685                 d_fprintf(stderr, "tevent_context_init_byname failed\n");
8686                 goto fail;
8687         }
8688
8689         fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
8690         if (fd1 == NULL) {
8691                 d_fprintf(stderr, "tevent_add_fd failed\n");
8692                 goto fail;
8693         }
8694         fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
8695         if (fd2 == NULL) {
8696                 d_fprintf(stderr, "tevent_add_fd failed\n");
8697                 goto fail;
8698         }
8699         TALLOC_FREE(fd2);
8700
8701         fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
8702         if (fd2 == NULL) {
8703                 d_fprintf(stderr, "tevent_add_fd failed\n");
8704                 goto fail;
8705         }
8706
8707         result = true;
8708 fail:
8709         TALLOC_FREE(ev);
8710         return result;
8711 }
8712
8713 static bool run_local_hex_encode_buf(int dummy)
8714 {
8715         char buf[17];
8716         uint8_t src[8];
8717         int i;
8718
8719         for (i=0; i<sizeof(src); i++) {
8720                 src[i] = i;
8721         }
8722         hex_encode_buf(buf, src, sizeof(src));
8723         if (strcmp(buf, "0001020304050607") != 0) {
8724                 return false;
8725         }
8726         hex_encode_buf(buf, NULL, 0);
8727         if (buf[0] != '\0') {
8728                 return false;
8729         }
8730         return true;
8731 }
8732
8733 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
8734         "0.0.0.0",
8735         "::0",
8736         "1.2.3.1",
8737         "0.0.0.0",
8738         "0.0.0.0",
8739         "1.2.3.2",
8740         "1.2.3.3",
8741         "1.2.3.4",
8742         "1.2.3.5",
8743         "::0",
8744         "1.2.3.6",
8745         "1.2.3.7",
8746         "::0",
8747         "::0",
8748         "::0",
8749         "1.2.3.8",
8750         "1.2.3.9",
8751         "1.2.3.10",
8752         "1.2.3.11",
8753         "1.2.3.12",
8754         "1.2.3.13",
8755         "1001:1111:1111:1000:0:1111:1111:1111",
8756         "1.2.3.1",
8757         "1.2.3.2",
8758         "1.2.3.3",
8759         "1.2.3.12",
8760         "::0",
8761         "::0"
8762 };
8763
8764 static const char *remove_duplicate_addrs2_test_strings_result[] = {
8765         "1.2.3.1",
8766         "1.2.3.2",
8767         "1.2.3.3",
8768         "1.2.3.4",
8769         "1.2.3.5",
8770         "1.2.3.6",
8771         "1.2.3.7",
8772         "1.2.3.8",
8773         "1.2.3.9",
8774         "1.2.3.10",
8775         "1.2.3.11",
8776         "1.2.3.12",
8777         "1.2.3.13",
8778         "1001:1111:1111:1000:0:1111:1111:1111"
8779 };
8780
8781 static bool run_local_remove_duplicate_addrs2(int dummy)
8782 {
8783         struct ip_service test_vector[28];
8784         int count, i;
8785
8786         /* Construct the sockaddr_storage test vector. */
8787         for (i = 0; i < 28; i++) {
8788                 struct addrinfo hints;
8789                 struct addrinfo *res = NULL;
8790                 int ret;
8791
8792                 memset(&hints, '\0', sizeof(hints));
8793                 hints.ai_flags = AI_NUMERICHOST;
8794                 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
8795                                 NULL,
8796                                 &hints,
8797                                 &res);
8798                 if (ret) {
8799                         fprintf(stderr, "getaddrinfo failed on [%s]\n",
8800                                 remove_duplicate_addrs2_test_strings_vector[i]);
8801                         return false;
8802                 }
8803                 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
8804                 memcpy(&test_vector[i].ss,
8805                         res->ai_addr,
8806                         res->ai_addrlen);
8807                 freeaddrinfo(res);
8808         }
8809
8810         count = remove_duplicate_addrs2(test_vector, i);
8811
8812         if (count != 14) {
8813                 fprintf(stderr, "count wrong (%d) should be 14\n",
8814                         count);
8815                 return false;
8816         }
8817
8818         for (i = 0; i < count; i++) {
8819                 char addr[INET6_ADDRSTRLEN];
8820
8821                 print_sockaddr(addr, sizeof(addr), &test_vector[i].ss);
8822
8823                 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
8824                         fprintf(stderr, "mismatch on [%d] [%s] [%s]\n",
8825                                 i,
8826                                 addr,
8827                                 remove_duplicate_addrs2_test_strings_result[i]);
8828                         return false;
8829                 }
8830         }
8831
8832         printf("run_local_remove_duplicate_addrs2: success\n");
8833         return true;
8834 }
8835
8836 static double create_procs(bool (*fn)(int), bool *result)
8837 {
8838         int i, status;
8839         volatile pid_t *child_status;
8840         volatile bool *child_status_out;
8841         int synccount;
8842         int tries = 8;
8843         struct timeval start;
8844
8845         synccount = 0;
8846
8847         child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*torture_nprocs);
8848         if (!child_status) {
8849                 printf("Failed to setup shared memory\n");
8850                 return -1;
8851         }
8852
8853         child_status_out = (volatile bool *)shm_setup(sizeof(bool)*torture_nprocs);
8854         if (!child_status_out) {
8855                 printf("Failed to setup result status shared memory\n");
8856                 return -1;
8857         }
8858
8859         for (i = 0; i < torture_nprocs; i++) {
8860                 child_status[i] = 0;
8861                 child_status_out[i] = True;
8862         }
8863
8864         start = timeval_current();
8865
8866         for (i=0;i<torture_nprocs;i++) {
8867                 procnum = i;
8868                 if (fork() == 0) {
8869                         pid_t mypid = getpid();
8870                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
8871
8872                         slprintf(myname,sizeof(myname),"CLIENT%d", i);
8873
8874                         while (1) {
8875                                 if (torture_open_connection(&current_cli, i)) break;
8876                                 if (tries-- == 0) {
8877                                         printf("pid %d failed to start\n", (int)getpid());
8878                                         _exit(1);
8879                                 }
8880                                 smb_msleep(10); 
8881                         }
8882
8883                         child_status[i] = getpid();
8884
8885                         while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
8886
8887                         child_status_out[i] = fn(i);
8888                         _exit(0);
8889                 }
8890         }
8891
8892         do {
8893                 synccount = 0;
8894                 for (i=0;i<torture_nprocs;i++) {
8895                         if (child_status[i]) synccount++;
8896                 }
8897                 if (synccount == torture_nprocs) break;
8898                 smb_msleep(10);
8899         } while (timeval_elapsed(&start) < 30);
8900
8901         if (synccount != torture_nprocs) {
8902                 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
8903                 *result = False;
8904                 return timeval_elapsed(&start);
8905         }
8906
8907         /* start the client load */
8908         start = timeval_current();
8909
8910         for (i=0;i<torture_nprocs;i++) {
8911                 child_status[i] = 0;
8912         }
8913
8914         printf("%d clients started\n", torture_nprocs);
8915
8916         for (i=0;i<torture_nprocs;i++) {
8917                 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
8918         }
8919
8920         printf("\n");
8921
8922         for (i=0;i<torture_nprocs;i++) {
8923                 if (!child_status_out[i]) {
8924                         *result = False;
8925                 }
8926         }
8927         return timeval_elapsed(&start);
8928 }
8929
8930 #define FLAG_MULTIPROC 1
8931
8932 static struct {
8933         const char *name;
8934         bool (*fn)(int);
8935         unsigned flags;
8936 } torture_ops[] = {
8937         {"FDPASS", run_fdpasstest, 0},
8938         {"LOCK1",  run_locktest1,  0},
8939         {"LOCK2",  run_locktest2,  0},
8940         {"LOCK3",  run_locktest3,  0},
8941         {"LOCK4",  run_locktest4,  0},
8942         {"LOCK5",  run_locktest5,  0},
8943         {"LOCK6",  run_locktest6,  0},
8944         {"LOCK7",  run_locktest7,  0},
8945         {"LOCK8",  run_locktest8,  0},
8946         {"LOCK9",  run_locktest9,  0},
8947         {"UNLINK", run_unlinktest, 0},
8948         {"BROWSE", run_browsetest, 0},
8949         {"ATTR",   run_attrtest,   0},
8950         {"TRANS2", run_trans2test, 0},
8951         {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
8952         {"TORTURE",run_torture,    FLAG_MULTIPROC},
8953         {"RANDOMIPC", run_randomipc, 0},
8954         {"NEGNOWAIT", run_negprot_nowait, 0},
8955         {"NBENCH",  run_nbench, 0},
8956         {"NBENCH2", run_nbench2, 0},
8957         {"OPLOCK1",  run_oplock1, 0},
8958         {"OPLOCK2",  run_oplock2, 0},
8959         {"OPLOCK4",  run_oplock4, 0},
8960         {"DIR",  run_dirtest, 0},
8961         {"DIR1",  run_dirtest1, 0},
8962         {"DIR-CREATETIME",  run_dir_createtime, 0},
8963         {"DENY1",  torture_denytest1, 0},
8964         {"DENY2",  torture_denytest2, 0},
8965         {"TCON",  run_tcon_test, 0},
8966         {"TCONDEV",  run_tcon_devtype_test, 0},
8967         {"RW1",  run_readwritetest, 0},
8968         {"RW2",  run_readwritemulti, FLAG_MULTIPROC},
8969         {"RW3",  run_readwritelarge, 0},
8970         {"RW-SIGNING",  run_readwritelarge_signtest, 0},
8971         {"OPEN", run_opentest, 0},
8972         {"POSIX", run_simple_posix_open_test, 0},
8973         {"POSIX-APPEND", run_posix_append, 0},
8974         {"CASE-INSENSITIVE-CREATE", run_case_insensitive_create, 0},
8975         {"ASYNC-ECHO", run_async_echo, 0},
8976         { "UID-REGRESSION-TEST", run_uid_regression_test, 0},
8977         { "SHORTNAME-TEST", run_shortname_test, 0},
8978         { "ADDRCHANGE", run_addrchange, 0},
8979 #if 1
8980         {"OPENATTR", run_openattrtest, 0},
8981 #endif
8982         {"XCOPY", run_xcopy, 0},
8983         {"RENAME", run_rename, 0},
8984         {"DELETE", run_deletetest, 0},
8985         {"DELETE-LN", run_deletetest_ln, 0},
8986         {"PROPERTIES", run_properties, 0},
8987         {"MANGLE", torture_mangle, 0},
8988         {"MANGLE1", run_mangle1, 0},
8989         {"W2K", run_w2ktest, 0},
8990         {"TRANS2SCAN", torture_trans2_scan, 0},
8991         {"NTTRANSSCAN", torture_nttrans_scan, 0},
8992         {"UTABLE", torture_utable, 0},
8993         {"CASETABLE", torture_casetable, 0},
8994         {"ERRMAPEXTRACT", run_error_map_extract, 0},
8995         {"PIPE_NUMBER", run_pipe_number, 0},
8996         {"TCON2",  run_tcon2_test, 0},
8997         {"IOCTL",  torture_ioctl_test, 0},
8998         {"CHKPATH",  torture_chkpath_test, 0},
8999         {"FDSESS", run_fdsesstest, 0},
9000         { "EATEST", run_eatest, 0},
9001         { "SESSSETUP_BENCH", run_sesssetup_bench, 0},
9002         { "CHAIN1", run_chain1, 0},
9003         { "CHAIN2", run_chain2, 0},
9004         { "CHAIN3", run_chain3, 0},
9005         { "WINDOWS-WRITE", run_windows_write, 0},
9006         { "NTTRANS-CREATE", run_nttrans_create, 0},
9007         { "NTTRANS-FSCTL", run_nttrans_fsctl, 0},
9008         { "CLI_ECHO", run_cli_echo, 0},
9009         { "GETADDRINFO", run_getaddrinfo_send, 0},
9010         { "TLDAP", run_tldap },
9011         { "STREAMERROR", run_streamerror },
9012         { "NOTIFY-BENCH", run_notify_bench },
9013         { "NOTIFY-BENCH2", run_notify_bench2 },
9014         { "NOTIFY-BENCH3", run_notify_bench3 },
9015         { "BAD-NBT-SESSION", run_bad_nbt_session },
9016         { "SMB-ANY-CONNECT", run_smb_any_connect },
9017         { "NOTIFY-ONLINE", run_notify_online },
9018         { "SMB2-BASIC", run_smb2_basic },
9019         { "SMB2-NEGPROT", run_smb2_negprot },
9020         { "SMB2-SESSION-RECONNECT", run_smb2_session_reconnect },
9021         { "SMB2-TCON-DEPENDENCE", run_smb2_tcon_dependence },
9022         { "SMB2-MULTI-CHANNEL", run_smb2_multi_channel },
9023         { "SMB2-SESSION-REAUTH", run_smb2_session_reauth },
9024         { "CLEANUP1", run_cleanup1 },
9025         { "CLEANUP2", run_cleanup2 },
9026         { "CLEANUP3", run_cleanup3 },
9027         { "LOCAL-SUBSTITUTE", run_local_substitute, 0},
9028         { "LOCAL-GENCACHE", run_local_gencache, 0},
9029         { "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0},
9030         { "LOCAL-CTDB-CONN", run_ctdb_conn, 0},
9031         { "LOCAL-MSG", run_msg_test, 0},
9032         { "LOCAL-DBWRAP-WATCH1", run_dbwrap_watch1, 0 },
9033         { "LOCAL-BASE64", run_local_base64, 0},
9034         { "LOCAL-RBTREE", run_local_rbtree, 0},
9035         { "LOCAL-MEMCACHE", run_local_memcache, 0},
9036         { "LOCAL-STREAM-NAME", run_local_stream_name, 0},
9037         { "LOCAL-WBCLIENT", run_local_wbclient, 0},
9038         { "LOCAL-string_to_sid", run_local_string_to_sid, 0},
9039         { "LOCAL-binary_to_sid", run_local_binary_to_sid, 0},
9040         { "LOCAL-DBTRANS", run_local_dbtrans, 0},
9041         { "LOCAL-TEVENT-SELECT", run_local_tevent_select, 0},
9042         { "LOCAL-CONVERT-STRING", run_local_convert_string, 0},
9043         { "LOCAL-CONV-AUTH-INFO", run_local_conv_auth_info, 0},
9044         { "LOCAL-sprintf_append", run_local_sprintf_append, 0},
9045         { "LOCAL-hex_encode_buf", run_local_hex_encode_buf, 0},
9046         { "LOCAL-IDMAP-TDB-COMMON", run_idmap_tdb_common_test, 0},
9047         { "LOCAL-remove_duplicate_addrs2", run_local_remove_duplicate_addrs2, 0},
9048         {NULL, NULL, 0}};
9049
9050
9051
9052 /****************************************************************************
9053 run a specified test or "ALL"
9054 ****************************************************************************/
9055 static bool run_test(const char *name)
9056 {
9057         bool ret = True;
9058         bool result = True;
9059         bool found = False;
9060         int i;
9061         double t;
9062         if (strequal(name,"ALL")) {
9063                 for (i=0;torture_ops[i].name;i++) {
9064                         run_test(torture_ops[i].name);
9065                 }
9066                 found = True;
9067         }
9068
9069         for (i=0;torture_ops[i].name;i++) {
9070                 fstr_sprintf(randomfname, "\\XX%x", 
9071                          (unsigned)random());
9072
9073                 if (strequal(name, torture_ops[i].name)) {
9074                         found = True;
9075                         printf("Running %s\n", name);
9076                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
9077                                 t = create_procs(torture_ops[i].fn, &result);
9078                                 if (!result) { 
9079                                         ret = False;
9080                                         printf("TEST %s FAILED!\n", name);
9081                                 }
9082                         } else {
9083                                 struct timeval start;
9084                                 start = timeval_current();
9085                                 if (!torture_ops[i].fn(0)) {
9086                                         ret = False;
9087                                         printf("TEST %s FAILED!\n", name);
9088                                 }
9089                                 t = timeval_elapsed(&start);
9090                         }
9091                         printf("%s took %g secs\n\n", name, t);
9092                 }
9093         }
9094
9095         if (!found) {
9096                 printf("Did not find a test named %s\n", name);
9097                 ret = False;
9098         }
9099
9100         return ret;
9101 }
9102
9103
9104 static void usage(void)
9105 {
9106         int i;
9107
9108         printf("WARNING samba4 test suite is much more complete nowadays.\n");
9109         printf("Please use samba4 torture.\n\n");
9110
9111         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
9112
9113         printf("\t-d debuglevel\n");
9114         printf("\t-U user%%pass\n");
9115         printf("\t-k               use kerberos\n");
9116         printf("\t-N numprocs\n");
9117         printf("\t-n my_netbios_name\n");
9118         printf("\t-W workgroup\n");
9119         printf("\t-o num_operations\n");
9120         printf("\t-O socket_options\n");
9121         printf("\t-m maximum protocol\n");
9122         printf("\t-L use oplocks\n");
9123         printf("\t-c CLIENT.TXT   specify client load file for NBENCH\n");
9124         printf("\t-A showall\n");
9125         printf("\t-p port\n");
9126         printf("\t-s seed\n");
9127         printf("\t-b unclist_filename   specify multiple shares for multiple connections\n");
9128         printf("\t-f filename   filename to test\n");
9129         printf("\n\n");
9130
9131         printf("tests are:");
9132         for (i=0;torture_ops[i].name;i++) {
9133                 printf(" %s", torture_ops[i].name);
9134         }
9135         printf("\n");
9136
9137         printf("default test is ALL\n");
9138
9139         exit(1);
9140 }
9141
9142 /****************************************************************************
9143   main program
9144 ****************************************************************************/
9145  int main(int argc,char *argv[])
9146 {
9147         int opt, i;
9148         char *p;
9149         int gotuser = 0;
9150         int gotpass = 0;
9151         bool correct = True;
9152         TALLOC_CTX *frame = talloc_stackframe();
9153         int seed = time(NULL);
9154
9155 #ifdef HAVE_SETBUFFER
9156         setbuffer(stdout, NULL, 0);
9157 #endif
9158
9159         setup_logging("smbtorture", DEBUG_STDOUT);
9160
9161         load_case_tables();
9162
9163         if (is_default_dyn_CONFIGFILE()) {
9164                 if(getenv("SMB_CONF_PATH")) {
9165                         set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
9166                 }
9167         }
9168         lp_load_global(get_dyn_CONFIGFILE());
9169         load_interfaces();
9170
9171         if (argc < 2) {
9172                 usage();
9173         }
9174
9175         for(p = argv[1]; *p; p++)
9176           if(*p == '\\')
9177             *p = '/';
9178
9179         if (strncmp(argv[1], "//", 2)) {
9180                 usage();
9181         }
9182
9183         fstrcpy(host, &argv[1][2]);
9184         p = strchr_m(&host[2],'/');
9185         if (!p) {
9186                 usage();
9187         }
9188         *p = 0;
9189         fstrcpy(share, p+1);
9190
9191         fstrcpy(myname, get_myname(talloc_tos()));
9192         if (!*myname) {
9193                 fprintf(stderr, "Failed to get my hostname.\n");
9194                 return 1;
9195         }
9196
9197         if (*username == 0 && getenv("LOGNAME")) {
9198           fstrcpy(username,getenv("LOGNAME"));
9199         }
9200
9201         argc--;
9202         argv++;
9203
9204         fstrcpy(workgroup, lp_workgroup());
9205
9206         while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
9207                != EOF) {
9208                 switch (opt) {
9209                 case 'p':
9210                         port_to_use = atoi(optarg);
9211                         break;
9212                 case 's':
9213                         seed = atoi(optarg);
9214                         break;
9215                 case 'W':
9216                         fstrcpy(workgroup,optarg);
9217                         break;
9218                 case 'm':
9219                         max_protocol = interpret_protocol(optarg, max_protocol);
9220                         break;
9221                 case 'N':
9222                         torture_nprocs = atoi(optarg);
9223                         break;
9224                 case 'o':
9225                         torture_numops = atoi(optarg);
9226                         break;
9227                 case 'd':
9228                         lp_set_cmdline("log level", optarg);
9229                         break;
9230                 case 'O':
9231                         sockops = optarg;
9232                         break;
9233                 case 'L':
9234                         use_oplocks = True;
9235                         break;
9236                 case 'l':
9237                         local_path = optarg;
9238                         break;
9239                 case 'A':
9240                         torture_showall = True;
9241                         break;
9242                 case 'n':
9243                         fstrcpy(myname, optarg);
9244                         break;
9245                 case 'c':
9246                         client_txt = optarg;
9247                         break;
9248                 case 'e':
9249                         do_encrypt = true;
9250                         break;
9251                 case 'k':
9252 #ifdef HAVE_KRB5
9253                         use_kerberos = True;
9254 #else
9255                         d_printf("No kerberos support compiled in\n");
9256                         exit(1);
9257 #endif
9258                         break;
9259                 case 'U':
9260                         gotuser = 1;
9261                         fstrcpy(username,optarg);
9262                         p = strchr_m(username,'%');
9263                         if (p) {
9264                                 *p = 0;
9265                                 fstrcpy(password, p+1);
9266                                 gotpass = 1;
9267                         }
9268                         break;
9269                 case 'b':
9270                         fstrcpy(multishare_conn_fname, optarg);
9271                         use_multishare_conn = True;
9272                         break;
9273                 case 'B':
9274                         torture_blocksize = atoi(optarg);
9275                         break;
9276                 case 'f':
9277                         test_filename = SMB_STRDUP(optarg);
9278                         break;
9279                 default:
9280                         printf("Unknown option %c (%d)\n", (char)opt, opt);
9281                         usage();
9282                 }
9283         }
9284
9285         d_printf("using seed %d\n", seed);
9286
9287         srandom(seed);
9288
9289         if(use_kerberos && !gotuser) gotpass = True;
9290
9291         while (!gotpass) {
9292                 p = getpass("Password:");
9293                 if (p) {
9294                         fstrcpy(password, p);
9295                         gotpass = 1;
9296                 }
9297         }
9298
9299         printf("host=%s share=%s user=%s myname=%s\n", 
9300                host, share, username, myname);
9301
9302         if (argc == optind) {
9303                 correct = run_test("ALL");
9304         } else {
9305                 for (i=optind;i<argc;i++) {
9306                         if (!run_test(argv[i])) {
9307                                 correct = False;
9308                         }
9309                 }
9310         }
9311
9312         TALLOC_FREE(frame);
9313
9314         if (correct) {
9315                 return(0);
9316         } else {
9317                 return(1);
9318         }
9319 }