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