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