libcli/smb: pass smbXcli_tcon to smb2cli_flush*()
[kai/samba.git] / source3 / torture / torture.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB torture tester
4    Copyright (C) Andrew Tridgell 1997-1998
5    Copyright (C) Jeremy Allison 2009
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "system/shmem.h"
23 #include "wbc_async.h"
24 #include "torture/proto.h"
25 #include "libcli/security/security.h"
26 #include "tldap.h"
27 #include "tldap_util.h"
28 #include "../librpc/gen_ndr/svcctl.h"
29 #include "memcache.h"
30 #include "nsswitch/winbind_client.h"
31 #include "dbwrap/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         /* Ensure st_mode == 0600 */
5406         if ((sbuf.st_ex_mode & 07777) != 0600) {
5407                 printf("posix_open - bad permissions 0%o != 0600\n",
5408                                 (unsigned int)(sbuf.st_ex_mode & 07777));
5409                 goto out;
5410         }
5411
5412         /* Test ftruncate - set file size back to zero. */
5413         status = cli_ftruncate(cli1, fnum1, 0);
5414         if (!NT_STATUS_IS_OK(status)) {
5415                 printf("ftruncate failed (%s)\n", nt_errstr(status));
5416                 goto out;
5417         }
5418
5419         status = cli_close(cli1, fnum1);
5420         if (!NT_STATUS_IS_OK(status)) {
5421                 printf("close failed (%s)\n", nt_errstr(status));
5422                 goto out;
5423         }
5424
5425         /* Now open the file again for read only. */
5426         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5427         if (!NT_STATUS_IS_OK(status)) {
5428                 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
5429                 goto out;
5430         }
5431
5432         /* Now unlink while open. */
5433         status = cli_posix_unlink(cli1, fname);
5434         if (!NT_STATUS_IS_OK(status)) {
5435                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5436                 goto out;
5437         }
5438
5439         status = cli_close(cli1, fnum1);
5440         if (!NT_STATUS_IS_OK(status)) {
5441                 printf("close(2) failed (%s)\n", nt_errstr(status));
5442                 goto out;
5443         }
5444
5445         /* Ensure the file has gone. */
5446         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5447         if (NT_STATUS_IS_OK(status)) {
5448                 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
5449                 goto out;
5450         }
5451
5452         /* Create again to test open with O_TRUNC. */
5453         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
5454         if (!NT_STATUS_IS_OK(status)) {
5455                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5456                 goto out;
5457         }
5458
5459         /* Test ftruncate - set file size. */
5460         status = cli_ftruncate(cli1, fnum1, 1000);
5461         if (!NT_STATUS_IS_OK(status)) {
5462                 printf("ftruncate failed (%s)\n", nt_errstr(status));
5463                 goto out;
5464         }
5465
5466         /* Ensure st_size == 1000 */
5467         status = cli_posix_stat(cli1, fname, &sbuf);
5468         if (!NT_STATUS_IS_OK(status)) {
5469                 printf("stat failed (%s)\n", nt_errstr(status));
5470                 goto out;
5471         }
5472
5473         if (sbuf.st_ex_size != 1000) {
5474                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5475                 goto out;
5476         }
5477
5478         status = cli_close(cli1, fnum1);
5479         if (!NT_STATUS_IS_OK(status)) {
5480                 printf("close(2) failed (%s)\n", nt_errstr(status));
5481                 goto out;
5482         }
5483
5484         /* Re-open with O_TRUNC. */
5485         status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
5486         if (!NT_STATUS_IS_OK(status)) {
5487                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5488                 goto out;
5489         }
5490
5491         /* Ensure st_size == 0 */
5492         status = cli_posix_stat(cli1, fname, &sbuf);
5493         if (!NT_STATUS_IS_OK(status)) {
5494                 printf("stat failed (%s)\n", nt_errstr(status));
5495                 goto out;
5496         }
5497
5498         if (sbuf.st_ex_size != 0) {
5499                 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
5500                 goto out;
5501         }
5502
5503         status = cli_close(cli1, fnum1);
5504         if (!NT_STATUS_IS_OK(status)) {
5505                 printf("close failed (%s)\n", nt_errstr(status));
5506                 goto out;
5507         }
5508
5509         status = cli_posix_unlink(cli1, fname);
5510         if (!NT_STATUS_IS_OK(status)) {
5511                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5512                 goto out;
5513         }
5514
5515         status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
5516         if (!NT_STATUS_IS_OK(status)) {
5517                 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
5518                         dname, nt_errstr(status));
5519                 goto out;
5520         }
5521
5522         cli_close(cli1, fnum1);
5523
5524         /* What happens when we try and POSIX open a directory for write ? */
5525         status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
5526         if (NT_STATUS_IS_OK(status)) {
5527                 printf("POSIX open of directory %s succeeded, should have failed.\n", fname);
5528                 goto out;
5529         } else {
5530                 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
5531                                 NT_STATUS_FILE_IS_A_DIRECTORY)) {
5532                         goto out;
5533                 }
5534         }
5535
5536         /* Create the file. */
5537         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5538                                 0600, &fnum1);
5539         if (!NT_STATUS_IS_OK(status)) {
5540                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5541                 goto out;
5542         }
5543
5544         /* Write some data into it. */
5545         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5546                               NULL);
5547         if (!NT_STATUS_IS_OK(status)) {
5548                 printf("cli_write failed: %s\n", nt_errstr(status));
5549                 goto out;
5550         }
5551
5552         cli_close(cli1, fnum1);
5553
5554         /* Now create a hardlink. */
5555         status = cli_posix_hardlink(cli1, fname, hname);
5556         if (!NT_STATUS_IS_OK(status)) {
5557                 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
5558                 goto out;
5559         }
5560
5561         /* Now create a symlink. */
5562         status = cli_posix_symlink(cli1, fname, sname);
5563         if (!NT_STATUS_IS_OK(status)) {
5564                 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
5565                 goto out;
5566         }
5567
5568         /* Open the hardlink for read. */
5569         status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
5570         if (!NT_STATUS_IS_OK(status)) {
5571                 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
5572                 goto out;
5573         }
5574
5575         status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
5576         if (!NT_STATUS_IS_OK(status)) {
5577                 printf("POSIX read of %s failed (%s)\n", hname,
5578                        nt_errstr(status));
5579                 goto out;
5580         } else if (nread != 10) {
5581                 printf("POSIX read of %s failed. Received %ld, expected %d\n",
5582                        hname, (unsigned long)nread, 10);
5583                 goto out;
5584         }
5585
5586         if (memcmp(buf, "TEST DATA\n", 10)) {
5587                 printf("invalid data read from hardlink\n");
5588                 goto out;
5589         }
5590
5591         /* Do a POSIX lock/unlock. */
5592         status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
5593         if (!NT_STATUS_IS_OK(status)) {
5594                 printf("POSIX lock failed %s\n", nt_errstr(status));
5595                 goto out;
5596         }
5597
5598         /* Punch a hole in the locked area. */
5599         status = cli_posix_unlock(cli1, fnum1, 10, 80);
5600         if (!NT_STATUS_IS_OK(status)) {
5601                 printf("POSIX unlock failed %s\n", nt_errstr(status));
5602                 goto out;
5603         }
5604
5605         cli_close(cli1, fnum1);
5606
5607         /* Open the symlink for read - this should fail. A POSIX
5608            client should not be doing opens on a symlink. */
5609         status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
5610         if (NT_STATUS_IS_OK(status)) {
5611                 printf("POSIX open of %s succeeded (should have failed)\n", sname);
5612                 goto out;
5613         } else {
5614                 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
5615                                 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
5616                         printf("POSIX open of %s should have failed "
5617                                 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
5618                                 "failed with %s instead.\n",
5619                                 sname, nt_errstr(status));
5620                         goto out;
5621                 }
5622         }
5623
5624         status = cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf));
5625         if (!NT_STATUS_IS_OK(status)) {
5626                 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
5627                 goto out;
5628         }
5629
5630         if (strcmp(namebuf, fname) != 0) {
5631                 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
5632                         sname, fname, namebuf);
5633                 goto out;
5634         }
5635
5636         status = cli_posix_rmdir(cli1, dname);
5637         if (!NT_STATUS_IS_OK(status)) {
5638                 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
5639                 goto out;
5640         }
5641
5642         /* Check directory opens with a specific permission. */
5643         status = cli_posix_mkdir(cli1, dname, 0700);
5644         if (!NT_STATUS_IS_OK(status)) {
5645                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
5646                 goto out;
5647         }
5648
5649         /* Ensure st_mode == 0700 */
5650         status = cli_posix_stat(cli1, dname, &sbuf);
5651         if (!NT_STATUS_IS_OK(status)) {
5652                 printf("stat failed (%s)\n", nt_errstr(status));
5653                 goto out;
5654         }
5655
5656         if ((sbuf.st_ex_mode & 07777) != 0700) {
5657                 printf("posix_mkdir - bad permissions 0%o != 0700\n",
5658                                 (unsigned int)(sbuf.st_ex_mode & 07777));
5659                 goto out;
5660         }
5661
5662         printf("Simple POSIX open test passed\n");
5663         correct = true;
5664
5665   out:
5666
5667         if (fnum1 != (uint16_t)-1) {
5668                 cli_close(cli1, fnum1);
5669                 fnum1 = (uint16_t)-1;
5670         }
5671
5672         cli_setatr(cli1, sname, 0, 0);
5673         cli_posix_unlink(cli1, sname);
5674         cli_setatr(cli1, hname, 0, 0);
5675         cli_posix_unlink(cli1, hname);
5676         cli_setatr(cli1, fname, 0, 0);
5677         cli_posix_unlink(cli1, fname);
5678         cli_setatr(cli1, dname, 0, 0);
5679         cli_posix_rmdir(cli1, dname);
5680
5681         if (!torture_close_connection(cli1)) {
5682                 correct = false;
5683         }
5684
5685         return correct;
5686 }
5687
5688
5689 static uint32 open_attrs_table[] = {
5690                 FILE_ATTRIBUTE_NORMAL,
5691                 FILE_ATTRIBUTE_ARCHIVE,
5692                 FILE_ATTRIBUTE_READONLY,
5693                 FILE_ATTRIBUTE_HIDDEN,
5694                 FILE_ATTRIBUTE_SYSTEM,
5695
5696                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
5697                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
5698                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
5699                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5700                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5701                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5702
5703                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5704                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5705                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5706                 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
5707 };
5708
5709 struct trunc_open_results {
5710         unsigned int num;
5711         uint32 init_attr;
5712         uint32 trunc_attr;
5713         uint32 result_attr;
5714 };
5715
5716 static struct trunc_open_results attr_results[] = {
5717         { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5718         { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5719         { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5720         { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5721         { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5722         { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5723         { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5724         { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5725         { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5726         { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5727         { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5728         { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
5729         { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5730         { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5731         { 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 },
5732         { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5733         { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5734         { 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 },
5735         { 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 },
5736         { 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 },
5737         { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5738         { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5739         { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5740         { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5741         { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5742         { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
5743 };
5744
5745 static bool run_openattrtest(int dummy)
5746 {
5747         static struct cli_state *cli1;
5748         const char *fname = "\\openattr.file";
5749         uint16_t fnum1;
5750         bool correct = True;
5751         uint16 attr;
5752         unsigned int i, j, k, l;
5753         NTSTATUS status;
5754
5755         printf("starting open attr test\n");
5756
5757         if (!torture_open_connection(&cli1, 0)) {
5758                 return False;
5759         }
5760
5761         smbXcli_conn_set_sockopt(cli1->conn, sockops);
5762
5763         for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32); i++) {
5764                 cli_setatr(cli1, fname, 0, 0);
5765                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5766
5767                 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
5768                                        open_attrs_table[i], FILE_SHARE_NONE,
5769                                        FILE_OVERWRITE_IF, 0, 0, &fnum1);
5770                 if (!NT_STATUS_IS_OK(status)) {
5771                         printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5772                         return False;
5773                 }
5774
5775                 status = cli_close(cli1, fnum1);
5776                 if (!NT_STATUS_IS_OK(status)) {
5777                         printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5778                         return False;
5779                 }
5780
5781                 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32); j++) {
5782                         status = cli_ntcreate(cli1, fname, 0,
5783                                               FILE_READ_DATA|FILE_WRITE_DATA,
5784                                               open_attrs_table[j],
5785                                               FILE_SHARE_NONE, FILE_OVERWRITE,
5786                                               0, 0, &fnum1);
5787                         if (!NT_STATUS_IS_OK(status)) {
5788                                 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5789                                         if (attr_results[l].num == k) {
5790                                                 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
5791                                                                 k, open_attrs_table[i],
5792                                                                 open_attrs_table[j],
5793                                                                 fname, NT_STATUS_V(status), nt_errstr(status));
5794                                                 correct = False;
5795                                         }
5796                                 }
5797
5798                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5799                                         printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
5800                                                         k, open_attrs_table[i], open_attrs_table[j],
5801                                                         nt_errstr(status));
5802                                         correct = False;
5803                                 }
5804 #if 0
5805                                 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
5806 #endif
5807                                 k++;
5808                                 continue;
5809                         }
5810
5811                         status = cli_close(cli1, fnum1);
5812                         if (!NT_STATUS_IS_OK(status)) {
5813                                 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
5814                                 return False;
5815                         }
5816
5817                         status = cli_getatr(cli1, fname, &attr, NULL, NULL);
5818                         if (!NT_STATUS_IS_OK(status)) {
5819                                 printf("getatr(2) failed (%s)\n", nt_errstr(status));
5820                                 return False;
5821                         }
5822
5823 #if 0
5824                         printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
5825                                         k,  open_attrs_table[i],  open_attrs_table[j], attr );
5826 #endif
5827
5828                         for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5829                                 if (attr_results[l].num == k) {
5830                                         if (attr != attr_results[l].result_attr ||
5831                                                         open_attrs_table[i] != attr_results[l].init_attr ||
5832                                                         open_attrs_table[j] != attr_results[l].trunc_attr) {
5833                                                 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
5834                                                 open_attrs_table[i],
5835                                                 open_attrs_table[j],
5836                                                 (unsigned int)attr,
5837                                                 attr_results[l].result_attr);
5838                                                 correct = False;
5839                                         }
5840                                         break;
5841                                 }
5842                         }
5843                         k++;
5844                 }
5845         }
5846
5847         cli_setatr(cli1, fname, 0, 0);
5848         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5849
5850         printf("open attr test %s.\n", correct ? "passed" : "failed");
5851
5852         if (!torture_close_connection(cli1)) {
5853                 correct = False;
5854         }
5855         return correct;
5856 }
5857
5858 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
5859                     const char *name, void *state)
5860 {
5861         int *matched = (int *)state;
5862         if (matched != NULL) {
5863                 *matched += 1;
5864         }
5865         return NT_STATUS_OK;
5866 }
5867
5868 /*
5869   test directory listing speed
5870  */
5871 static bool run_dirtest(int dummy)
5872 {
5873         int i;
5874         static struct cli_state *cli;
5875         uint16_t fnum;
5876         struct timeval core_start;
5877         bool correct = True;
5878         int matched;
5879
5880         printf("starting directory test\n");
5881
5882         if (!torture_open_connection(&cli, 0)) {
5883                 return False;
5884         }
5885
5886         smbXcli_conn_set_sockopt(cli->conn, sockops);
5887
5888         srandom(0);
5889         for (i=0;i<torture_numops;i++) {
5890                 fstring fname;
5891                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5892                 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
5893                         fprintf(stderr,"Failed to open %s\n", fname);
5894                         return False;
5895                 }
5896                 cli_close(cli, fnum);
5897         }
5898
5899         core_start = timeval_current();
5900
5901         matched = 0;
5902         cli_list(cli, "a*.*", 0, list_fn, &matched);
5903         printf("Matched %d\n", matched);
5904
5905         matched = 0;
5906         cli_list(cli, "b*.*", 0, list_fn, &matched);
5907         printf("Matched %d\n", matched);
5908
5909         matched = 0;
5910         cli_list(cli, "xyzabc", 0, list_fn, &matched);
5911         printf("Matched %d\n", matched);
5912
5913         printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
5914
5915         srandom(0);
5916         for (i=0;i<torture_numops;i++) {
5917                 fstring fname;
5918                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5919                 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5920         }
5921
5922         if (!torture_close_connection(cli)) {
5923                 correct = False;
5924         }
5925
5926         printf("finished dirtest\n");
5927
5928         return correct;
5929 }
5930
5931 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
5932                    void *state)
5933 {
5934         struct cli_state *pcli = (struct cli_state *)state;
5935         fstring fname;
5936         slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
5937
5938         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
5939                 return NT_STATUS_OK;
5940
5941         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
5942                 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
5943                         printf("del_fn: failed to rmdir %s\n,", fname );
5944         } else {
5945                 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
5946                         printf("del_fn: failed to unlink %s\n,", fname );
5947         }
5948         return NT_STATUS_OK;
5949 }
5950
5951
5952 /*
5953   sees what IOCTLs are supported
5954  */
5955 bool torture_ioctl_test(int dummy)
5956 {
5957         static struct cli_state *cli;
5958         uint16_t device, function;
5959         uint16_t fnum;
5960         const char *fname = "\\ioctl.dat";
5961         DATA_BLOB blob;
5962         NTSTATUS status;
5963
5964         if (!torture_open_connection(&cli, 0)) {
5965                 return False;
5966         }
5967
5968         printf("starting ioctl test\n");
5969
5970         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5971
5972         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5973         if (!NT_STATUS_IS_OK(status)) {
5974                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5975                 return False;
5976         }
5977
5978         status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
5979         printf("ioctl device info: %s\n", nt_errstr(status));
5980
5981         status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
5982         printf("ioctl job info: %s\n", nt_errstr(status));
5983
5984         for (device=0;device<0x100;device++) {
5985                 printf("ioctl test with device = 0x%x\n", device);
5986                 for (function=0;function<0x100;function++) {
5987                         uint32 code = (device<<16) | function;
5988
5989                         status = cli_raw_ioctl(cli, fnum, code, &blob);
5990
5991                         if (NT_STATUS_IS_OK(status)) {
5992                                 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
5993                                        (int)blob.length);
5994                                 data_blob_free(&blob);
5995                         }
5996                 }
5997         }
5998
5999         if (!torture_close_connection(cli)) {
6000                 return False;
6001         }
6002
6003         return True;
6004 }
6005
6006
6007 /*
6008   tries varients of chkpath
6009  */
6010 bool torture_chkpath_test(int dummy)
6011 {
6012         static struct cli_state *cli;
6013         uint16_t fnum;
6014         bool ret;
6015         NTSTATUS status;
6016
6017         if (!torture_open_connection(&cli, 0)) {
6018                 return False;
6019         }
6020
6021         printf("starting chkpath test\n");
6022
6023         /* cleanup from an old run */
6024         cli_rmdir(cli, "\\chkpath.dir\\dir2");
6025         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6026         cli_rmdir(cli, "\\chkpath.dir");
6027
6028         status = cli_mkdir(cli, "\\chkpath.dir");
6029         if (!NT_STATUS_IS_OK(status)) {
6030                 printf("mkdir1 failed : %s\n", nt_errstr(status));
6031                 return False;
6032         }
6033
6034         status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
6035         if (!NT_STATUS_IS_OK(status)) {
6036                 printf("mkdir2 failed : %s\n", nt_errstr(status));
6037                 return False;
6038         }
6039
6040         status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
6041                           DENY_NONE, &fnum);
6042         if (!NT_STATUS_IS_OK(status)) {
6043                 printf("open1 failed (%s)\n", nt_errstr(status));
6044                 return False;
6045         }
6046         cli_close(cli, fnum);
6047
6048         status = cli_chkpath(cli, "\\chkpath.dir");
6049         if (!NT_STATUS_IS_OK(status)) {
6050                 printf("chkpath1 failed: %s\n", nt_errstr(status));
6051                 ret = False;
6052         }
6053
6054         status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
6055         if (!NT_STATUS_IS_OK(status)) {
6056                 printf("chkpath2 failed: %s\n", nt_errstr(status));
6057                 ret = False;
6058         }
6059
6060         status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
6061         if (!NT_STATUS_IS_OK(status)) {
6062                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
6063                                   NT_STATUS_NOT_A_DIRECTORY);
6064         } else {
6065                 printf("* chkpath on a file should fail\n");
6066                 ret = False;
6067         }
6068
6069         status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
6070         if (!NT_STATUS_IS_OK(status)) {
6071                 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
6072                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
6073         } else {
6074                 printf("* chkpath on a non existent file should fail\n");
6075                 ret = False;
6076         }
6077
6078         status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
6079         if (!NT_STATUS_IS_OK(status)) {
6080                 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
6081                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
6082         } else {
6083                 printf("* chkpath on a non existent component should fail\n");
6084                 ret = False;
6085         }
6086
6087         cli_rmdir(cli, "\\chkpath.dir\\dir2");
6088         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6089         cli_rmdir(cli, "\\chkpath.dir");
6090
6091         if (!torture_close_connection(cli)) {
6092                 return False;
6093         }
6094
6095         return ret;
6096 }
6097
6098 static bool run_eatest(int dummy)
6099 {
6100         static struct cli_state *cli;
6101         const char *fname = "\\eatest.txt";
6102         bool correct = True;
6103         uint16_t fnum;
6104         int i;
6105         size_t num_eas;
6106         struct ea_struct *ea_list = NULL;
6107         TALLOC_CTX *mem_ctx = talloc_init("eatest");
6108         NTSTATUS status;
6109
6110         printf("starting eatest\n");
6111
6112         if (!torture_open_connection(&cli, 0)) {
6113                 talloc_destroy(mem_ctx);
6114                 return False;
6115         }
6116
6117         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6118
6119         status = cli_ntcreate(cli, fname, 0,
6120                               FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6121                               FILE_SHARE_NONE, FILE_OVERWRITE_IF,
6122                               0x4044, 0, &fnum);
6123         if (!NT_STATUS_IS_OK(status)) {
6124                 printf("open failed - %s\n", nt_errstr(status));
6125                 talloc_destroy(mem_ctx);
6126                 return False;
6127         }
6128
6129         for (i = 0; i < 10; i++) {
6130                 fstring ea_name, ea_val;
6131
6132                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
6133                 memset(ea_val, (char)i+1, i+1);
6134                 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
6135                 if (!NT_STATUS_IS_OK(status)) {
6136                         printf("ea_set of name %s failed - %s\n", ea_name,
6137                                nt_errstr(status));
6138                         talloc_destroy(mem_ctx);
6139                         return False;
6140                 }
6141         }
6142
6143         cli_close(cli, fnum);
6144         for (i = 0; i < 10; i++) {
6145                 fstring ea_name, ea_val;
6146
6147                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
6148                 memset(ea_val, (char)i+1, i+1);
6149                 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
6150                 if (!NT_STATUS_IS_OK(status)) {
6151                         printf("ea_set of name %s failed - %s\n", ea_name,
6152                                nt_errstr(status));
6153                         talloc_destroy(mem_ctx);
6154                         return False;
6155                 }
6156         }
6157
6158         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6159         if (!NT_STATUS_IS_OK(status)) {
6160                 printf("ea_get list failed - %s\n", nt_errstr(status));
6161                 correct = False;
6162         }
6163
6164         printf("num_eas = %d\n", (int)num_eas);
6165
6166         if (num_eas != 20) {
6167                 printf("Should be 20 EA's stored... failing.\n");
6168                 correct = False;
6169         }
6170
6171         for (i = 0; i < num_eas; i++) {
6172                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6173                 dump_data(0, ea_list[i].value.data,
6174                           ea_list[i].value.length);
6175         }
6176
6177         /* Setting EA's to zero length deletes them. Test this */
6178         printf("Now deleting all EA's - case indepenent....\n");
6179
6180 #if 1
6181         cli_set_ea_path(cli, fname, "", "", 0);
6182 #else
6183         for (i = 0; i < 20; i++) {
6184                 fstring ea_name;
6185                 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
6186                 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
6187                 if (!NT_STATUS_IS_OK(status)) {
6188                         printf("ea_set of name %s failed - %s\n", ea_name,
6189                                nt_errstr(status));
6190                         talloc_destroy(mem_ctx);
6191                         return False;
6192                 }
6193         }
6194 #endif
6195
6196         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6197         if (!NT_STATUS_IS_OK(status)) {
6198                 printf("ea_get list failed - %s\n", nt_errstr(status));
6199                 correct = False;
6200         }
6201
6202         printf("num_eas = %d\n", (int)num_eas);
6203         for (i = 0; i < num_eas; i++) {
6204                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6205                 dump_data(0, ea_list[i].value.data,
6206                           ea_list[i].value.length);
6207         }
6208
6209         if (num_eas != 0) {
6210                 printf("deleting EA's failed.\n");
6211                 correct = False;
6212         }
6213
6214         /* Try and delete a non existent EA. */
6215         status = cli_set_ea_path(cli, fname, "foo", "", 0);
6216         if (!NT_STATUS_IS_OK(status)) {
6217                 printf("deleting non-existent EA 'foo' should succeed. %s\n",
6218                        nt_errstr(status));
6219                 correct = False;
6220         }
6221
6222         talloc_destroy(mem_ctx);
6223         if (!torture_close_connection(cli)) {
6224                 correct = False;
6225         }
6226
6227         return correct;
6228 }
6229
6230 static bool run_dirtest1(int dummy)
6231 {
6232         int i;
6233         static struct cli_state *cli;
6234         uint16_t fnum;
6235         int num_seen;
6236         bool correct = True;
6237
6238         printf("starting directory test\n");
6239
6240         if (!torture_open_connection(&cli, 0)) {
6241                 return False;
6242         }
6243
6244         smbXcli_conn_set_sockopt(cli->conn, sockops);
6245
6246         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6247         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6248         cli_rmdir(cli, "\\LISTDIR");
6249         cli_mkdir(cli, "\\LISTDIR");
6250
6251         /* Create 1000 files and 1000 directories. */
6252         for (i=0;i<1000;i++) {
6253                 fstring fname;
6254                 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
6255                 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6256                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum))) {
6257                         fprintf(stderr,"Failed to open %s\n", fname);
6258                         return False;
6259                 }
6260                 cli_close(cli, fnum);
6261         }
6262         for (i=0;i<1000;i++) {
6263                 fstring fname;
6264                 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
6265                 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
6266                         fprintf(stderr,"Failed to open %s\n", fname);
6267                         return False;
6268                 }
6269         }
6270
6271         /* Now ensure that doing an old list sees both files and directories. */
6272         num_seen = 0;
6273         cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6274         printf("num_seen = %d\n", num_seen );
6275         /* We should see 100 files + 1000 directories + . and .. */
6276         if (num_seen != 2002)
6277                 correct = False;
6278
6279         /* Ensure if we have the "must have" bits we only see the
6280          * relevent entries.
6281          */
6282         num_seen = 0;
6283         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6284         printf("num_seen = %d\n", num_seen );
6285         if (num_seen != 1002)
6286                 correct = False;
6287
6288         num_seen = 0;
6289         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6290         printf("num_seen = %d\n", num_seen );
6291         if (num_seen != 1000)
6292                 correct = False;
6293
6294         /* Delete everything. */
6295         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6296         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6297         cli_rmdir(cli, "\\LISTDIR");
6298
6299 #if 0
6300         printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
6301         printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
6302         printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
6303 #endif
6304
6305         if (!torture_close_connection(cli)) {
6306                 correct = False;
6307         }
6308
6309         printf("finished dirtest1\n");
6310
6311         return correct;
6312 }
6313
6314 static bool run_error_map_extract(int dummy) {
6315
6316         static struct cli_state *c_dos;
6317         static struct cli_state *c_nt;
6318         NTSTATUS status;
6319
6320         uint32 error;
6321
6322         uint32 errnum;
6323         uint8 errclass;
6324
6325         NTSTATUS nt_status;
6326
6327         fstring user;
6328
6329         /* NT-Error connection */
6330
6331         disable_spnego = true;
6332         if (!(c_nt = open_nbt_connection())) {
6333                 disable_spnego = false;
6334                 return False;
6335         }
6336         disable_spnego = false;
6337
6338         status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
6339                                  PROTOCOL_NT1);
6340
6341         if (!NT_STATUS_IS_OK(status)) {
6342                 printf("%s rejected the NT-error negprot (%s)\n", host,
6343                        nt_errstr(status));
6344                 cli_shutdown(c_nt);
6345                 return False;
6346         }
6347
6348         status = cli_session_setup(c_nt, "", "", 0, "", 0, workgroup);
6349         if (!NT_STATUS_IS_OK(status)) {
6350                 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
6351                 return False;
6352         }
6353
6354         /* DOS-Error connection */
6355
6356         disable_spnego = true;
6357         force_dos_errors = true;
6358         if (!(c_dos = open_nbt_connection())) {
6359                 disable_spnego = false;
6360                 force_dos_errors = false;
6361                 return False;
6362         }
6363         disable_spnego = false;
6364         force_dos_errors = false;
6365
6366         status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
6367                                  PROTOCOL_NT1);
6368         if (!NT_STATUS_IS_OK(status)) {
6369                 printf("%s rejected the DOS-error negprot (%s)\n", host,
6370                        nt_errstr(status));
6371                 cli_shutdown(c_dos);
6372                 return False;
6373         }
6374
6375         status = cli_session_setup(c_dos, "", "", 0, "", 0, workgroup);
6376         if (!NT_STATUS_IS_OK(status)) {
6377                 printf("%s rejected the DOS-error initial session setup (%s)\n",
6378                         host, nt_errstr(status));
6379                 return False;
6380         }
6381
6382         c_nt->map_dos_errors = false;
6383         c_dos->map_dos_errors = false;
6384
6385         for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
6386                 fstr_sprintf(user, "%X", error);
6387
6388                 status = cli_session_setup(c_nt, user,
6389                                            password, strlen(password),
6390                                            password, strlen(password),
6391                                            workgroup);
6392                 if (NT_STATUS_IS_OK(status)) {
6393                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
6394                 }
6395
6396                 /* Case #1: 32-bit NT errors */
6397                 if (!NT_STATUS_IS_DOS(status)) {
6398                         nt_status = status;
6399                 } else {
6400                         printf("/** Dos error on NT connection! (%s) */\n", 
6401                                nt_errstr(status));
6402                         nt_status = NT_STATUS(0xc0000000);
6403                 }
6404
6405                 status = cli_session_setup(c_dos, user,
6406                                            password, strlen(password),
6407                                            password, strlen(password),
6408                                            workgroup);
6409                 if (NT_STATUS_IS_OK(status)) {
6410                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
6411                 }
6412
6413                 /* Case #1: 32-bit NT errors */
6414                 if (NT_STATUS_IS_DOS(status)) {
6415                         printf("/** NT error on DOS connection! (%s) */\n", 
6416                                nt_errstr(status));
6417                         errnum = errclass = 0;
6418                 } else {
6419                         errclass = NT_STATUS_DOS_CLASS(status);
6420                         errnum = NT_STATUS_DOS_CODE(status);
6421                 }
6422
6423                 if (NT_STATUS_V(nt_status) != error) { 
6424                         printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n", 
6425                                get_nt_error_c_code(talloc_tos(), NT_STATUS(error)), 
6426                                get_nt_error_c_code(talloc_tos(), nt_status));
6427                 }
6428
6429                 printf("\t{%s,\t%s,\t%s},\n", 
6430                        smb_dos_err_class(errclass), 
6431                        smb_dos_err_name(errclass, errnum), 
6432                        get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
6433         }
6434         return True;
6435 }
6436
6437 static bool run_sesssetup_bench(int dummy)
6438 {
6439         static struct cli_state *c;
6440         const char *fname = "\\file.dat";
6441         uint16_t fnum;
6442         NTSTATUS status;
6443         int i;
6444
6445         if (!torture_open_connection(&c, 0)) {
6446                 return false;
6447         }
6448
6449         status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6450                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6451                               FILE_DELETE_ON_CLOSE, 0, &fnum);
6452         if (!NT_STATUS_IS_OK(status)) {
6453                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
6454                 return false;
6455         }
6456
6457         for (i=0; i<torture_numops; i++) {
6458                 status = cli_session_setup(
6459                         c, username,
6460                         password, strlen(password),
6461                         password, strlen(password),
6462                         workgroup);
6463                 if (!NT_STATUS_IS_OK(status)) {
6464                         d_printf("(%s) cli_session_setup failed: %s\n",
6465                                  __location__, nt_errstr(status));
6466                         return false;
6467                 }
6468
6469                 d_printf("\r%d   ", (int)cli_state_get_uid(c));
6470
6471                 status = cli_ulogoff(c);
6472                 if (!NT_STATUS_IS_OK(status)) {
6473                         d_printf("(%s) cli_ulogoff failed: %s\n",
6474                                  __location__, nt_errstr(status));
6475                         return false;
6476                 }
6477         }
6478
6479         return true;
6480 }
6481
6482 static bool subst_test(const char *str, const char *user, const char *domain,
6483                        uid_t uid, gid_t gid, const char *expected)
6484 {
6485         char *subst;
6486         bool result = true;
6487
6488         subst = talloc_sub_specified(talloc_tos(), str, user, domain, uid, gid);
6489
6490         if (strcmp(subst, expected) != 0) {
6491                 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
6492                        "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
6493                        expected);
6494                 result = false;
6495         }
6496
6497         TALLOC_FREE(subst);
6498         return result;
6499 }
6500
6501 static void chain1_open_completion(struct tevent_req *req)
6502 {
6503         uint16_t fnum;
6504         NTSTATUS status;
6505         status = cli_openx_recv(req, &fnum);
6506         TALLOC_FREE(req);
6507
6508         d_printf("cli_openx_recv returned %s: %d\n",
6509                  nt_errstr(status),
6510                  NT_STATUS_IS_OK(status) ? fnum : -1);
6511 }
6512
6513 static void chain1_write_completion(struct tevent_req *req)
6514 {
6515         size_t written;
6516         NTSTATUS status;
6517         status = cli_write_andx_recv(req, &written);
6518         TALLOC_FREE(req);
6519
6520         d_printf("cli_write_andx_recv returned %s: %d\n",
6521                  nt_errstr(status),
6522                  NT_STATUS_IS_OK(status) ? (int)written : -1);
6523 }
6524
6525 static void chain1_close_completion(struct tevent_req *req)
6526 {
6527         NTSTATUS status;
6528         bool *done = (bool *)tevent_req_callback_data_void(req);
6529
6530         status = cli_close_recv(req);
6531         *done = true;
6532
6533         TALLOC_FREE(req);
6534
6535         d_printf("cli_close returned %s\n", nt_errstr(status));
6536 }
6537
6538 static bool run_chain1(int dummy)
6539 {
6540         struct cli_state *cli1;
6541         struct event_context *evt = event_context_init(NULL);
6542         struct tevent_req *reqs[3], *smbreqs[3];
6543         bool done = false;
6544         const char *str = "foobar";
6545         NTSTATUS status;
6546
6547         printf("starting chain1 test\n");
6548         if (!torture_open_connection(&cli1, 0)) {
6549                 return False;
6550         }
6551
6552         smbXcli_conn_set_sockopt(cli1->conn, sockops);
6553
6554         reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, "\\test",
6555                                   O_CREAT|O_RDWR, 0, &smbreqs[0]);
6556         if (reqs[0] == NULL) return false;
6557         tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
6558
6559
6560         reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
6561                                         (const uint8_t *)str, 0, strlen(str)+1,
6562                                         smbreqs, 1, &smbreqs[1]);
6563         if (reqs[1] == NULL) return false;
6564         tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
6565
6566         reqs[2] = cli_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
6567         if (reqs[2] == NULL) return false;
6568         tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
6569
6570         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
6571         if (!NT_STATUS_IS_OK(status)) {
6572                 return false;
6573         }
6574
6575         while (!done) {
6576                 tevent_loop_once(evt);
6577         }
6578
6579         torture_close_connection(cli1);
6580         return True;
6581 }
6582
6583 static void chain2_sesssetup_completion(struct tevent_req *req)
6584 {
6585         NTSTATUS status;
6586         status = cli_session_setup_guest_recv(req);
6587         d_printf("sesssetup returned %s\n", nt_errstr(status));
6588 }
6589
6590 static void chain2_tcon_completion(struct tevent_req *req)
6591 {
6592         bool *done = (bool *)tevent_req_callback_data_void(req);
6593         NTSTATUS status;
6594         status = cli_tcon_andx_recv(req);
6595         d_printf("tcon_and_x returned %s\n", nt_errstr(status));
6596         *done = true;
6597 }
6598
6599 static bool run_chain2(int dummy)
6600 {
6601         struct cli_state *cli1;
6602         struct event_context *evt = event_context_init(NULL);
6603         struct tevent_req *reqs[2], *smbreqs[2];
6604         bool done = false;
6605         NTSTATUS status;
6606
6607         printf("starting chain2 test\n");
6608         status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
6609                                       port_to_use, SMB_SIGNING_DEFAULT, 0);
6610         if (!NT_STATUS_IS_OK(status)) {
6611                 return False;
6612         }
6613
6614         smbXcli_conn_set_sockopt(cli1->conn, sockops);
6615
6616         reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
6617                                                  &smbreqs[0]);
6618         if (reqs[0] == NULL) return false;
6619         tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
6620
6621         reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
6622                                        "?????", NULL, 0, &smbreqs[1]);
6623         if (reqs[1] == NULL) return false;
6624         tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
6625
6626         status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
6627         if (!NT_STATUS_IS_OK(status)) {
6628                 return false;
6629         }
6630
6631         while (!done) {
6632                 tevent_loop_once(evt);
6633         }
6634
6635         torture_close_connection(cli1);
6636         return True;
6637 }
6638
6639
6640 struct torture_createdel_state {
6641         struct tevent_context *ev;
6642         struct cli_state *cli;
6643 };
6644
6645 static void torture_createdel_created(struct tevent_req *subreq);
6646 static void torture_createdel_closed(struct tevent_req *subreq);
6647
6648 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
6649                                                  struct tevent_context *ev,
6650                                                  struct cli_state *cli,
6651                                                  const char *name)
6652 {
6653         struct tevent_req *req, *subreq;
6654         struct torture_createdel_state *state;
6655
6656         req = tevent_req_create(mem_ctx, &state,
6657                                 struct torture_createdel_state);
6658         if (req == NULL) {
6659                 return NULL;
6660         }
6661         state->ev = ev;
6662         state->cli = cli;
6663
6664         subreq = cli_ntcreate_send(
6665                 state, ev, cli, name, 0,
6666                 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
6667                 FILE_ATTRIBUTE_NORMAL,
6668                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6669                 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
6670
6671         if (tevent_req_nomem(subreq, req)) {
6672                 return tevent_req_post(req, ev);
6673         }
6674         tevent_req_set_callback(subreq, torture_createdel_created, req);
6675         return req;
6676 }
6677
6678 static void torture_createdel_created(struct tevent_req *subreq)
6679 {
6680         struct tevent_req *req = tevent_req_callback_data(
6681                 subreq, struct tevent_req);
6682         struct torture_createdel_state *state = tevent_req_data(
6683                 req, struct torture_createdel_state);
6684         NTSTATUS status;
6685         uint16_t fnum;
6686
6687         status = cli_ntcreate_recv(subreq, &fnum);
6688         TALLOC_FREE(subreq);
6689         if (!NT_STATUS_IS_OK(status)) {
6690                 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
6691                            nt_errstr(status)));
6692                 tevent_req_nterror(req, status);
6693                 return;
6694         }
6695
6696         subreq = cli_close_send(state, state->ev, state->cli, fnum);
6697         if (tevent_req_nomem(subreq, req)) {
6698                 return;
6699         }
6700         tevent_req_set_callback(subreq, torture_createdel_closed, req);
6701 }
6702
6703 static void torture_createdel_closed(struct tevent_req *subreq)
6704 {
6705         struct tevent_req *req = tevent_req_callback_data(
6706                 subreq, struct tevent_req);
6707         NTSTATUS status;
6708
6709         status = cli_close_recv(subreq);
6710         if (!NT_STATUS_IS_OK(status)) {
6711                 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
6712                 tevent_req_nterror(req, status);
6713                 return;
6714         }
6715         tevent_req_done(req);
6716 }
6717
6718 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
6719 {
6720         return tevent_req_simple_recv_ntstatus(req);
6721 }
6722
6723 struct torture_createdels_state {
6724         struct tevent_context *ev;
6725         struct cli_state *cli;
6726         const char *base_name;
6727         int sent;
6728         int received;
6729         int num_files;
6730         struct tevent_req **reqs;
6731 };
6732
6733 static void torture_createdels_done(struct tevent_req *subreq);
6734
6735 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
6736                                                   struct tevent_context *ev,
6737                                                   struct cli_state *cli,
6738                                                   const char *base_name,
6739                                                   int num_parallel,
6740                                                   int num_files)
6741 {
6742         struct tevent_req *req;
6743         struct torture_createdels_state *state;
6744         int i;
6745
6746         req = tevent_req_create(mem_ctx, &state,
6747                                 struct torture_createdels_state);
6748         if (req == NULL) {
6749                 return NULL;
6750         }
6751         state->ev = ev;
6752         state->cli = cli;
6753         state->base_name = talloc_strdup(state, base_name);
6754         if (tevent_req_nomem(state->base_name, req)) {
6755                 return tevent_req_post(req, ev);
6756         }
6757         state->num_files = MAX(num_parallel, num_files);
6758         state->sent = 0;
6759         state->received = 0;
6760
6761         state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
6762         if (tevent_req_nomem(state->reqs, req)) {
6763                 return tevent_req_post(req, ev);
6764         }
6765
6766         for (i=0; i<num_parallel; i++) {
6767                 char *name;
6768
6769                 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6770                                        state->sent);
6771                 if (tevent_req_nomem(name, req)) {
6772                         return tevent_req_post(req, ev);
6773                 }
6774                 state->reqs[i] = torture_createdel_send(
6775                         state->reqs, state->ev, state->cli, name);
6776                 if (tevent_req_nomem(state->reqs[i], req)) {
6777                         return tevent_req_post(req, ev);
6778                 }
6779                 name = talloc_move(state->reqs[i], &name);
6780                 tevent_req_set_callback(state->reqs[i],
6781                                         torture_createdels_done, req);
6782                 state->sent += 1;
6783         }
6784         return req;
6785 }
6786
6787 static void torture_createdels_done(struct tevent_req *subreq)
6788 {
6789         struct tevent_req *req = tevent_req_callback_data(
6790                 subreq, struct tevent_req);
6791         struct torture_createdels_state *state = tevent_req_data(
6792                 req, struct torture_createdels_state);
6793         size_t num_parallel = talloc_array_length(state->reqs);
6794         NTSTATUS status;
6795         char *name;
6796         int i;
6797
6798         status = torture_createdel_recv(subreq);
6799         if (!NT_STATUS_IS_OK(status)){
6800                 DEBUG(10, ("torture_createdel_recv returned %s\n",
6801                            nt_errstr(status)));
6802                 TALLOC_FREE(subreq);
6803                 tevent_req_nterror(req, status);
6804                 return;
6805         }
6806
6807         for (i=0; i<num_parallel; i++) {
6808                 if (subreq == state->reqs[i]) {
6809                         break;
6810                 }
6811         }
6812         if (i == num_parallel) {
6813                 DEBUG(10, ("received something we did not send\n"));
6814                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
6815                 return;
6816         }
6817         TALLOC_FREE(state->reqs[i]);
6818
6819         if (state->sent >= state->num_files) {
6820                 tevent_req_done(req);
6821                 return;
6822         }
6823
6824         name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6825                                state->sent);
6826         if (tevent_req_nomem(name, req)) {
6827                 return;
6828         }
6829         state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
6830                                                 state->cli, name);
6831         if (tevent_req_nomem(state->reqs[i], req)) {
6832                 return;
6833         }
6834         name = talloc_move(state->reqs[i], &name);
6835         tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
6836         state->sent += 1;
6837 }
6838
6839 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
6840 {
6841         return tevent_req_simple_recv_ntstatus(req);
6842 }
6843
6844 struct swallow_notify_state {
6845         struct tevent_context *ev;
6846         struct cli_state *cli;
6847         uint16_t fnum;
6848         uint32_t completion_filter;
6849         bool recursive;
6850         bool (*fn)(uint32_t action, const char *name, void *priv);
6851         void *priv;
6852 };
6853
6854 static void swallow_notify_done(struct tevent_req *subreq);
6855
6856 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
6857                                               struct tevent_context *ev,
6858                                               struct cli_state *cli,
6859                                               uint16_t fnum,
6860                                               uint32_t completion_filter,
6861                                               bool recursive,
6862                                               bool (*fn)(uint32_t action,
6863                                                          const char *name,
6864                                                          void *priv),
6865                                               void *priv)
6866 {
6867         struct tevent_req *req, *subreq;
6868         struct swallow_notify_state *state;
6869
6870         req = tevent_req_create(mem_ctx, &state,
6871                                 struct swallow_notify_state);
6872         if (req == NULL) {
6873                 return NULL;
6874         }
6875         state->ev = ev;
6876         state->cli = cli;
6877         state->fnum = fnum;
6878         state->completion_filter = completion_filter;
6879         state->recursive = recursive;
6880         state->fn = fn;
6881         state->priv = priv;
6882
6883         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6884                                  0xffff, state->completion_filter,
6885                                  state->recursive);
6886         if (tevent_req_nomem(subreq, req)) {
6887                 return tevent_req_post(req, ev);
6888         }
6889         tevent_req_set_callback(subreq, swallow_notify_done, req);
6890         return req;
6891 }
6892
6893 static void swallow_notify_done(struct tevent_req *subreq)
6894 {
6895         struct tevent_req *req = tevent_req_callback_data(
6896                 subreq, struct tevent_req);
6897         struct swallow_notify_state *state = tevent_req_data(
6898                 req, struct swallow_notify_state);
6899         NTSTATUS status;
6900         uint32_t i, num_changes;
6901         struct notify_change *changes;
6902
6903         status = cli_notify_recv(subreq, state, &num_changes, &changes);
6904         TALLOC_FREE(subreq);
6905         if (!NT_STATUS_IS_OK(status)) {
6906                 DEBUG(10, ("cli_notify_recv returned %s\n",
6907                            nt_errstr(status)));
6908                 tevent_req_nterror(req, status);
6909                 return;
6910         }
6911
6912         for (i=0; i<num_changes; i++) {
6913                 state->fn(changes[i].action, changes[i].name, state->priv);
6914         }
6915         TALLOC_FREE(changes);
6916
6917         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6918                                  0xffff, state->completion_filter,
6919                                  state->recursive);
6920         if (tevent_req_nomem(subreq, req)) {
6921                 return;
6922         }
6923         tevent_req_set_callback(subreq, swallow_notify_done, req);
6924 }
6925
6926 static bool print_notifies(uint32_t action, const char *name, void *priv)
6927 {
6928         if (DEBUGLEVEL > 5) {
6929                 d_printf("%d %s\n", (int)action, name);
6930         }
6931         return true;
6932 }
6933
6934 static void notify_bench_done(struct tevent_req *req)
6935 {
6936         int *num_finished = (int *)tevent_req_callback_data_void(req);
6937         *num_finished += 1;
6938 }
6939
6940 static bool run_notify_bench(int dummy)
6941 {
6942         const char *dname = "\\notify-bench";
6943         struct tevent_context *ev;
6944         NTSTATUS status;
6945         uint16_t dnum;
6946         struct tevent_req *req1;
6947         struct tevent_req *req2 = NULL;
6948         int i, num_unc_names;
6949         int num_finished = 0;
6950
6951         printf("starting notify-bench test\n");
6952
6953         if (use_multishare_conn) {
6954                 char **unc_list;
6955                 unc_list = file_lines_load(multishare_conn_fname,
6956                                            &num_unc_names, 0, NULL);
6957                 if (!unc_list || num_unc_names <= 0) {
6958                         d_printf("Failed to load unc names list from '%s'\n",
6959                                  multishare_conn_fname);
6960                         return false;
6961                 }
6962                 TALLOC_FREE(unc_list);
6963         } else {
6964                 num_unc_names = 1;
6965         }
6966
6967         ev = tevent_context_init(talloc_tos());
6968         if (ev == NULL) {
6969                 d_printf("tevent_context_init failed\n");
6970                 return false;
6971         }
6972
6973         for (i=0; i<num_unc_names; i++) {
6974                 struct cli_state *cli;
6975                 char *base_fname;
6976
6977                 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
6978                                              dname, i);
6979                 if (base_fname == NULL) {
6980                         return false;
6981                 }
6982
6983                 if (!torture_open_connection(&cli, i)) {
6984                         return false;
6985                 }
6986
6987                 status = cli_ntcreate(cli, dname, 0,
6988                                       MAXIMUM_ALLOWED_ACCESS,
6989                                       0, FILE_SHARE_READ|FILE_SHARE_WRITE|
6990                                       FILE_SHARE_DELETE,
6991                                       FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
6992                                       &dnum);
6993
6994                 if (!NT_STATUS_IS_OK(status)) {
6995                         d_printf("Could not create %s: %s\n", dname,
6996                                  nt_errstr(status));
6997                         return false;
6998                 }
6999
7000                 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
7001                                            FILE_NOTIFY_CHANGE_FILE_NAME |
7002                                            FILE_NOTIFY_CHANGE_DIR_NAME |
7003                                            FILE_NOTIFY_CHANGE_ATTRIBUTES |
7004                                            FILE_NOTIFY_CHANGE_LAST_WRITE,
7005                                            false, print_notifies, NULL);
7006                 if (req1 == NULL) {
7007                         d_printf("Could not create notify request\n");
7008                         return false;
7009                 }
7010
7011                 req2 = torture_createdels_send(talloc_tos(), ev, cli,
7012                                                base_fname, 10, torture_numops);
7013                 if (req2 == NULL) {
7014                         d_printf("Could not create createdels request\n");
7015                         return false;
7016                 }
7017                 TALLOC_FREE(base_fname);
7018
7019                 tevent_req_set_callback(req2, notify_bench_done,
7020                                         &num_finished);
7021         }
7022
7023         while (num_finished < num_unc_names) {
7024                 int ret;
7025                 ret = tevent_loop_once(ev);
7026                 if (ret != 0) {
7027                         d_printf("tevent_loop_once failed\n");
7028                         return false;
7029                 }
7030         }
7031
7032         if (!tevent_req_poll(req2, ev)) {
7033                 d_printf("tevent_req_poll failed\n");
7034         }
7035
7036         status = torture_createdels_recv(req2);
7037         d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
7038
7039         return true;
7040 }
7041
7042 static bool run_mangle1(int dummy)
7043 {
7044         struct cli_state *cli;
7045         const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
7046         uint16_t fnum;
7047         fstring alt_name;
7048         NTSTATUS status;
7049         time_t change_time, access_time, write_time;
7050         off_t size;
7051         uint16_t mode;
7052
7053         printf("starting mangle1 test\n");
7054         if (!torture_open_connection(&cli, 0)) {
7055                 return False;
7056         }
7057
7058         smbXcli_conn_set_sockopt(cli->conn, sockops);
7059
7060         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
7061                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
7062                               0, 0, &fnum);
7063         if (!NT_STATUS_IS_OK(status)) {
7064                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
7065                 return false;
7066         }
7067         cli_close(cli, fnum);
7068
7069         status = cli_qpathinfo_alt_name(cli, fname, alt_name);
7070         if (!NT_STATUS_IS_OK(status)) {
7071                 d_printf("cli_qpathinfo_alt_name failed: %s\n",
7072                          nt_errstr(status));
7073                 return false;
7074         }
7075         d_printf("alt_name: %s\n", alt_name);
7076
7077         status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
7078         if (!NT_STATUS_IS_OK(status)) {
7079                 d_printf("cli_openx(%s) failed: %s\n", alt_name,
7080                          nt_errstr(status));
7081                 return false;
7082         }
7083         cli_close(cli, fnum);
7084
7085         status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
7086                                 &write_time, &size, &mode);
7087         if (!NT_STATUS_IS_OK(status)) {
7088                 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
7089                          nt_errstr(status));
7090                 return false;
7091         }
7092
7093         return true;
7094 }
7095
7096 static size_t null_source(uint8_t *buf, size_t n, void *priv)
7097 {
7098         size_t *to_pull = (size_t *)priv;
7099         size_t thistime = *to_pull;
7100
7101         thistime = MIN(thistime, n);
7102         if (thistime == 0) {
7103                 return 0;
7104         }
7105
7106         memset(buf, 0, thistime);
7107         *to_pull -= thistime;
7108         return thistime;
7109 }
7110
7111 static bool run_windows_write(int dummy)
7112 {
7113         struct cli_state *cli1;
7114         uint16_t fnum;
7115         int i;
7116         bool ret = false;
7117         const char *fname = "\\writetest.txt";
7118         struct timeval start_time;
7119         double seconds;
7120         double kbytes;
7121         NTSTATUS status;
7122
7123         printf("starting windows_write test\n");
7124         if (!torture_open_connection(&cli1, 0)) {
7125                 return False;
7126         }
7127
7128         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
7129         if (!NT_STATUS_IS_OK(status)) {
7130                 printf("open failed (%s)\n", nt_errstr(status));
7131                 return False;
7132         }
7133
7134         smbXcli_conn_set_sockopt(cli1->conn, sockops);
7135
7136         start_time = timeval_current();
7137
7138         for (i=0; i<torture_numops; i++) {
7139                 uint8_t c = 0;
7140                 off_t start = i * torture_blocksize;
7141                 size_t to_pull = torture_blocksize - 1;
7142
7143                 status = cli_writeall(cli1, fnum, 0, &c,
7144                                       start + torture_blocksize - 1, 1, NULL);
7145                 if (!NT_STATUS_IS_OK(status)) {
7146                         printf("cli_write failed: %s\n", nt_errstr(status));
7147                         goto fail;
7148                 }
7149
7150                 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
7151                                   null_source, &to_pull);
7152                 if (!NT_STATUS_IS_OK(status)) {
7153                         printf("cli_push returned: %s\n", nt_errstr(status));
7154                         goto fail;
7155                 }
7156         }
7157
7158         seconds = timeval_elapsed(&start_time);
7159         kbytes = (double)torture_blocksize * torture_numops;
7160         kbytes /= 1024;
7161
7162         printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
7163                (double)seconds, (int)(kbytes/seconds));
7164
7165         ret = true;
7166  fail:
7167         cli_close(cli1, fnum);
7168         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7169         torture_close_connection(cli1);
7170         return ret;
7171 }
7172
7173 static bool run_cli_echo(int dummy)
7174 {
7175         struct cli_state *cli;
7176         NTSTATUS status;
7177
7178         printf("starting cli_echo test\n");
7179         if (!torture_open_connection(&cli, 0)) {
7180                 return false;
7181         }
7182         smbXcli_conn_set_sockopt(cli->conn, sockops);
7183
7184         status = cli_echo(cli, 5, data_blob_const("hello", 5));
7185
7186         d_printf("cli_echo returned %s\n", nt_errstr(status));
7187
7188         torture_close_connection(cli);
7189         return NT_STATUS_IS_OK(status);
7190 }
7191
7192 static bool run_uid_regression_test(int dummy)
7193 {
7194         static struct cli_state *cli;
7195         int16_t old_vuid;
7196         int16_t old_cnum;
7197         bool correct = True;
7198         NTSTATUS status;
7199
7200         printf("starting uid regression test\n");
7201
7202         if (!torture_open_connection(&cli, 0)) {
7203                 return False;
7204         }
7205
7206         smbXcli_conn_set_sockopt(cli->conn, sockops);
7207
7208         /* Ok - now save then logoff our current user. */
7209         old_vuid = cli_state_get_uid(cli);
7210
7211         status = cli_ulogoff(cli);
7212         if (!NT_STATUS_IS_OK(status)) {
7213                 d_printf("(%s) cli_ulogoff failed: %s\n",
7214                          __location__, nt_errstr(status));
7215                 correct = false;
7216                 goto out;
7217         }
7218
7219         cli_state_set_uid(cli, old_vuid);
7220
7221         /* Try an operation. */
7222         status = cli_mkdir(cli, "\\uid_reg_test");
7223         if (NT_STATUS_IS_OK(status)) {
7224                 d_printf("(%s) cli_mkdir succeeded\n",
7225                          __location__);
7226                 correct = false;
7227                 goto out;
7228         } else {
7229                 /* Should be bad uid. */
7230                 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
7231                                  NT_STATUS_USER_SESSION_DELETED)) {
7232                         correct = false;
7233                         goto out;
7234                 }
7235         }
7236
7237         old_cnum = cli_state_get_tid(cli);
7238
7239         /* Now try a SMBtdis with the invald vuid set to zero. */
7240         cli_state_set_uid(cli, 0);
7241
7242         /* This should succeed. */
7243         status = cli_tdis(cli);
7244
7245         if (NT_STATUS_IS_OK(status)) {
7246                 d_printf("First tdis with invalid vuid should succeed.\n");
7247         } else {
7248                 d_printf("First tdis failed (%s)\n", nt_errstr(status));
7249                 correct = false;
7250                 goto out;
7251         }
7252
7253         cli_state_set_uid(cli, old_vuid);
7254         cli_state_set_tid(cli, old_cnum);
7255
7256         /* This should fail. */
7257         status = cli_tdis(cli);
7258         if (NT_STATUS_IS_OK(status)) {
7259                 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
7260                 correct = false;
7261                 goto out;
7262         } else {
7263                 /* Should be bad tid. */
7264                 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
7265                                 NT_STATUS_NETWORK_NAME_DELETED)) {
7266                         correct = false;
7267                         goto out;
7268                 }
7269         }
7270
7271         cli_rmdir(cli, "\\uid_reg_test");
7272
7273   out:
7274
7275         cli_shutdown(cli);
7276         return correct;
7277 }
7278
7279
7280 static const char *illegal_chars = "*\\/?<>|\":";
7281 static char force_shortname_chars[] = " +,.[];=\177";
7282
7283 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
7284                              const char *mask, void *state)
7285 {
7286         struct cli_state *pcli = (struct cli_state *)state;
7287         fstring fname;
7288         NTSTATUS status = NT_STATUS_OK;
7289
7290         slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
7291
7292         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
7293                 return NT_STATUS_OK;
7294
7295         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
7296                 status = cli_rmdir(pcli, fname);
7297                 if (!NT_STATUS_IS_OK(status)) {
7298                         printf("del_fn: failed to rmdir %s\n,", fname );
7299                 }
7300         } else {
7301                 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7302                 if (!NT_STATUS_IS_OK(status)) {
7303                         printf("del_fn: failed to unlink %s\n,", fname );
7304                 }
7305         }
7306         return status;
7307 }
7308
7309 struct sn_state {
7310         int matched;
7311         int i;
7312         bool val;
7313 };
7314
7315 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
7316                               const char *name, void *state)
7317 {
7318         struct sn_state *s = (struct sn_state  *)state;
7319         int i = s->i;
7320
7321 #if 0
7322         printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
7323                 i, finfo->name, finfo->short_name);
7324 #endif
7325
7326         if (strchr(force_shortname_chars, i)) {
7327                 if (!finfo->short_name) {
7328                         /* Shortname not created when it should be. */
7329                         d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
7330                                 __location__, finfo->name, i);
7331                         s->val = true;
7332                 }
7333         } else if (finfo->short_name){
7334                 /* Shortname created when it should not be. */
7335                 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
7336                         __location__, finfo->short_name, finfo->name);
7337                 s->val = true;
7338         }
7339         s->matched += 1;
7340         return NT_STATUS_OK;
7341 }
7342
7343 static bool run_shortname_test(int dummy)
7344 {
7345         static struct cli_state *cli;
7346         bool correct = True;
7347         int i;
7348         struct sn_state s;
7349         char fname[40];
7350         NTSTATUS status;
7351
7352         printf("starting shortname test\n");
7353
7354         if (!torture_open_connection(&cli, 0)) {
7355                 return False;
7356         }
7357
7358         smbXcli_conn_set_sockopt(cli->conn, sockops);
7359
7360         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7361         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7362         cli_rmdir(cli, "\\shortname");
7363
7364         status = cli_mkdir(cli, "\\shortname");
7365         if (!NT_STATUS_IS_OK(status)) {
7366                 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
7367                         __location__, nt_errstr(status));
7368                 correct = false;
7369                 goto out;
7370         }
7371
7372         if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
7373                 correct = false;
7374                 goto out;
7375         }
7376         if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
7377                 correct = false;
7378                 goto out;
7379         }
7380
7381         s.val = false;
7382
7383         for (i = 32; i < 128; i++) {
7384                 uint16_t fnum = (uint16_t)-1;
7385
7386                 s.i = i;
7387
7388                 if (strchr(illegal_chars, i)) {
7389                         continue;
7390                 }
7391                 fname[15] = i;
7392
7393                 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
7394                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum);
7395                 if (!NT_STATUS_IS_OK(status)) {
7396                         d_printf("(%s) cli_nt_create of %s failed: %s\n",
7397                                 __location__, fname, nt_errstr(status));
7398                         correct = false;
7399                         goto out;
7400                 }
7401                 cli_close(cli, fnum);
7402
7403                 s.matched = 0;
7404                 status = cli_list(cli, "\\shortname\\test*.*", 0,
7405                                   shortname_list_fn, &s);
7406                 if (s.matched != 1) {
7407                         d_printf("(%s) failed to list %s: %s\n",
7408                                 __location__, fname, nt_errstr(status));
7409                         correct = false;
7410                         goto out;
7411                 }
7412
7413                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7414                 if (!NT_STATUS_IS_OK(status)) {
7415                         d_printf("(%s) failed to delete %s: %s\n",
7416                                 __location__, fname, nt_errstr(status));
7417                         correct = false;
7418                         goto out;
7419                 }
7420
7421                 if (s.val) {
7422                         correct = false;
7423                         goto out;
7424                 }
7425         }
7426
7427   out:
7428
7429         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7430         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7431         cli_rmdir(cli, "\\shortname");
7432         torture_close_connection(cli);
7433         return correct;
7434 }
7435
7436 static void pagedsearch_cb(struct tevent_req *req)
7437 {
7438         int rc;
7439         struct tldap_message *msg;
7440         char *dn;
7441
7442         rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
7443         if (rc != TLDAP_SUCCESS) {
7444                 d_printf("tldap_search_paged_recv failed: %s\n",
7445                          tldap_err2string(rc));
7446                 return;
7447         }
7448         if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
7449                 TALLOC_FREE(msg);
7450                 return;
7451         }
7452         if (!tldap_entry_dn(msg, &dn)) {
7453                 d_printf("tldap_entry_dn failed\n");
7454                 return;
7455         }
7456         d_printf("%s\n", dn);
7457         TALLOC_FREE(msg);
7458 }
7459
7460 static bool run_tldap(int dummy)
7461 {
7462         struct tldap_context *ld;
7463         int fd, rc;
7464         NTSTATUS status;
7465         struct sockaddr_storage addr;
7466         struct tevent_context *ev;
7467         struct tevent_req *req;
7468         char *basedn;
7469         const char *filter;
7470
7471         if (!resolve_name(host, &addr, 0, false)) {
7472                 d_printf("could not find host %s\n", host);
7473                 return false;
7474         }
7475         status = open_socket_out(&addr, 389, 9999, &fd);
7476         if (!NT_STATUS_IS_OK(status)) {
7477                 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
7478                 return false;
7479         }
7480
7481         ld = tldap_context_create(talloc_tos(), fd);
7482         if (ld == NULL) {
7483                 close(fd);
7484                 d_printf("tldap_context_create failed\n");
7485                 return false;
7486         }
7487
7488         rc = tldap_fetch_rootdse(ld);
7489         if (rc != TLDAP_SUCCESS) {
7490                 d_printf("tldap_fetch_rootdse failed: %s\n",
7491                          tldap_errstr(talloc_tos(), ld, rc));
7492                 return false;
7493         }
7494
7495         basedn = tldap_talloc_single_attribute(
7496                 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
7497         if (basedn == NULL) {
7498                 d_printf("no defaultNamingContext\n");
7499                 return false;
7500         }
7501         d_printf("defaultNamingContext: %s\n", basedn);
7502
7503         ev = tevent_context_init(talloc_tos());
7504         if (ev == NULL) {
7505                 d_printf("tevent_context_init failed\n");
7506                 return false;
7507         }
7508
7509         req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
7510                                       TLDAP_SCOPE_SUB, "(objectclass=*)",
7511                                       NULL, 0, 0,
7512                                       NULL, 0, NULL, 0, 0, 0, 0, 5);
7513         if (req == NULL) {
7514                 d_printf("tldap_search_paged_send failed\n");
7515                 return false;
7516         }
7517         tevent_req_set_callback(req, pagedsearch_cb, NULL);
7518
7519         tevent_req_poll(req, ev);
7520
7521         TALLOC_FREE(req);
7522
7523         /* test search filters against rootDSE */
7524         filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
7525                    "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
7526
7527         rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
7528                           NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
7529                           talloc_tos(), NULL, NULL);
7530         if (rc != TLDAP_SUCCESS) {
7531                 d_printf("tldap_search with complex filter failed: %s\n",
7532                          tldap_errstr(talloc_tos(), ld, rc));
7533                 return false;
7534         }
7535
7536         TALLOC_FREE(ld);
7537         return true;
7538 }
7539
7540 /* Torture test to ensure no regression of :
7541 https://bugzilla.samba.org/show_bug.cgi?id=7084
7542 */
7543
7544 static bool run_dir_createtime(int dummy)
7545 {
7546         struct cli_state *cli;
7547         const char *dname = "\\testdir";
7548         const char *fname = "\\testdir\\testfile";
7549         NTSTATUS status;
7550         struct timespec create_time;
7551         struct timespec create_time1;
7552         uint16_t fnum;
7553         bool ret = false;
7554
7555         if (!torture_open_connection(&cli, 0)) {
7556                 return false;
7557         }
7558
7559         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7560         cli_rmdir(cli, dname);
7561
7562         status = cli_mkdir(cli, dname);
7563         if (!NT_STATUS_IS_OK(status)) {
7564                 printf("mkdir failed: %s\n", nt_errstr(status));
7565                 goto out;
7566         }
7567
7568         status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
7569                                 NULL, NULL, NULL);
7570         if (!NT_STATUS_IS_OK(status)) {
7571                 printf("cli_qpathinfo2 returned %s\n",
7572                        nt_errstr(status));
7573                 goto out;
7574         }
7575
7576         /* Sleep 3 seconds, then create a file. */
7577         sleep(3);
7578
7579         status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
7580                          DENY_NONE, &fnum);
7581         if (!NT_STATUS_IS_OK(status)) {
7582                 printf("cli_openx failed: %s\n", nt_errstr(status));
7583                 goto out;
7584         }
7585
7586         status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
7587                                 NULL, NULL, NULL);
7588         if (!NT_STATUS_IS_OK(status)) {
7589                 printf("cli_qpathinfo2 (2) returned %s\n",
7590                        nt_errstr(status));
7591                 goto out;
7592         }
7593
7594         if (timespec_compare(&create_time1, &create_time)) {
7595                 printf("run_dir_createtime: create time was updated (error)\n");
7596         } else {
7597                 printf("run_dir_createtime: create time was not updated (correct)\n");
7598                 ret = true;
7599         }
7600
7601   out:
7602
7603         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7604         cli_rmdir(cli, dname);
7605         if (!torture_close_connection(cli)) {
7606                 ret = false;
7607         }
7608         return ret;
7609 }
7610
7611
7612 static bool run_streamerror(int dummy)
7613 {
7614         struct cli_state *cli;
7615         const char *dname = "\\testdir";
7616         const char *streamname =
7617                 "testdir:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
7618         NTSTATUS status;
7619         time_t change_time, access_time, write_time;
7620         off_t size;
7621         uint16_t mode, fnum;
7622         bool ret = true;
7623
7624         if (!torture_open_connection(&cli, 0)) {
7625                 return false;
7626         }
7627
7628         cli_unlink(cli, "\\testdir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7629         cli_rmdir(cli, dname);
7630
7631         status = cli_mkdir(cli, dname);
7632         if (!NT_STATUS_IS_OK(status)) {
7633                 printf("mkdir failed: %s\n", nt_errstr(status));
7634                 return false;
7635         }
7636
7637         status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
7638                                 &write_time, &size, &mode);
7639         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7640                 printf("pathinfo returned %s, expected "
7641                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
7642                        nt_errstr(status));
7643                 ret = false;
7644         }
7645
7646         status = cli_ntcreate(cli, streamname, 0x16,
7647                               FILE_READ_DATA|FILE_READ_EA|
7648                               FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
7649                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7650                               FILE_OPEN, 0, 0, &fnum);
7651
7652         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7653                 printf("ntcreate returned %s, expected "
7654                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
7655                        nt_errstr(status));
7656                 ret = false;
7657         }
7658
7659
7660         cli_rmdir(cli, dname);
7661         return ret;
7662 }
7663
7664 static bool run_local_substitute(int dummy)
7665 {
7666         bool ok = true;
7667
7668         ok &= subst_test("%U", "bla", "", -1, -1, "bla");
7669         ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
7670         ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
7671         ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
7672         ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
7673         ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
7674         ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
7675         ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
7676
7677         /* Different captialization rules in sub_basic... */
7678
7679         ok &=  (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
7680                        "blaDOM") == 0);
7681
7682         return ok;
7683 }
7684
7685 static bool run_local_base64(int dummy)
7686 {
7687         int i;
7688         bool ret = true;
7689
7690         for (i=1; i<2000; i++) {
7691                 DATA_BLOB blob1, blob2;
7692                 char *b64;
7693
7694                 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
7695                 blob1.length = i;
7696                 generate_random_buffer(blob1.data, blob1.length);
7697
7698                 b64 = base64_encode_data_blob(talloc_tos(), blob1);
7699                 if (b64 == NULL) {
7700                         d_fprintf(stderr, "base64_encode_data_blob failed "
7701                                   "for %d bytes\n", i);
7702                         ret = false;
7703                 }
7704                 blob2 = base64_decode_data_blob(b64);
7705                 TALLOC_FREE(b64);
7706
7707                 if (data_blob_cmp(&blob1, &blob2)) {
7708                         d_fprintf(stderr, "data_blob_cmp failed for %d "
7709                                   "bytes\n", i);
7710                         ret = false;
7711                 }
7712                 TALLOC_FREE(blob1.data);
7713                 data_blob_free(&blob2);
7714         }
7715         return ret;
7716 }
7717
7718 static bool run_local_gencache(int dummy)
7719 {
7720         char *val;
7721         time_t tm;
7722         DATA_BLOB blob;
7723
7724         if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
7725                 d_printf("%s: gencache_set() failed\n", __location__);
7726                 return False;
7727         }
7728
7729         if (!gencache_get("foo", NULL, NULL)) {
7730                 d_printf("%s: gencache_get() failed\n", __location__);
7731                 return False;
7732         }
7733
7734         if (!gencache_get("foo", &val, &tm)) {
7735                 d_printf("%s: gencache_get() failed\n", __location__);
7736                 return False;
7737         }
7738
7739         if (strcmp(val, "bar") != 0) {
7740                 d_printf("%s: gencache_get() returned %s, expected %s\n",
7741                          __location__, val, "bar");
7742                 SAFE_FREE(val);
7743                 return False;
7744         }
7745
7746         SAFE_FREE(val);
7747
7748         if (!gencache_del("foo")) {
7749                 d_printf("%s: gencache_del() failed\n", __location__);
7750                 return False;
7751         }
7752         if (gencache_del("foo")) {
7753                 d_printf("%s: second gencache_del() succeeded\n",
7754                          __location__);
7755                 return False;
7756         }
7757
7758         if (gencache_get("foo", &val, &tm)) {
7759                 d_printf("%s: gencache_get() on deleted entry "
7760                          "succeeded\n", __location__);
7761                 return False;
7762         }
7763
7764         blob = data_blob_string_const_null("bar");
7765         tm = time(NULL) + 60;
7766
7767         if (!gencache_set_data_blob("foo", &blob, tm)) {
7768                 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
7769                 return False;
7770         }
7771
7772         if (!gencache_get_data_blob("foo", &blob, NULL, NULL)) {
7773                 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
7774                 return False;
7775         }
7776
7777         if (strcmp((const char *)blob.data, "bar") != 0) {
7778                 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
7779                          __location__, (const char *)blob.data, "bar");
7780                 data_blob_free(&blob);
7781                 return False;
7782         }
7783
7784         data_blob_free(&blob);
7785
7786         if (!gencache_del("foo")) {
7787                 d_printf("%s: gencache_del() failed\n", __location__);
7788                 return False;
7789         }
7790         if (gencache_del("foo")) {
7791                 d_printf("%s: second gencache_del() succeeded\n",
7792                          __location__);
7793                 return False;
7794         }
7795
7796         if (gencache_get_data_blob("foo", &blob, NULL, NULL)) {
7797                 d_printf("%s: gencache_get_data_blob() on deleted entry "
7798                          "succeeded\n", __location__);
7799                 return False;
7800         }
7801
7802         return True;
7803 }
7804
7805 static bool rbt_testval(struct db_context *db, const char *key,
7806                         const char *value)
7807 {
7808         struct db_record *rec;
7809         TDB_DATA data = string_tdb_data(value);
7810         bool ret = false;
7811         NTSTATUS status;
7812         TDB_DATA dbvalue;
7813
7814         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
7815         if (rec == NULL) {
7816                 d_fprintf(stderr, "fetch_locked failed\n");
7817                 goto done;
7818         }
7819         status = dbwrap_record_store(rec, data, 0);
7820         if (!NT_STATUS_IS_OK(status)) {
7821                 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
7822                 goto done;
7823         }
7824         TALLOC_FREE(rec);
7825
7826         rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
7827         if (rec == NULL) {
7828                 d_fprintf(stderr, "second fetch_locked failed\n");
7829                 goto done;
7830         }
7831
7832         dbvalue = dbwrap_record_get_value(rec);
7833         if ((dbvalue.dsize != data.dsize)
7834             || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
7835                 d_fprintf(stderr, "Got wrong data back\n");
7836                 goto done;
7837         }
7838
7839         ret = true;
7840  done:
7841         TALLOC_FREE(rec);
7842         return ret;
7843 }
7844
7845 static bool run_local_rbtree(int dummy)
7846 {
7847         struct db_context *db;
7848         bool ret = false;
7849         int i;
7850
7851         db = db_open_rbt(NULL);
7852
7853         if (db == NULL) {
7854                 d_fprintf(stderr, "db_open_rbt failed\n");
7855                 return false;
7856         }
7857
7858         for (i=0; i<1000; i++) {
7859                 char *key, *value;
7860
7861                 if (asprintf(&key, "key%ld", random()) == -1) {
7862                         goto done;
7863                 }
7864                 if (asprintf(&value, "value%ld", random()) == -1) {
7865                         SAFE_FREE(key);
7866                         goto done;
7867                 }
7868
7869                 if (!rbt_testval(db, key, value)) {
7870                         SAFE_FREE(key);
7871                         SAFE_FREE(value);
7872                         goto done;
7873                 }
7874
7875                 SAFE_FREE(value);
7876                 if (asprintf(&value, "value%ld", random()) == -1) {
7877                         SAFE_FREE(key);
7878                         goto done;
7879                 }
7880
7881                 if (!rbt_testval(db, key, value)) {
7882                         SAFE_FREE(key);
7883                         SAFE_FREE(value);
7884                         goto done;
7885                 }
7886
7887                 SAFE_FREE(key);
7888                 SAFE_FREE(value);
7889         }
7890
7891         ret = true;
7892
7893  done:
7894         TALLOC_FREE(db);
7895         return ret;
7896 }
7897
7898
7899 /*
7900   local test for character set functions
7901
7902   This is a very simple test for the functionality in convert_string_error()
7903  */
7904 static bool run_local_convert_string(int dummy)
7905 {
7906         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
7907         const char *test_strings[2] = { "March", "M\303\244rz" };
7908         char dst[7];
7909         int i;
7910
7911         for (i=0; i<2; i++) {
7912                 const char *str = test_strings[i];
7913                 int len = strlen(str);
7914                 size_t converted_size;
7915                 bool ret;
7916
7917                 memset(dst, 'X', sizeof(dst));
7918
7919                 /* first try with real source length */
7920                 ret = convert_string_error(CH_UNIX, CH_UTF8,
7921                                            str, len,
7922                                            dst, sizeof(dst),
7923                                            &converted_size);
7924                 if (ret != true) {
7925                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
7926                         goto failed;
7927                 }
7928
7929                 if (converted_size != len) {
7930                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
7931                                   str, len, (int)converted_size);
7932                         goto failed;
7933                 }
7934
7935                 if (strncmp(str, dst, converted_size) != 0) {
7936                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
7937                         goto failed;
7938                 }
7939
7940                 if (strlen(str) != converted_size) {
7941                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
7942                                   (int)strlen(str), (int)converted_size);
7943                         goto failed;
7944                 }
7945
7946                 if (dst[converted_size] != 'X') {
7947                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
7948                         goto failed;
7949                 }
7950
7951                 /* now with srclen==-1, this causes the nul to be
7952                  * converted too */
7953                 ret = convert_string_error(CH_UNIX, CH_UTF8,
7954                                            str, -1,
7955                                            dst, sizeof(dst),
7956                                            &converted_size);
7957                 if (ret != true) {
7958                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
7959                         goto failed;
7960                 }
7961
7962                 if (converted_size != len+1) {
7963                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
7964                                   str, len, (int)converted_size);
7965                         goto failed;
7966                 }
7967
7968                 if (strncmp(str, dst, converted_size) != 0) {
7969                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
7970                         goto failed;
7971                 }
7972
7973                 if (len+1 != converted_size) {
7974                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
7975                                   len+1, (int)converted_size);
7976                         goto failed;
7977                 }
7978
7979                 if (dst[converted_size] != 'X') {
7980                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
7981                         goto failed;
7982                 }
7983
7984         }
7985
7986
7987         TALLOC_FREE(tmp_ctx);
7988         return true;
7989 failed:
7990         TALLOC_FREE(tmp_ctx);
7991         return false;
7992 }
7993
7994
7995 struct talloc_dict_test {
7996         int content;
7997 };
7998
7999 static int talloc_dict_traverse_fn(DATA_BLOB key, void *data, void *priv)
8000 {
8001         int *count = (int *)priv;
8002         *count += 1;
8003         return 0;
8004 }
8005
8006 static bool run_local_talloc_dict(int dummy)
8007 {
8008         struct talloc_dict *dict;
8009         struct talloc_dict_test *t;
8010         int key, count, res;
8011         bool ok;
8012
8013         dict = talloc_dict_init(talloc_tos());
8014         if (dict == NULL) {
8015                 return false;
8016         }
8017
8018         t = talloc(talloc_tos(), struct talloc_dict_test);
8019         if (t == NULL) {
8020                 return false;
8021         }
8022
8023         key = 1;
8024         t->content = 1;
8025         ok = talloc_dict_set(dict, data_blob_const(&key, sizeof(key)), &t);
8026         if (!ok) {
8027                 return false;
8028         }
8029
8030         count = 0;
8031         res = talloc_dict_traverse(dict, talloc_dict_traverse_fn, &count);
8032         if (res == -1) {
8033                 return false;
8034         }
8035
8036         if (count != 1) {
8037                 return false;
8038         }
8039
8040         if (count != res) {
8041                 return false;
8042         }
8043
8044         TALLOC_FREE(dict);
8045
8046         return true;
8047 }
8048
8049 static bool run_local_string_to_sid(int dummy) {
8050         struct dom_sid sid;
8051
8052         if (string_to_sid(&sid, "S--1-5-32-545")) {
8053                 printf("allowing S--1-5-32-545\n");
8054                 return false;
8055         }
8056         if (string_to_sid(&sid, "S-1-5-32-+545")) {
8057                 printf("allowing S-1-5-32-+545\n");
8058                 return false;
8059         }
8060         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")) {
8061                 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
8062                 return false;
8063         }
8064         if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
8065                 printf("allowing S-1-5-32-545-abc\n");
8066                 return false;
8067         }
8068         if (!string_to_sid(&sid, "S-1-5-32-545")) {
8069                 printf("could not parse S-1-5-32-545\n");
8070                 return false;
8071         }
8072         if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
8073                 printf("mis-parsed S-1-5-32-545 as %s\n",
8074                        sid_string_tos(&sid));
8075                 return false;
8076         }
8077         return true;
8078 }
8079
8080 static bool run_local_binary_to_sid(int dummy) {
8081         struct dom_sid *sid = talloc(NULL, struct dom_sid);
8082         static const char good_binary_sid[] = {
8083                 0x1, /* revision number */
8084                 15, /* num auths */
8085                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8086                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8087                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8088                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8089                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8090                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8091                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8092                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8093                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8094                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8095                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8096                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8097                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8098                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8099                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8100                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8101         };
8102
8103         static const char long_binary_sid[] = {
8104                 0x1, /* revision number */
8105                 15, /* num auths */
8106                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8107                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8108                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8109                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8110                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8111                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8112                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8113                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8114                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8115                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8116                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8117                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8118                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8119                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8120                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8121                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8122                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
8123                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
8124                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
8125         };
8126
8127         static const char long_binary_sid2[] = {
8128                 0x1, /* revision number */
8129                 32, /* num auths */
8130                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8131                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8132                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8133                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8134                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8135                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8136                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8137                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8138                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8139                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8140                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8141                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8142                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8143                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8144                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8145                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8146                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
8147                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
8148                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
8149                 0x1, 0x1, 0x1, 0x1, /* auth[18] */
8150                 0x1, 0x1, 0x1, 0x1, /* auth[19] */
8151                 0x1, 0x1, 0x1, 0x1, /* auth[20] */
8152                 0x1, 0x1, 0x1, 0x1, /* auth[21] */
8153                 0x1, 0x1, 0x1, 0x1, /* auth[22] */
8154                 0x1, 0x1, 0x1, 0x1, /* auth[23] */
8155                 0x1, 0x1, 0x1, 0x1, /* auth[24] */
8156                 0x1, 0x1, 0x1, 0x1, /* auth[25] */
8157                 0x1, 0x1, 0x1, 0x1, /* auth[26] */
8158                 0x1, 0x1, 0x1, 0x1, /* auth[27] */
8159                 0x1, 0x1, 0x1, 0x1, /* auth[28] */
8160                 0x1, 0x1, 0x1, 0x1, /* auth[29] */
8161                 0x1, 0x1, 0x1, 0x1, /* auth[30] */
8162                 0x1, 0x1, 0x1, 0x1, /* auth[31] */
8163         };
8164
8165         if (!sid_parse(good_binary_sid, sizeof(good_binary_sid), sid)) {
8166                 return false;
8167         }
8168         if (sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid)) {
8169                 return false;
8170         }
8171         if (sid_parse(long_binary_sid, sizeof(long_binary_sid), sid)) {
8172                 return false;
8173         }
8174         return true;
8175 }
8176
8177 /* Split a path name into filename and stream name components. Canonicalise
8178  * such that an implicit $DATA token is always explicit.
8179  *
8180  * The "specification" of this function can be found in the
8181  * run_local_stream_name() function in torture.c, I've tried those
8182  * combinations against a W2k3 server.
8183  */
8184
8185 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
8186                                        char **pbase, char **pstream)
8187 {
8188         char *base = NULL;
8189         char *stream = NULL;
8190         char *sname; /* stream name */
8191         const char *stype; /* stream type */
8192
8193         DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
8194
8195         sname = strchr_m(fname, ':');
8196
8197         if (lp_posix_pathnames() || (sname == NULL)) {
8198                 if (pbase != NULL) {
8199                         base = talloc_strdup(mem_ctx, fname);
8200                         NT_STATUS_HAVE_NO_MEMORY(base);
8201                 }
8202                 goto done;
8203         }
8204
8205         if (pbase != NULL) {
8206                 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
8207                 NT_STATUS_HAVE_NO_MEMORY(base);
8208         }
8209
8210         sname += 1;
8211
8212         stype = strchr_m(sname, ':');
8213
8214         if (stype == NULL) {
8215                 sname = talloc_strdup(mem_ctx, sname);
8216                 stype = "$DATA";
8217         }
8218         else {
8219                 if (strcasecmp_m(stype, ":$DATA") != 0) {
8220                         /*
8221                          * If there is an explicit stream type, so far we only
8222                          * allow $DATA. Is there anything else allowed? -- vl
8223                          */
8224                         DEBUG(10, ("[%s] is an invalid stream type\n", stype));
8225                         TALLOC_FREE(base);
8226                         return NT_STATUS_OBJECT_NAME_INVALID;
8227                 }
8228                 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
8229                 stype += 1;
8230         }
8231
8232         if (sname == NULL) {
8233                 TALLOC_FREE(base);
8234                 return NT_STATUS_NO_MEMORY;
8235         }
8236
8237         if (sname[0] == '\0') {
8238                 /*
8239                  * no stream name, so no stream
8240                  */
8241                 goto done;
8242         }
8243
8244         if (pstream != NULL) {
8245                 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
8246                 if (stream == NULL) {
8247                         TALLOC_FREE(sname);
8248                         TALLOC_FREE(base);
8249                         return NT_STATUS_NO_MEMORY;
8250                 }
8251                 /*
8252                  * upper-case the type field
8253                  */
8254                 strupper_m(strchr_m(stream, ':')+1);
8255         }
8256
8257  done:
8258         if (pbase != NULL) {
8259                 *pbase = base;
8260         }
8261         if (pstream != NULL) {
8262                 *pstream = stream;
8263         }
8264         return NT_STATUS_OK;
8265 }
8266
8267 static bool test_stream_name(const char *fname, const char *expected_base,
8268                              const char *expected_stream,
8269                              NTSTATUS expected_status)
8270 {
8271         NTSTATUS status;
8272         char *base = NULL;
8273         char *stream = NULL;
8274
8275         status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
8276         if (!NT_STATUS_EQUAL(status, expected_status)) {
8277                 goto error;
8278         }
8279
8280         if (!NT_STATUS_IS_OK(status)) {
8281                 return true;
8282         }
8283
8284         if (base == NULL) goto error;
8285
8286         if (strcmp(expected_base, base) != 0) goto error;
8287
8288         if ((expected_stream != NULL) && (stream == NULL)) goto error;
8289         if ((expected_stream == NULL) && (stream != NULL)) goto error;
8290
8291         if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
8292                 goto error;
8293
8294         TALLOC_FREE(base);
8295         TALLOC_FREE(stream);
8296         return true;
8297
8298  error:
8299         d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
8300                   fname, expected_base ? expected_base : "<NULL>",
8301                   expected_stream ? expected_stream : "<NULL>",
8302                   nt_errstr(expected_status));
8303         d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
8304                   base ? base : "<NULL>", stream ? stream : "<NULL>",
8305                   nt_errstr(status));
8306         TALLOC_FREE(base);
8307         TALLOC_FREE(stream);
8308         return false;
8309 }
8310
8311 static bool run_local_stream_name(int dummy)
8312 {
8313         bool ret = true;
8314
8315         ret &= test_stream_name(
8316                 "bla", "bla", NULL, NT_STATUS_OK);
8317         ret &= test_stream_name(
8318                 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
8319         ret &= test_stream_name(
8320                 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8321         ret &= test_stream_name(
8322                 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
8323         ret &= test_stream_name(
8324                 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8325         ret &= test_stream_name(
8326                 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
8327         ret &= test_stream_name(
8328                 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
8329         ret &= test_stream_name(
8330                 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
8331
8332         return ret;
8333 }
8334
8335 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
8336 {
8337         if (a.length != b.length) {
8338                 printf("a.length=%d != b.length=%d\n",
8339                        (int)a.length, (int)b.length);
8340                 return false;
8341         }
8342         if (memcmp(a.data, b.data, a.length) != 0) {
8343                 printf("a.data and b.data differ\n");
8344                 return false;
8345         }
8346         return true;
8347 }
8348
8349 static bool run_local_memcache(int dummy)
8350 {
8351         struct memcache *cache;
8352         DATA_BLOB k1, k2;
8353         DATA_BLOB d1, d2, d3;
8354         DATA_BLOB v1, v2, v3;
8355
8356         TALLOC_CTX *mem_ctx;
8357         char *str1, *str2;
8358         size_t size1, size2;
8359         bool ret = false;
8360
8361         cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
8362
8363         if (cache == NULL) {
8364                 printf("memcache_init failed\n");
8365                 return false;
8366         }
8367
8368         d1 = data_blob_const("d1", 2);
8369         d2 = data_blob_const("d2", 2);
8370         d3 = data_blob_const("d3", 2);
8371
8372         k1 = data_blob_const("d1", 2);
8373         k2 = data_blob_const("d2", 2);
8374
8375         memcache_add(cache, STAT_CACHE, k1, d1);
8376         memcache_add(cache, GETWD_CACHE, k2, d2);
8377
8378         if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
8379                 printf("could not find k1\n");
8380                 return false;
8381         }
8382         if (!data_blob_equal(d1, v1)) {
8383                 return false;
8384         }
8385
8386         if (!memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8387                 printf("could not find k2\n");
8388                 return false;
8389         }
8390         if (!data_blob_equal(d2, v2)) {
8391                 return false;
8392         }
8393
8394         memcache_add(cache, STAT_CACHE, k1, d3);
8395
8396         if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
8397                 printf("could not find replaced k1\n");
8398                 return false;
8399         }
8400         if (!data_blob_equal(d3, v3)) {
8401                 return false;
8402         }
8403
8404         memcache_add(cache, GETWD_CACHE, k1, d1);
8405
8406         if (memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8407                 printf("Did find k2, should have been purged\n");
8408                 return false;
8409         }
8410
8411         TALLOC_FREE(cache);
8412
8413         cache = memcache_init(NULL, 0);
8414
8415         mem_ctx = talloc_init("foo");
8416
8417         str1 = talloc_strdup(mem_ctx, "string1");
8418         str2 = talloc_strdup(mem_ctx, "string2");
8419
8420         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8421                             data_blob_string_const("torture"), &str1);
8422         size1 = talloc_total_size(cache);
8423
8424         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8425                             data_blob_string_const("torture"), &str2);
8426         size2 = talloc_total_size(cache);
8427
8428         printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
8429
8430         if (size2 > size1) {
8431                 printf("memcache leaks memory!\n");
8432                 goto fail;
8433         }
8434
8435         ret = true;
8436  fail:
8437         TALLOC_FREE(cache);
8438         return ret;
8439 }
8440
8441 static void wbclient_done(struct tevent_req *req)
8442 {
8443         wbcErr wbc_err;
8444         struct winbindd_response *wb_resp;
8445         int *i = (int *)tevent_req_callback_data_void(req);
8446
8447         wbc_err = wb_trans_recv(req, req, &wb_resp);
8448         TALLOC_FREE(req);
8449         *i += 1;
8450         d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
8451 }
8452
8453 static bool run_local_wbclient(int dummy)
8454 {
8455         struct event_context *ev;
8456         struct wb_context **wb_ctx;
8457         struct winbindd_request wb_req;
8458         bool result = false;
8459         int i, j;
8460
8461         BlockSignals(True, SIGPIPE);
8462
8463         ev = tevent_context_init_byname(talloc_tos(), "epoll");
8464         if (ev == NULL) {
8465                 goto fail;
8466         }
8467
8468         wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
8469         if (wb_ctx == NULL) {
8470                 goto fail;
8471         }
8472
8473         ZERO_STRUCT(wb_req);
8474         wb_req.cmd = WINBINDD_PING;
8475
8476         d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
8477
8478         for (i=0; i<torture_nprocs; i++) {
8479                 wb_ctx[i] = wb_context_init(ev, NULL);
8480                 if (wb_ctx[i] == NULL) {
8481                         goto fail;
8482                 }
8483                 for (j=0; j<torture_numops; j++) {
8484                         struct tevent_req *req;
8485                         req = wb_trans_send(ev, ev, wb_ctx[i],
8486                                             (j % 2) == 0, &wb_req);
8487                         if (req == NULL) {
8488                                 goto fail;
8489                         }
8490                         tevent_req_set_callback(req, wbclient_done, &i);
8491                 }
8492         }
8493
8494         i = 0;
8495
8496         while (i < torture_nprocs * torture_numops) {
8497                 tevent_loop_once(ev);
8498         }
8499
8500         result = true;
8501  fail:
8502         TALLOC_FREE(ev);
8503         return result;
8504 }
8505
8506 static void getaddrinfo_finished(struct tevent_req *req)
8507 {
8508         char *name = (char *)tevent_req_callback_data_void(req);
8509         struct addrinfo *ainfo;
8510         int res;
8511
8512         res = getaddrinfo_recv(req, &ainfo);
8513         if (res != 0) {
8514                 d_printf("gai(%s) returned %s\n", name, gai_strerror(res));
8515                 return;
8516         }
8517         d_printf("gai(%s) succeeded\n", name);
8518         freeaddrinfo(ainfo);
8519 }
8520
8521 static bool run_getaddrinfo_send(int dummy)
8522 {
8523         TALLOC_CTX *frame = talloc_stackframe();
8524         struct fncall_context *ctx;
8525         struct tevent_context *ev;
8526         bool result = false;
8527         const char *names[4] = { "www.samba.org", "notfound.samba.org",
8528                                  "www.slashdot.org", "heise.de" };
8529         struct tevent_req *reqs[4];
8530         int i;
8531
8532         ev = event_context_init(frame);
8533         if (ev == NULL) {
8534                 goto fail;
8535         }
8536
8537         ctx = fncall_context_init(frame, 4);
8538
8539         for (i=0; i<ARRAY_SIZE(names); i++) {
8540                 reqs[i] = getaddrinfo_send(frame, ev, ctx, names[i], NULL,
8541                                            NULL);
8542                 if (reqs[i] == NULL) {
8543                         goto fail;
8544                 }
8545                 tevent_req_set_callback(reqs[i], getaddrinfo_finished,
8546                                         discard_const_p(void, names[i]));
8547         }
8548
8549         for (i=0; i<ARRAY_SIZE(reqs); i++) {
8550                 tevent_loop_once(ev);
8551         }
8552
8553         result = true;
8554 fail:
8555         TALLOC_FREE(frame);
8556         return result;
8557 }
8558
8559 static bool dbtrans_inc(struct db_context *db)
8560 {
8561         struct db_record *rec;
8562         uint32_t val;
8563         bool ret = false;
8564         NTSTATUS status;
8565         TDB_DATA value;
8566
8567         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
8568         if (rec == NULL) {
8569                 printf(__location__ "fetch_lock failed\n");
8570                 return false;
8571         }
8572
8573         value = dbwrap_record_get_value(rec);
8574
8575         if (value.dsize != sizeof(uint32_t)) {
8576                 printf(__location__ "value.dsize = %d\n",
8577                        (int)value.dsize);
8578                 goto fail;
8579         }
8580
8581         memcpy(&val, value.dptr, sizeof(val));
8582         val += 1;
8583
8584         status = dbwrap_record_store(
8585                 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
8586         if (!NT_STATUS_IS_OK(status)) {
8587                 printf(__location__ "store failed: %s\n",
8588                        nt_errstr(status));
8589                 goto fail;
8590         }
8591
8592         ret = true;
8593 fail:
8594         TALLOC_FREE(rec);
8595         return ret;
8596 }
8597
8598 static bool run_local_dbtrans(int dummy)
8599 {
8600         struct db_context *db;
8601         struct db_record *rec;
8602         NTSTATUS status;
8603         uint32_t initial;
8604         int res;
8605         TDB_DATA value;
8606
8607         db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
8608                      O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1);
8609         if (db == NULL) {
8610                 printf("Could not open transtest.db\n");
8611                 return false;
8612         }
8613
8614         res = dbwrap_transaction_start(db);
8615         if (res != 0) {
8616                 printf(__location__ "transaction_start failed\n");
8617                 return false;
8618         }
8619
8620         rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
8621         if (rec == NULL) {
8622                 printf(__location__ "fetch_lock failed\n");
8623                 return false;
8624         }
8625
8626         value = dbwrap_record_get_value(rec);
8627
8628         if (value.dptr == NULL) {
8629                 initial = 0;
8630                 status = dbwrap_record_store(
8631                         rec, make_tdb_data((uint8_t *)&initial,
8632                                            sizeof(initial)),
8633                         0);
8634                 if (!NT_STATUS_IS_OK(status)) {
8635                         printf(__location__ "store returned %s\n",
8636                                nt_errstr(status));
8637                         return false;
8638                 }
8639         }
8640
8641         TALLOC_FREE(rec);
8642
8643         res = dbwrap_transaction_commit(db);
8644         if (res != 0) {
8645                 printf(__location__ "transaction_commit failed\n");
8646                 return false;
8647         }
8648
8649         while (true) {
8650                 uint32_t val, val2;
8651                 int i;
8652
8653                 res = dbwrap_transaction_start(db);
8654                 if (res != 0) {
8655                         printf(__location__ "transaction_start failed\n");
8656                         break;
8657                 }
8658
8659                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
8660                 if (!NT_STATUS_IS_OK(status)) {
8661                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
8662                                nt_errstr(status));
8663                         break;
8664                 }
8665
8666                 for (i=0; i<10; i++) {
8667                         if (!dbtrans_inc(db)) {
8668                                 return false;
8669                         }
8670                 }
8671
8672                 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
8673                 if (!NT_STATUS_IS_OK(status)) {
8674                         printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
8675                                nt_errstr(status));
8676                         break;
8677                 }
8678
8679                 if (val2 != val + 10) {
8680                         printf(__location__ "val=%d, val2=%d\n",
8681                                (int)val, (int)val2);
8682                         break;
8683                 }
8684
8685                 printf("val2=%d\r", val2);
8686
8687                 res = dbwrap_transaction_commit(db);
8688                 if (res != 0) {
8689                         printf(__location__ "transaction_commit failed\n");
8690                         break;
8691                 }
8692         }
8693
8694         TALLOC_FREE(db);
8695         return true;
8696 }
8697
8698 /*
8699  * Just a dummy test to be run under a debugger. There's no real way
8700  * to inspect the tevent_select specific function from outside of
8701  * tevent_select.c.
8702  */
8703
8704 static bool run_local_tevent_select(int dummy)
8705 {
8706         struct tevent_context *ev;
8707         struct tevent_fd *fd1, *fd2;
8708         bool result = false;
8709
8710         ev = tevent_context_init_byname(NULL, "select");
8711         if (ev == NULL) {
8712                 d_fprintf(stderr, "tevent_context_init_byname failed\n");
8713                 goto fail;
8714         }
8715
8716         fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
8717         if (fd1 == NULL) {
8718                 d_fprintf(stderr, "tevent_add_fd failed\n");
8719                 goto fail;
8720         }
8721         fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
8722         if (fd2 == NULL) {
8723                 d_fprintf(stderr, "tevent_add_fd failed\n");
8724                 goto fail;
8725         }
8726         TALLOC_FREE(fd2);
8727
8728         fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
8729         if (fd2 == NULL) {
8730                 d_fprintf(stderr, "tevent_add_fd failed\n");
8731                 goto fail;
8732         }
8733
8734         result = true;
8735 fail:
8736         TALLOC_FREE(ev);
8737         return result;
8738 }
8739
8740 static bool run_local_hex_encode_buf(int dummy)
8741 {
8742         char buf[17];
8743         uint8_t src[8];
8744         int i;
8745
8746         for (i=0; i<sizeof(src); i++) {
8747                 src[i] = i;
8748         }
8749         hex_encode_buf(buf, src, sizeof(src));
8750         if (strcmp(buf, "0001020304050607") != 0) {
8751                 return false;
8752         }
8753         hex_encode_buf(buf, NULL, 0);
8754         if (buf[0] != '\0') {
8755                 return false;
8756         }
8757         return true;
8758 }
8759
8760 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
8761         "0.0.0.0",
8762         "::0",
8763         "1.2.3.1",
8764         "0.0.0.0",
8765         "0.0.0.0",
8766         "1.2.3.2",
8767         "1.2.3.3",
8768         "1.2.3.4",
8769         "1.2.3.5",
8770         "::0",
8771         "1.2.3.6",
8772         "1.2.3.7",
8773         "::0",
8774         "::0",
8775         "::0",
8776         "1.2.3.8",
8777         "1.2.3.9",
8778         "1.2.3.10",
8779         "1.2.3.11",
8780         "1.2.3.12",
8781         "1.2.3.13",
8782         "1001:1111:1111:1000:0:1111:1111:1111",
8783         "1.2.3.1",
8784         "1.2.3.2",
8785         "1.2.3.3",
8786         "1.2.3.12",
8787         "::0",
8788         "::0"
8789 };
8790
8791 static const char *remove_duplicate_addrs2_test_strings_result[] = {
8792         "1.2.3.1",
8793         "1.2.3.2",
8794         "1.2.3.3",
8795         "1.2.3.4",
8796         "1.2.3.5",
8797         "1.2.3.6",
8798         "1.2.3.7",
8799         "1.2.3.8",
8800         "1.2.3.9",
8801         "1.2.3.10",
8802         "1.2.3.11",
8803         "1.2.3.12",
8804         "1.2.3.13",
8805         "1001:1111:1111:1000:0:1111:1111:1111"
8806 };
8807
8808 static bool run_local_remove_duplicate_addrs2(int dummy)
8809 {
8810         struct ip_service test_vector[28];
8811         int count, i;
8812
8813         /* Construct the sockaddr_storage test vector. */
8814         for (i = 0; i < 28; i++) {
8815                 struct addrinfo hints;
8816                 struct addrinfo *res = NULL;
8817                 int ret;
8818
8819                 memset(&hints, '\0', sizeof(hints));
8820                 hints.ai_flags = AI_NUMERICHOST;
8821                 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
8822                                 NULL,
8823                                 &hints,
8824                                 &res);
8825                 if (ret) {
8826                         fprintf(stderr, "getaddrinfo failed on [%s]\n",
8827                                 remove_duplicate_addrs2_test_strings_vector[i]);
8828                         return false;
8829                 }
8830                 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
8831                 memcpy(&test_vector[i].ss,
8832                         res->ai_addr,
8833                         res->ai_addrlen);
8834                 freeaddrinfo(res);
8835         }
8836
8837         count = remove_duplicate_addrs2(test_vector, i);
8838
8839         if (count != 14) {
8840                 fprintf(stderr, "count wrong (%d) should be 14\n",
8841                         count);
8842                 return false;
8843         }
8844
8845         for (i = 0; i < count; i++) {
8846                 char addr[INET6_ADDRSTRLEN];
8847
8848                 print_sockaddr(addr, sizeof(addr), &test_vector[i].ss);
8849
8850                 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
8851                         fprintf(stderr, "mismatch on [%d] [%s] [%s]\n",
8852                                 i,
8853                                 addr,
8854                                 remove_duplicate_addrs2_test_strings_result[i]);
8855                         return false;
8856                 }
8857         }
8858
8859         printf("run_local_remove_duplicate_addrs2: success\n");
8860         return true;
8861 }
8862
8863 static double create_procs(bool (*fn)(int), bool *result)
8864 {
8865         int i, status;
8866         volatile pid_t *child_status;
8867         volatile bool *child_status_out;
8868         int synccount;
8869         int tries = 8;
8870         struct timeval start;
8871
8872         synccount = 0;
8873
8874         child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*torture_nprocs);
8875         if (!child_status) {
8876                 printf("Failed to setup shared memory\n");
8877                 return -1;
8878         }
8879
8880         child_status_out = (volatile bool *)shm_setup(sizeof(bool)*torture_nprocs);
8881         if (!child_status_out) {
8882                 printf("Failed to setup result status shared memory\n");
8883                 return -1;
8884         }
8885
8886         for (i = 0; i < torture_nprocs; i++) {
8887                 child_status[i] = 0;
8888                 child_status_out[i] = True;
8889         }
8890
8891         start = timeval_current();
8892
8893         for (i=0;i<torture_nprocs;i++) {
8894                 procnum = i;
8895                 if (fork() == 0) {
8896                         pid_t mypid = getpid();
8897                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
8898
8899                         slprintf(myname,sizeof(myname),"CLIENT%d", i);
8900
8901                         while (1) {
8902                                 if (torture_open_connection(&current_cli, i)) break;
8903                                 if (tries-- == 0) {
8904                                         printf("pid %d failed to start\n", (int)getpid());
8905                                         _exit(1);
8906                                 }
8907                                 smb_msleep(10); 
8908                         }
8909
8910                         child_status[i] = getpid();
8911
8912                         while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
8913
8914                         child_status_out[i] = fn(i);
8915                         _exit(0);
8916                 }
8917         }
8918
8919         do {
8920                 synccount = 0;
8921                 for (i=0;i<torture_nprocs;i++) {
8922                         if (child_status[i]) synccount++;
8923                 }
8924                 if (synccount == torture_nprocs) break;
8925                 smb_msleep(10);
8926         } while (timeval_elapsed(&start) < 30);
8927
8928         if (synccount != torture_nprocs) {
8929                 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
8930                 *result = False;
8931                 return timeval_elapsed(&start);
8932         }
8933
8934         /* start the client load */
8935         start = timeval_current();
8936
8937         for (i=0;i<torture_nprocs;i++) {
8938                 child_status[i] = 0;
8939         }
8940
8941         printf("%d clients started\n", torture_nprocs);
8942
8943         for (i=0;i<torture_nprocs;i++) {
8944                 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
8945         }
8946
8947         printf("\n");
8948
8949         for (i=0;i<torture_nprocs;i++) {
8950                 if (!child_status_out[i]) {
8951                         *result = False;
8952                 }
8953         }
8954         return timeval_elapsed(&start);
8955 }
8956
8957 #define FLAG_MULTIPROC 1
8958
8959 static struct {
8960         const char *name;
8961         bool (*fn)(int);
8962         unsigned flags;
8963 } torture_ops[] = {
8964         {"FDPASS", run_fdpasstest, 0},
8965         {"LOCK1",  run_locktest1,  0},
8966         {"LOCK2",  run_locktest2,  0},
8967         {"LOCK3",  run_locktest3,  0},
8968         {"LOCK4",  run_locktest4,  0},
8969         {"LOCK5",  run_locktest5,  0},
8970         {"LOCK6",  run_locktest6,  0},
8971         {"LOCK7",  run_locktest7,  0},
8972         {"LOCK8",  run_locktest8,  0},
8973         {"LOCK9",  run_locktest9,  0},
8974         {"UNLINK", run_unlinktest, 0},
8975         {"BROWSE", run_browsetest, 0},
8976         {"ATTR",   run_attrtest,   0},
8977         {"TRANS2", run_trans2test, 0},
8978         {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
8979         {"TORTURE",run_torture,    FLAG_MULTIPROC},
8980         {"RANDOMIPC", run_randomipc, 0},
8981         {"NEGNOWAIT", run_negprot_nowait, 0},
8982         {"NBENCH",  run_nbench, 0},
8983         {"NBENCH2", run_nbench2, 0},
8984         {"OPLOCK1",  run_oplock1, 0},
8985         {"OPLOCK2",  run_oplock2, 0},
8986         {"OPLOCK4",  run_oplock4, 0},
8987         {"DIR",  run_dirtest, 0},
8988         {"DIR1",  run_dirtest1, 0},
8989         {"DIR-CREATETIME",  run_dir_createtime, 0},
8990         {"DENY1",  torture_denytest1, 0},
8991         {"DENY2",  torture_denytest2, 0},
8992         {"TCON",  run_tcon_test, 0},
8993         {"TCONDEV",  run_tcon_devtype_test, 0},
8994         {"RW1",  run_readwritetest, 0},
8995         {"RW2",  run_readwritemulti, FLAG_MULTIPROC},
8996         {"RW3",  run_readwritelarge, 0},
8997         {"RW-SIGNING",  run_readwritelarge_signtest, 0},
8998         {"OPEN", run_opentest, 0},
8999         {"POSIX", run_simple_posix_open_test, 0},
9000         {"POSIX-APPEND", run_posix_append, 0},
9001         {"CASE-INSENSITIVE-CREATE", run_case_insensitive_create, 0},
9002         {"ASYNC-ECHO", run_async_echo, 0},
9003         { "UID-REGRESSION-TEST", run_uid_regression_test, 0},
9004         { "SHORTNAME-TEST", run_shortname_test, 0},
9005         { "ADDRCHANGE", run_addrchange, 0},
9006 #if 1
9007         {"OPENATTR", run_openattrtest, 0},
9008 #endif
9009         {"XCOPY", run_xcopy, 0},
9010         {"RENAME", run_rename, 0},
9011         {"DELETE", run_deletetest, 0},
9012         {"DELETE-LN", run_deletetest_ln, 0},
9013         {"PROPERTIES", run_properties, 0},
9014         {"MANGLE", torture_mangle, 0},
9015         {"MANGLE1", run_mangle1, 0},
9016         {"W2K", run_w2ktest, 0},
9017         {"TRANS2SCAN", torture_trans2_scan, 0},
9018         {"NTTRANSSCAN", torture_nttrans_scan, 0},
9019         {"UTABLE", torture_utable, 0},
9020         {"CASETABLE", torture_casetable, 0},
9021         {"ERRMAPEXTRACT", run_error_map_extract, 0},
9022         {"PIPE_NUMBER", run_pipe_number, 0},
9023         {"TCON2",  run_tcon2_test, 0},
9024         {"IOCTL",  torture_ioctl_test, 0},
9025         {"CHKPATH",  torture_chkpath_test, 0},
9026         {"FDSESS", run_fdsesstest, 0},
9027         { "EATEST", run_eatest, 0},
9028         { "SESSSETUP_BENCH", run_sesssetup_bench, 0},
9029         { "CHAIN1", run_chain1, 0},
9030         { "CHAIN2", run_chain2, 0},
9031         { "CHAIN3", run_chain3, 0},
9032         { "WINDOWS-WRITE", run_windows_write, 0},
9033         { "NTTRANS-CREATE", run_nttrans_create, 0},
9034         { "NTTRANS-FSCTL", run_nttrans_fsctl, 0},
9035         { "CLI_ECHO", run_cli_echo, 0},
9036         { "GETADDRINFO", run_getaddrinfo_send, 0},
9037         { "TLDAP", run_tldap },
9038         { "STREAMERROR", run_streamerror },
9039         { "NOTIFY-BENCH", run_notify_bench },
9040         { "NOTIFY-BENCH2", run_notify_bench2 },
9041         { "NOTIFY-BENCH3", run_notify_bench3 },
9042         { "BAD-NBT-SESSION", run_bad_nbt_session },
9043         { "SMB-ANY-CONNECT", run_smb_any_connect },
9044         { "NOTIFY-ONLINE", run_notify_online },
9045         { "SMB2-BASIC", run_smb2_basic },
9046         { "SMB2-NEGPROT", run_smb2_negprot },
9047         { "SMB2-SESSION-RECONNECT", run_smb2_session_reconnect },
9048         { "SMB2-TCON-DEPENDENCE", run_smb2_tcon_dependence },
9049         { "SMB2-MULTI-CHANNEL", run_smb2_multi_channel },
9050         { "SMB2-SESSION-REAUTH", run_smb2_session_reauth },
9051         { "CLEANUP1", run_cleanup1 },
9052         { "CLEANUP2", run_cleanup2 },
9053         { "CLEANUP3", run_cleanup3 },
9054         { "LOCAL-SUBSTITUTE", run_local_substitute, 0},
9055         { "LOCAL-GENCACHE", run_local_gencache, 0},
9056         { "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0},
9057         { "LOCAL-CTDB-CONN", run_ctdb_conn, 0},
9058         { "LOCAL-MSG", run_msg_test, 0},
9059         { "LOCAL-DBWRAP-WATCH1", run_dbwrap_watch1, 0 },
9060         { "LOCAL-BASE64", run_local_base64, 0},
9061         { "LOCAL-RBTREE", run_local_rbtree, 0},
9062         { "LOCAL-MEMCACHE", run_local_memcache, 0},
9063         { "LOCAL-STREAM-NAME", run_local_stream_name, 0},
9064         { "LOCAL-WBCLIENT", run_local_wbclient, 0},
9065         { "LOCAL-string_to_sid", run_local_string_to_sid, 0},
9066         { "LOCAL-binary_to_sid", run_local_binary_to_sid, 0},
9067         { "LOCAL-DBTRANS", run_local_dbtrans, 0},
9068         { "LOCAL-TEVENT-SELECT", run_local_tevent_select, 0},
9069         { "LOCAL-CONVERT-STRING", run_local_convert_string, 0},
9070         { "LOCAL-CONV-AUTH-INFO", run_local_conv_auth_info, 0},
9071         { "LOCAL-sprintf_append", run_local_sprintf_append, 0},
9072         { "LOCAL-hex_encode_buf", run_local_hex_encode_buf, 0},
9073         { "LOCAL-IDMAP-TDB-COMMON", run_idmap_tdb_common_test, 0},
9074         { "LOCAL-remove_duplicate_addrs2", run_local_remove_duplicate_addrs2, 0},
9075         {NULL, NULL, 0}};
9076
9077
9078
9079 /****************************************************************************
9080 run a specified test or "ALL"
9081 ****************************************************************************/
9082 static bool run_test(const char *name)
9083 {
9084         bool ret = True;
9085         bool result = True;
9086         bool found = False;
9087         int i;
9088         double t;
9089         if (strequal(name,"ALL")) {
9090                 for (i=0;torture_ops[i].name;i++) {
9091                         run_test(torture_ops[i].name);
9092                 }
9093                 found = True;
9094         }
9095
9096         for (i=0;torture_ops[i].name;i++) {
9097                 fstr_sprintf(randomfname, "\\XX%x", 
9098                          (unsigned)random());
9099
9100                 if (strequal(name, torture_ops[i].name)) {
9101                         found = True;
9102                         printf("Running %s\n", name);
9103                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
9104                                 t = create_procs(torture_ops[i].fn, &result);
9105                                 if (!result) { 
9106                                         ret = False;
9107                                         printf("TEST %s FAILED!\n", name);
9108                                 }
9109                         } else {
9110                                 struct timeval start;
9111                                 start = timeval_current();
9112                                 if (!torture_ops[i].fn(0)) {
9113                                         ret = False;
9114                                         printf("TEST %s FAILED!\n", name);
9115                                 }
9116                                 t = timeval_elapsed(&start);
9117                         }
9118                         printf("%s took %g secs\n\n", name, t);
9119                 }
9120         }
9121
9122         if (!found) {
9123                 printf("Did not find a test named %s\n", name);
9124                 ret = False;
9125         }
9126
9127         return ret;
9128 }
9129
9130
9131 static void usage(void)
9132 {
9133         int i;
9134
9135         printf("WARNING samba4 test suite is much more complete nowadays.\n");
9136         printf("Please use samba4 torture.\n\n");
9137
9138         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
9139
9140         printf("\t-d debuglevel\n");
9141         printf("\t-U user%%pass\n");
9142         printf("\t-k               use kerberos\n");
9143         printf("\t-N numprocs\n");
9144         printf("\t-n my_netbios_name\n");
9145         printf("\t-W workgroup\n");
9146         printf("\t-o num_operations\n");
9147         printf("\t-O socket_options\n");
9148         printf("\t-m maximum protocol\n");
9149         printf("\t-L use oplocks\n");
9150         printf("\t-c CLIENT.TXT   specify client load file for NBENCH\n");
9151         printf("\t-A showall\n");
9152         printf("\t-p port\n");
9153         printf("\t-s seed\n");
9154         printf("\t-b unclist_filename   specify multiple shares for multiple connections\n");
9155         printf("\t-f filename   filename to test\n");
9156         printf("\n\n");
9157
9158         printf("tests are:");
9159         for (i=0;torture_ops[i].name;i++) {
9160                 printf(" %s", torture_ops[i].name);
9161         }
9162         printf("\n");
9163
9164         printf("default test is ALL\n");
9165
9166         exit(1);
9167 }
9168
9169 /****************************************************************************
9170   main program
9171 ****************************************************************************/
9172  int main(int argc,char *argv[])
9173 {
9174         int opt, i;
9175         char *p;
9176         int gotuser = 0;
9177         int gotpass = 0;
9178         bool correct = True;
9179         TALLOC_CTX *frame = talloc_stackframe();
9180         int seed = time(NULL);
9181
9182 #ifdef HAVE_SETBUFFER
9183         setbuffer(stdout, NULL, 0);
9184 #endif
9185
9186         setup_logging("smbtorture", DEBUG_STDOUT);
9187
9188         load_case_tables();
9189
9190         if (is_default_dyn_CONFIGFILE()) {
9191                 if(getenv("SMB_CONF_PATH")) {
9192                         set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
9193                 }
9194         }
9195         lp_load_global(get_dyn_CONFIGFILE());
9196         load_interfaces();
9197
9198         if (argc < 2) {
9199                 usage();
9200         }
9201
9202         for(p = argv[1]; *p; p++)
9203           if(*p == '\\')
9204             *p = '/';
9205
9206         if (strncmp(argv[1], "//", 2)) {
9207                 usage();
9208         }
9209
9210         fstrcpy(host, &argv[1][2]);
9211         p = strchr_m(&host[2],'/');
9212         if (!p) {
9213                 usage();
9214         }
9215         *p = 0;
9216         fstrcpy(share, p+1);
9217
9218         fstrcpy(myname, get_myname(talloc_tos()));
9219         if (!*myname) {
9220                 fprintf(stderr, "Failed to get my hostname.\n");
9221                 return 1;
9222         }
9223
9224         if (*username == 0 && getenv("LOGNAME")) {
9225           fstrcpy(username,getenv("LOGNAME"));
9226         }
9227
9228         argc--;
9229         argv++;
9230
9231         fstrcpy(workgroup, lp_workgroup());
9232
9233         while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
9234                != EOF) {
9235                 switch (opt) {
9236                 case 'p':
9237                         port_to_use = atoi(optarg);
9238                         break;
9239                 case 's':
9240                         seed = atoi(optarg);
9241                         break;
9242                 case 'W':
9243                         fstrcpy(workgroup,optarg);
9244                         break;
9245                 case 'm':
9246                         max_protocol = interpret_protocol(optarg, max_protocol);
9247                         break;
9248                 case 'N':
9249                         torture_nprocs = atoi(optarg);
9250                         break;
9251                 case 'o':
9252                         torture_numops = atoi(optarg);
9253                         break;
9254                 case 'd':
9255                         lp_set_cmdline("log level", optarg);
9256                         break;
9257                 case 'O':
9258                         sockops = optarg;
9259                         break;
9260                 case 'L':
9261                         use_oplocks = True;
9262                         break;
9263                 case 'l':
9264                         local_path = optarg;
9265                         break;
9266                 case 'A':
9267                         torture_showall = True;
9268                         break;
9269                 case 'n':
9270                         fstrcpy(myname, optarg);
9271                         break;
9272                 case 'c':
9273                         client_txt = optarg;
9274                         break;
9275                 case 'e':
9276                         do_encrypt = true;
9277                         break;
9278                 case 'k':
9279 #ifdef HAVE_KRB5
9280                         use_kerberos = True;
9281 #else
9282                         d_printf("No kerberos support compiled in\n");
9283                         exit(1);
9284 #endif
9285                         break;
9286                 case 'U':
9287                         gotuser = 1;
9288                         fstrcpy(username,optarg);
9289                         p = strchr_m(username,'%');
9290                         if (p) {
9291                                 *p = 0;
9292                                 fstrcpy(password, p+1);
9293                                 gotpass = 1;
9294                         }
9295                         break;
9296                 case 'b':
9297                         fstrcpy(multishare_conn_fname, optarg);
9298                         use_multishare_conn = True;
9299                         break;
9300                 case 'B':
9301                         torture_blocksize = atoi(optarg);
9302                         break;
9303                 case 'f':
9304                         test_filename = SMB_STRDUP(optarg);
9305                         break;
9306                 default:
9307                         printf("Unknown option %c (%d)\n", (char)opt, opt);
9308                         usage();
9309                 }
9310         }
9311
9312         d_printf("using seed %d\n", seed);
9313
9314         srandom(seed);
9315
9316         if(use_kerberos && !gotuser) gotpass = True;
9317
9318         while (!gotpass) {
9319                 p = getpass("Password:");
9320                 if (p) {
9321                         fstrcpy(password, p);
9322                         gotpass = 1;
9323                 }
9324         }
9325
9326         printf("host=%s share=%s user=%s myname=%s\n", 
9327                host, share, username, myname);
9328
9329         if (argc == optind) {
9330                 correct = run_test("ALL");
9331         } else {
9332                 for (i=optind;i<argc;i++) {
9333                         if (!run_test(argv[i])) {
9334                                 correct = False;
9335                         }
9336                 }
9337         }
9338
9339         TALLOC_FREE(frame);
9340
9341         if (correct) {
9342                 return(0);
9343         } else {
9344                 return(1);
9345         }
9346 }