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