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