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