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