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