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