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