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