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