s3-torture: introduce check_both_error()
[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         if (NT_STATUS_IS_OK(cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN))) {
2791                 printf("error: server allowed unlink on an open file\n");
2792                 correct = False;
2793         } else {
2794                 correct = check_error(__LINE__, cli, ERRDOS, ERRbadshare, 
2795                                       NT_STATUS_SHARING_VIOLATION);
2796         }
2797
2798         cli_close(cli, fnum);
2799         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2800
2801         if (!torture_close_connection(cli)) {
2802                 correct = False;
2803         }
2804
2805         printf("unlink test finished\n");
2806
2807         return correct;
2808 }
2809
2810
2811 /*
2812 test how many open files this server supports on the one socket
2813 */
2814 static bool run_maxfidtest(int dummy)
2815 {
2816         struct cli_state *cli;
2817         fstring fname;
2818         uint16_t fnums[0x11000];
2819         int i;
2820         int retries=4;
2821         bool correct = True;
2822         NTSTATUS status;
2823
2824         cli = current_cli;
2825
2826         if (retries <= 0) {
2827                 printf("failed to connect\n");
2828                 return False;
2829         }
2830
2831         cli_sockopt(cli, sockops);
2832
2833         for (i=0; i<0x11000; i++) {
2834                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2835                 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
2836                                   &fnums[i]);
2837                 if (!NT_STATUS_IS_OK(status)) {
2838                         printf("open of %s failed (%s)\n", 
2839                                fname, nt_errstr(status));
2840                         printf("maximum fnum is %d\n", i);
2841                         break;
2842                 }
2843                 printf("%6d\r", i);
2844         }
2845         printf("%6d\n", i);
2846         i--;
2847
2848         printf("cleaning up\n");
2849         for (;i>=0;i--) {
2850                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2851                 cli_close(cli, fnums[i]);
2852
2853                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2854                 if (!NT_STATUS_IS_OK(status)) {
2855                         printf("unlink of %s failed (%s)\n", 
2856                                fname, nt_errstr(status));
2857                         correct = False;
2858                 }
2859                 printf("%6d\r", i);
2860         }
2861         printf("%6d\n", 0);
2862
2863         printf("maxfid test finished\n");
2864         if (!torture_close_connection(cli)) {
2865                 correct = False;
2866         }
2867         return correct;
2868 }
2869
2870 /* generate a random buffer */
2871 static void rand_buf(char *buf, int len)
2872 {
2873         while (len--) {
2874                 *buf = (char)sys_random();
2875                 buf++;
2876         }
2877 }
2878
2879 /* send smb negprot commands, not reading the response */
2880 static bool run_negprot_nowait(int dummy)
2881 {
2882         struct tevent_context *ev;
2883         int i;
2884         struct cli_state *cli;
2885         bool correct = True;
2886
2887         printf("starting negprot nowait test\n");
2888
2889         ev = tevent_context_init(talloc_tos());
2890         if (ev == NULL) {
2891                 return false;
2892         }
2893
2894         if (!(cli = open_nbt_connection())) {
2895                 TALLOC_FREE(ev);
2896                 return False;
2897         }
2898
2899         for (i=0;i<50000;i++) {
2900                 struct tevent_req *req;
2901
2902                 req = cli_negprot_send(ev, ev, cli);
2903                 if (req == NULL) {
2904                         TALLOC_FREE(ev);
2905                         return false;
2906                 }
2907                 if (!tevent_req_poll(req, ev)) {
2908                         d_fprintf(stderr, "tevent_req_poll failed: %s\n",
2909                                   strerror(errno));
2910                         TALLOC_FREE(ev);
2911                         return false;
2912                 }
2913                 TALLOC_FREE(req);
2914         }
2915
2916         if (torture_close_connection(cli)) {
2917                 correct = False;
2918         }
2919
2920         printf("finished negprot nowait test\n");
2921
2922         return correct;
2923 }
2924
2925 /* send smb negprot commands, not reading the response */
2926 static bool run_bad_nbt_session(int dummy)
2927 {
2928         struct nmb_name called, calling;
2929         struct sockaddr_storage ss;
2930         NTSTATUS status;
2931         int fd;
2932         bool ret;
2933
2934         printf("starting bad nbt session test\n");
2935
2936         make_nmb_name(&calling, myname, 0x0);
2937         make_nmb_name(&called , host, 0x20);
2938
2939         if (!resolve_name(host, &ss, 0x20, true)) {
2940                 d_fprintf(stderr, "Could not resolve name %s\n", host);
2941                 return false;
2942         }
2943
2944         status = open_socket_out(&ss, 139, 10000, &fd);
2945         if (!NT_STATUS_IS_OK(status)) {
2946                 d_fprintf(stderr, "open_socket_out failed: %s\n",
2947                           nt_errstr(status));
2948                 return false;
2949         }
2950
2951         ret = cli_bad_session_request(fd, &calling, &called);
2952         close(fd);
2953         if (!ret) {
2954                 d_fprintf(stderr, "open_socket_out failed: %s\n",
2955                           nt_errstr(status));
2956                 return false;
2957         }
2958
2959         printf("finished bad nbt session test\n");
2960         return true;
2961 }
2962
2963 /* send random IPC commands */
2964 static bool run_randomipc(int dummy)
2965 {
2966         char *rparam = NULL;
2967         char *rdata = NULL;
2968         unsigned int rdrcnt,rprcnt;
2969         char param[1024];
2970         int api, param_len, i;
2971         struct cli_state *cli;
2972         bool correct = True;
2973         int count = 50000;
2974
2975         printf("starting random ipc test\n");
2976
2977         if (!torture_open_connection(&cli, 0)) {
2978                 return False;
2979         }
2980
2981         for (i=0;i<count;i++) {
2982                 api = sys_random() % 500;
2983                 param_len = (sys_random() % 64);
2984
2985                 rand_buf(param, param_len);
2986
2987                 SSVAL(param,0,api); 
2988
2989                 cli_api(cli, 
2990                         param, param_len, 8,  
2991                         NULL, 0, BUFFER_SIZE, 
2992                         &rparam, &rprcnt,     
2993                         &rdata, &rdrcnt);
2994                 if (i % 100 == 0) {
2995                         printf("%d/%d\r", i,count);
2996                 }
2997         }
2998         printf("%d/%d\n", i, count);
2999
3000         if (!torture_close_connection(cli)) {
3001                 correct = False;
3002         }
3003
3004         printf("finished random ipc test\n");
3005
3006         return correct;
3007 }
3008
3009
3010
3011 static void browse_callback(const char *sname, uint32 stype, 
3012                             const char *comment, void *state)
3013 {
3014         printf("\t%20.20s %08x %s\n", sname, stype, comment);
3015 }
3016
3017
3018
3019 /*
3020   This test checks the browse list code
3021
3022 */
3023 static bool run_browsetest(int dummy)
3024 {
3025         static struct cli_state *cli;
3026         bool correct = True;
3027
3028         printf("starting browse test\n");
3029
3030         if (!torture_open_connection(&cli, 0)) {
3031                 return False;
3032         }
3033
3034         printf("domain list:\n");
3035         cli_NetServerEnum(cli, cli->server_domain, 
3036                           SV_TYPE_DOMAIN_ENUM,
3037                           browse_callback, NULL);
3038
3039         printf("machine list:\n");
3040         cli_NetServerEnum(cli, cli->server_domain, 
3041                           SV_TYPE_ALL,
3042                           browse_callback, NULL);
3043
3044         if (!torture_close_connection(cli)) {
3045                 correct = False;
3046         }
3047
3048         printf("browse test finished\n");
3049
3050         return correct;
3051
3052 }
3053
3054
3055 /*
3056   This checks how the getatr calls works
3057 */
3058 static bool run_attrtest(int dummy)
3059 {
3060         struct cli_state *cli;
3061         uint16_t fnum;
3062         time_t t, t2;
3063         const char *fname = "\\attrib123456789.tst";
3064         bool correct = True;
3065         NTSTATUS status;
3066
3067         printf("starting attrib test\n");
3068
3069         if (!torture_open_connection(&cli, 0)) {
3070                 return False;
3071         }
3072
3073         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3074         cli_open(cli, fname, 
3075                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3076         cli_close(cli, fnum);
3077
3078         status = cli_getatr(cli, fname, NULL, NULL, &t);
3079         if (!NT_STATUS_IS_OK(status)) {
3080                 printf("getatr failed (%s)\n", nt_errstr(status));
3081                 correct = False;
3082         }
3083
3084         if (abs(t - time(NULL)) > 60*60*24*10) {
3085                 printf("ERROR: SMBgetatr bug. time is %s",
3086                        ctime(&t));
3087                 t = time(NULL);
3088                 correct = True;
3089         }
3090
3091         t2 = t-60*60*24; /* 1 day ago */
3092
3093         status = cli_setatr(cli, fname, 0, t2);
3094         if (!NT_STATUS_IS_OK(status)) {
3095                 printf("setatr failed (%s)\n", nt_errstr(status));
3096                 correct = True;
3097         }
3098
3099         status = cli_getatr(cli, fname, NULL, NULL, &t);
3100         if (!NT_STATUS_IS_OK(status)) {
3101                 printf("getatr failed (%s)\n", nt_errstr(status));
3102                 correct = True;
3103         }
3104
3105         if (t != t2) {
3106                 printf("ERROR: getatr/setatr bug. times are\n%s",
3107                        ctime(&t));
3108                 printf("%s", ctime(&t2));
3109                 correct = True;
3110         }
3111
3112         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3113
3114         if (!torture_close_connection(cli)) {
3115                 correct = False;
3116         }
3117
3118         printf("attrib test finished\n");
3119
3120         return correct;
3121 }
3122
3123
3124 /*
3125   This checks a couple of trans2 calls
3126 */
3127 static bool run_trans2test(int dummy)
3128 {
3129         struct cli_state *cli;
3130         uint16_t fnum;
3131         SMB_OFF_T size;
3132         time_t c_time, a_time, m_time;
3133         struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
3134         const char *fname = "\\trans2.tst";
3135         const char *dname = "\\trans2";
3136         const char *fname2 = "\\trans2\\trans2.tst";
3137         char *pname;
3138         bool correct = True;
3139         NTSTATUS status;
3140         uint32_t fs_attr;
3141
3142         printf("starting trans2 test\n");
3143
3144         if (!torture_open_connection(&cli, 0)) {
3145                 return False;
3146         }
3147
3148         status = cli_get_fs_attr_info(cli, &fs_attr);
3149         if (!NT_STATUS_IS_OK(status)) {
3150                 printf("ERROR: cli_get_fs_attr_info returned %s\n",
3151                        nt_errstr(status));
3152                 correct = false;
3153         }
3154
3155         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3156         cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3157         status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
3158                                      &a_time_ts, &w_time_ts, &m_time_ts, NULL);
3159         if (!NT_STATUS_IS_OK(status)) {
3160                 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
3161                 correct = False;
3162         }
3163
3164         status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
3165         if (!NT_STATUS_IS_OK(status)) {
3166                 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
3167                 correct = False;
3168         }
3169
3170         if (strcmp(pname, fname)) {
3171                 printf("qfilename gave different name? [%s] [%s]\n",
3172                        fname, pname);
3173                 correct = False;
3174         }
3175
3176         cli_close(cli, fnum);
3177
3178         sleep(2);
3179
3180         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3181         status = cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
3182                           &fnum);
3183         if (!NT_STATUS_IS_OK(status)) {
3184                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3185                 return False;
3186         }
3187         cli_close(cli, fnum);
3188
3189         status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
3190                                 NULL);
3191         if (!NT_STATUS_IS_OK(status)) {
3192                 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
3193                 correct = False;
3194         } else {
3195                 if (c_time != m_time) {
3196                         printf("create time=%s", ctime(&c_time));
3197                         printf("modify time=%s", ctime(&m_time));
3198                         printf("This system appears to have sticky create times\n");
3199                 }
3200                 if (a_time % (60*60) == 0) {
3201                         printf("access time=%s", ctime(&a_time));
3202                         printf("This system appears to set a midnight access time\n");
3203                         correct = False;
3204                 }
3205
3206                 if (abs(m_time - time(NULL)) > 60*60*24*7) {
3207                         printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
3208                         correct = False;
3209                 }
3210         }
3211
3212
3213         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3214         cli_open(cli, fname, 
3215                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3216         cli_close(cli, fnum);
3217         status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
3218                                 &m_time_ts, &size, NULL, NULL);
3219         if (!NT_STATUS_IS_OK(status)) {
3220                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3221                 correct = False;
3222         } else {
3223                 if (w_time_ts.tv_sec < 60*60*24*2) {
3224                         printf("write time=%s", ctime(&w_time_ts.tv_sec));
3225                         printf("This system appears to set a initial 0 write time\n");
3226                         correct = False;
3227                 }
3228         }
3229
3230         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3231
3232
3233         /* check if the server updates the directory modification time
3234            when creating a new file */
3235         status = cli_mkdir(cli, dname);
3236         if (!NT_STATUS_IS_OK(status)) {
3237                 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
3238                 correct = False;
3239         }
3240         sleep(3);
3241         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3242                                 &w_time_ts, &m_time_ts, &size, NULL, NULL);
3243         if (!NT_STATUS_IS_OK(status)) {
3244                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3245                 correct = False;
3246         }
3247
3248         cli_open(cli, fname2, 
3249                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3250         cli_writeall(cli, fnum,  0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
3251         cli_close(cli, fnum);
3252         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3253                                 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
3254         if (!NT_STATUS_IS_OK(status)) {
3255                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3256                 correct = False;
3257         } else {
3258                 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
3259                     == 0) {
3260                         printf("This system does not update directory modification times\n");
3261                         correct = False;
3262                 }
3263         }
3264         cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3265         cli_rmdir(cli, dname);
3266
3267         if (!torture_close_connection(cli)) {
3268                 correct = False;
3269         }
3270
3271         printf("trans2 test finished\n");
3272
3273         return correct;
3274 }
3275
3276 /*
3277   This checks new W2K calls.
3278 */
3279
3280 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
3281 {
3282         uint8_t *buf = NULL;
3283         uint32 len;
3284         NTSTATUS status;
3285
3286         status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
3287                                pcli->max_xmit, NULL, &buf, &len);
3288         if (!NT_STATUS_IS_OK(status)) {
3289                 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
3290                        nt_errstr(status));
3291         } else {
3292                 printf("qfileinfo: level %d, len = %u\n", level, len);
3293                 dump_data(0, (uint8 *)buf, len);
3294                 printf("\n");
3295         }
3296         TALLOC_FREE(buf);
3297         return status;
3298 }
3299
3300 static bool run_w2ktest(int dummy)
3301 {
3302         struct cli_state *cli;
3303         uint16_t fnum;
3304         const char *fname = "\\w2ktest\\w2k.tst";
3305         int level;
3306         bool correct = True;
3307
3308         printf("starting w2k test\n");
3309
3310         if (!torture_open_connection(&cli, 0)) {
3311                 return False;
3312         }
3313
3314         cli_open(cli, fname, 
3315                         O_RDWR | O_CREAT , DENY_NONE, &fnum);
3316
3317         for (level = 1004; level < 1040; level++) {
3318                 new_trans(cli, fnum, level);
3319         }
3320
3321         cli_close(cli, fnum);
3322
3323         if (!torture_close_connection(cli)) {
3324                 correct = False;
3325         }
3326
3327         printf("w2k test finished\n");
3328
3329         return correct;
3330 }
3331
3332
3333 /*
3334   this is a harness for some oplock tests
3335  */
3336 static bool run_oplock1(int dummy)
3337 {
3338         struct cli_state *cli1;
3339         const char *fname = "\\lockt1.lck";
3340         uint16_t fnum1;
3341         bool correct = True;
3342         NTSTATUS status;
3343
3344         printf("starting oplock test 1\n");
3345
3346         if (!torture_open_connection(&cli1, 0)) {
3347                 return False;
3348         }
3349
3350         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3351
3352         cli_sockopt(cli1, sockops);
3353
3354         cli1->use_oplocks = True;
3355
3356         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3357                           &fnum1);
3358         if (!NT_STATUS_IS_OK(status)) {
3359                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3360                 return False;
3361         }
3362
3363         cli1->use_oplocks = False;
3364
3365         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3366         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3367
3368         status = cli_close(cli1, fnum1);
3369         if (!NT_STATUS_IS_OK(status)) {
3370                 printf("close2 failed (%s)\n", nt_errstr(status));
3371                 return False;
3372         }
3373
3374         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3375         if (!NT_STATUS_IS_OK(status)) {
3376                 printf("unlink failed (%s)\n", nt_errstr(status));
3377                 return False;
3378         }
3379
3380         if (!torture_close_connection(cli1)) {
3381                 correct = False;
3382         }
3383
3384         printf("finished oplock test 1\n");
3385
3386         return correct;
3387 }
3388
3389 static bool run_oplock2(int dummy)
3390 {
3391         struct cli_state *cli1, *cli2;
3392         const char *fname = "\\lockt2.lck";
3393         uint16_t fnum1, fnum2;
3394         int saved_use_oplocks = use_oplocks;
3395         char buf[4];
3396         bool correct = True;
3397         volatile bool *shared_correct;
3398         NTSTATUS status;
3399
3400         shared_correct = (volatile bool *)shm_setup(sizeof(bool));
3401         *shared_correct = True;
3402
3403         use_level_II_oplocks = True;
3404         use_oplocks = True;
3405
3406         printf("starting oplock test 2\n");
3407
3408         if (!torture_open_connection(&cli1, 0)) {
3409                 use_level_II_oplocks = False;
3410                 use_oplocks = saved_use_oplocks;
3411                 return False;
3412         }
3413
3414         cli1->use_oplocks = True;
3415         cli1->use_level_II_oplocks = True;
3416
3417         if (!torture_open_connection(&cli2, 1)) {
3418                 use_level_II_oplocks = False;
3419                 use_oplocks = saved_use_oplocks;
3420                 return False;
3421         }
3422
3423         cli2->use_oplocks = True;
3424         cli2->use_level_II_oplocks = True;
3425
3426         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3427
3428         cli_sockopt(cli1, sockops);
3429         cli_sockopt(cli2, sockops);
3430
3431         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3432                           &fnum1);
3433         if (!NT_STATUS_IS_OK(status)) {
3434                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3435                 return False;
3436         }
3437
3438         /* Don't need the globals any more. */
3439         use_level_II_oplocks = False;
3440         use_oplocks = saved_use_oplocks;
3441
3442         if (fork() == 0) {
3443                 /* Child code */
3444                 status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
3445                 if (!NT_STATUS_IS_OK(status)) {
3446                         printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
3447                         *shared_correct = False;
3448                         exit(0);
3449                 }
3450
3451                 sleep(2);
3452
3453                 status = cli_close(cli2, fnum2);
3454                 if (!NT_STATUS_IS_OK(status)) {
3455                         printf("close2 failed (%s)\n", nt_errstr(status));
3456                         *shared_correct = False;
3457                 }
3458
3459                 exit(0);
3460         }
3461
3462         sleep(2);
3463
3464         /* Ensure cli1 processes the break. Empty file should always return 0
3465          * bytes.  */
3466
3467         if (cli_read(cli1, fnum1, buf, 0, 4) != 0) {
3468                 printf("read on fnum1 failed (%s)\n", cli_errstr(cli1));
3469                 correct = False;
3470         }
3471
3472         /* Should now be at level II. */
3473         /* Test if sending a write locks causes a break to none. */
3474
3475         if (!cli_lock(cli1, fnum1, 0, 4, 0, READ_LOCK)) {
3476                 printf("lock failed (%s)\n", cli_errstr(cli1));
3477                 correct = False;
3478         }
3479
3480         cli_unlock(cli1, fnum1, 0, 4);
3481
3482         sleep(2);
3483
3484         if (!cli_lock(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) {
3485                 printf("lock failed (%s)\n", cli_errstr(cli1));
3486                 correct = False;
3487         }
3488
3489         cli_unlock(cli1, fnum1, 0, 4);
3490
3491         sleep(2);
3492
3493         cli_read(cli1, fnum1, buf, 0, 4);
3494
3495         status = cli_close(cli1, fnum1);
3496         if (!NT_STATUS_IS_OK(status)) {
3497                 printf("close1 failed (%s)\n", nt_errstr(status));
3498                 correct = False;
3499         }
3500
3501         sleep(4);
3502
3503         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3504         if (!NT_STATUS_IS_OK(status)) {
3505                 printf("unlink failed (%s)\n", nt_errstr(status));
3506                 correct = False;
3507         }
3508
3509         if (!torture_close_connection(cli1)) {
3510                 correct = False;
3511         }
3512
3513         if (!*shared_correct) {
3514                 correct = False;
3515         }
3516
3517         printf("finished oplock test 2\n");
3518
3519         return correct;
3520 }
3521
3522 struct oplock4_state {
3523         struct tevent_context *ev;
3524         struct cli_state *cli;
3525         bool *got_break;
3526         uint16_t *fnum2;
3527 };
3528
3529 static void oplock4_got_break(struct tevent_req *req);
3530 static void oplock4_got_open(struct tevent_req *req);
3531
3532 static bool run_oplock4(int dummy)
3533 {
3534         struct tevent_context *ev;
3535         struct cli_state *cli1, *cli2;
3536         struct tevent_req *oplock_req, *open_req;
3537         const char *fname = "\\lockt4.lck";
3538         const char *fname_ln = "\\lockt4_ln.lck";
3539         uint16_t fnum1, fnum2;
3540         int saved_use_oplocks = use_oplocks;
3541         NTSTATUS status;
3542         bool correct = true;
3543
3544         bool got_break;
3545
3546         struct oplock4_state *state;
3547
3548         printf("starting oplock test 4\n");
3549
3550         if (!torture_open_connection(&cli1, 0)) {
3551                 use_level_II_oplocks = false;
3552                 use_oplocks = saved_use_oplocks;
3553                 return false;
3554         }
3555
3556         if (!torture_open_connection(&cli2, 1)) {
3557                 use_level_II_oplocks = false;
3558                 use_oplocks = saved_use_oplocks;
3559                 return false;
3560         }
3561
3562         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3563         cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3564
3565         cli_sockopt(cli1, sockops);
3566         cli_sockopt(cli2, sockops);
3567
3568         /* Create the file. */
3569         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3570                           &fnum1);
3571         if (!NT_STATUS_IS_OK(status)) {
3572                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3573                 return false;
3574         }
3575
3576         status = cli_close(cli1, fnum1);
3577         if (!NT_STATUS_IS_OK(status)) {
3578                 printf("close1 failed (%s)\n", nt_errstr(status));
3579                 return false;
3580         }
3581
3582         /* Now create a hardlink. */
3583         status = cli_nt_hardlink(cli1, fname, fname_ln);
3584         if (!NT_STATUS_IS_OK(status)) {
3585                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
3586                 return false;
3587         }
3588
3589         /* Prove that opening hardlinks cause deny modes to conflict. */
3590         status = cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
3591         if (!NT_STATUS_IS_OK(status)) {
3592                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3593                 return false;
3594         }
3595
3596         status = cli_open(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
3597         if (NT_STATUS_IS_OK(status)) {
3598                 printf("open of %s succeeded - should fail with sharing violation.\n",
3599                         fname_ln);
3600                 return false;
3601         }
3602
3603         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3604                 printf("open of %s should fail with sharing violation. Got %s\n",
3605                         fname_ln, nt_errstr(status));
3606                 return false;
3607         }
3608
3609         status = cli_close(cli1, fnum1);
3610         if (!NT_STATUS_IS_OK(status)) {
3611                 printf("close1 failed (%s)\n", nt_errstr(status));
3612                 return false;
3613         }
3614
3615         cli1->use_oplocks = true;
3616         cli1->use_level_II_oplocks = true;
3617
3618         cli2->use_oplocks = true;
3619         cli2->use_level_II_oplocks = true;
3620
3621         status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3622         if (!NT_STATUS_IS_OK(status)) {
3623                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3624                 return false;
3625         }
3626
3627         ev = tevent_context_init(talloc_tos());
3628         if (ev == NULL) {
3629                 printf("tevent_req_create failed\n");
3630                 return false;
3631         }
3632
3633         state = talloc(ev, struct oplock4_state);
3634         if (state == NULL) {
3635                 printf("talloc failed\n");
3636                 return false;
3637         }
3638         state->ev = ev;
3639         state->cli = cli1;
3640         state->got_break = &got_break;
3641         state->fnum2 = &fnum2;
3642
3643         oplock_req = cli_smb_oplock_break_waiter_send(
3644                 talloc_tos(), ev, cli1);
3645         if (oplock_req == NULL) {
3646                 printf("cli_smb_oplock_break_waiter_send failed\n");
3647                 return false;
3648         }
3649         tevent_req_set_callback(oplock_req, oplock4_got_break, state);
3650
3651         open_req = cli_open_send(
3652                 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
3653         if (oplock_req == NULL) {
3654                 printf("cli_open_send failed\n");
3655                 return false;
3656         }
3657         tevent_req_set_callback(open_req, oplock4_got_open, state);
3658
3659         got_break = false;
3660         fnum2 = 0xffff;
3661
3662         while (!got_break || fnum2 == 0xffff) {
3663                 int ret;
3664                 ret = tevent_loop_once(ev);
3665                 if (ret == -1) {
3666                         printf("tevent_loop_once failed: %s\n",
3667                                strerror(errno));
3668                         return false;
3669                 }
3670         }
3671
3672         status = cli_close(cli2, fnum2);
3673         if (!NT_STATUS_IS_OK(status)) {
3674                 printf("close2 failed (%s)\n", nt_errstr(status));
3675                 correct = false;
3676         }
3677
3678         status = cli_close(cli1, fnum1);
3679         if (!NT_STATUS_IS_OK(status)) {
3680                 printf("close1 failed (%s)\n", nt_errstr(status));
3681                 correct = false;
3682         }
3683
3684         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3685         if (!NT_STATUS_IS_OK(status)) {
3686                 printf("unlink failed (%s)\n", nt_errstr(status));
3687                 correct = false;
3688         }
3689
3690         status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3691         if (!NT_STATUS_IS_OK(status)) {
3692                 printf("unlink failed (%s)\n", nt_errstr(status));
3693                 correct = false;
3694         }
3695
3696         if (!torture_close_connection(cli1)) {
3697                 correct = false;
3698         }
3699
3700         if (!got_break) {
3701                 correct = false;
3702         }
3703
3704         printf("finished oplock test 4\n");
3705
3706         return correct;
3707 }
3708
3709 static void oplock4_got_break(struct tevent_req *req)
3710 {
3711         struct oplock4_state *state = tevent_req_callback_data(
3712                 req, struct oplock4_state);
3713         uint16_t fnum;
3714         uint8_t level;
3715         NTSTATUS status;
3716
3717         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
3718         TALLOC_FREE(req);
3719         if (!NT_STATUS_IS_OK(status)) {
3720                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
3721                        nt_errstr(status));
3722                 return;
3723         }
3724         *state->got_break = true;
3725
3726         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
3727                                   NO_OPLOCK);
3728         if (req == NULL) {
3729                 printf("cli_oplock_ack_send failed\n");
3730                 return;
3731         }
3732 }
3733
3734 static void oplock4_got_open(struct tevent_req *req)
3735 {
3736         struct oplock4_state *state = tevent_req_callback_data(
3737                 req, struct oplock4_state);
3738         NTSTATUS status;
3739
3740         status = cli_open_recv(req, state->fnum2);
3741         if (!NT_STATUS_IS_OK(status)) {
3742                 printf("cli_open_recv returned %s\n", nt_errstr(status));
3743                 *state->fnum2 = 0xffff;
3744         }
3745 }
3746
3747 /*
3748   Test delete on close semantics.
3749  */
3750 static bool run_deletetest(int dummy)
3751 {
3752         struct cli_state *cli1 = NULL;
3753         struct cli_state *cli2 = NULL;
3754         const char *fname = "\\delete.file";
3755         uint16_t fnum1 = (uint16_t)-1;
3756         uint16_t fnum2 = (uint16_t)-1;
3757         bool correct = True;
3758         NTSTATUS status;
3759
3760         printf("starting delete test\n");
3761
3762         if (!torture_open_connection(&cli1, 0)) {
3763                 return False;
3764         }
3765
3766         cli_sockopt(cli1, sockops);
3767
3768         /* Test 1 - this should delete the file on close. */
3769
3770         cli_setatr(cli1, fname, 0, 0);
3771         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3772
3773         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
3774                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
3775                               FILE_DELETE_ON_CLOSE, 0, &fnum1);
3776         if (!NT_STATUS_IS_OK(status)) {
3777                 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
3778                 correct = False;
3779                 goto fail;
3780         }
3781
3782         status = cli_close(cli1, fnum1);
3783         if (!NT_STATUS_IS_OK(status)) {
3784                 printf("[1] close failed (%s)\n", nt_errstr(status));
3785                 correct = False;
3786                 goto fail;
3787         }
3788
3789         if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1))) {
3790                 printf("[1] open of %s succeeded (should fail)\n", fname);
3791                 correct = False;
3792                 goto fail;
3793         }
3794
3795         printf("first delete on close test succeeded.\n");
3796
3797         /* Test 2 - this should delete the file on close. */
3798
3799         cli_setatr(cli1, fname, 0, 0);
3800         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3801
3802         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3803                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
3804                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
3805         if (!NT_STATUS_IS_OK(status)) {
3806                 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
3807                 correct = False;
3808                 goto fail;
3809         }
3810
3811         status = cli_nt_delete_on_close(cli1, fnum1, true);
3812         if (!NT_STATUS_IS_OK(status)) {
3813                 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
3814                 correct = False;
3815                 goto fail;
3816         }
3817
3818         status = cli_close(cli1, fnum1);
3819         if (!NT_STATUS_IS_OK(status)) {
3820                 printf("[2] close failed (%s)\n", nt_errstr(status));
3821                 correct = False;
3822                 goto fail;
3823         }
3824
3825         if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3826                 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
3827                 status = cli_close(cli1, fnum1);
3828                 if (!NT_STATUS_IS_OK(status)) {
3829                         printf("[2] close failed (%s)\n", nt_errstr(status));
3830                         correct = False;
3831                         goto fail;
3832                 }
3833                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3834         } else
3835                 printf("second delete on close test succeeded.\n");
3836
3837         /* Test 3 - ... */
3838         cli_setatr(cli1, fname, 0, 0);
3839         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3840
3841         status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3842                               FILE_ATTRIBUTE_NORMAL,
3843                               FILE_SHARE_READ|FILE_SHARE_WRITE,
3844                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
3845         if (!NT_STATUS_IS_OK(status)) {
3846                 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
3847                 correct = False;
3848                 goto fail;
3849         }
3850
3851         /* This should fail with a sharing violation - open for delete is only compatible
3852            with SHARE_DELETE. */
3853
3854         if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
3855                         FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, 0, &fnum2))) {
3856                 printf("[3] open  - 2 of %s succeeded - should have failed.\n", fname);
3857                 correct = False;
3858                 goto fail;
3859         }
3860
3861         /* This should succeed. */
3862         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3863                              FILE_ATTRIBUTE_NORMAL,
3864                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3865                              FILE_OPEN, 0, 0, &fnum2);
3866         if (!NT_STATUS_IS_OK(status)) {
3867                 printf("[3] open  - 2 of %s failed (%s)\n", fname, nt_errstr(status));
3868                 correct = False;
3869                 goto fail;
3870         }
3871
3872         status = cli_nt_delete_on_close(cli1, fnum1, true);
3873         if (!NT_STATUS_IS_OK(status)) {
3874                 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
3875                 correct = False;
3876                 goto fail;
3877         }
3878
3879         status = cli_close(cli1, fnum1);
3880         if (!NT_STATUS_IS_OK(status)) {
3881                 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
3882                 correct = False;
3883                 goto fail;
3884         }
3885
3886         status = cli_close(cli1, fnum2);
3887         if (!NT_STATUS_IS_OK(status)) {
3888                 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
3889                 correct = False;
3890                 goto fail;
3891         }
3892
3893         /* This should fail - file should no longer be there. */
3894
3895         if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3896                 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
3897                 status = cli_close(cli1, fnum1);
3898                 if (!NT_STATUS_IS_OK(status)) {
3899                         printf("[3] close failed (%s)\n", nt_errstr(status));
3900                 }
3901                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3902                 correct = False;
3903                 goto fail;
3904         } else
3905                 printf("third delete on close test succeeded.\n");
3906
3907         /* Test 4 ... */
3908         cli_setatr(cli1, fname, 0, 0);
3909         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3910
3911         status = cli_ntcreate(cli1, fname, 0,
3912                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
3913                               FILE_ATTRIBUTE_NORMAL,
3914                               FILE_SHARE_READ|FILE_SHARE_WRITE,
3915                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
3916         if (!NT_STATUS_IS_OK(status)) {
3917                 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
3918                 correct = False;
3919                 goto fail;
3920         }
3921
3922         /* This should succeed. */
3923         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3924                              FILE_ATTRIBUTE_NORMAL,
3925                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3926                              FILE_OPEN, 0, 0, &fnum2);
3927         if (!NT_STATUS_IS_OK(status)) {
3928                 printf("[4] open  - 2 of %s failed (%s)\n", fname, nt_errstr(status));
3929                 correct = False;
3930                 goto fail;
3931         }
3932
3933         status = cli_close(cli1, fnum2);
3934         if (!NT_STATUS_IS_OK(status)) {
3935                 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
3936                 correct = False;
3937                 goto fail;
3938         }
3939
3940         status = cli_nt_delete_on_close(cli1, fnum1, true);
3941         if (!NT_STATUS_IS_OK(status)) {
3942                 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
3943                 correct = False;
3944                 goto fail;
3945         }
3946
3947         /* This should fail - no more opens once delete on close set. */
3948         if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3949                                    FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3950                                    FILE_OPEN, 0, 0, &fnum2))) {
3951                 printf("[4] open  - 3 of %s succeeded ! Should have failed.\n", fname );
3952                 correct = False;
3953                 goto fail;
3954         } else
3955                 printf("fourth delete on close test succeeded.\n");
3956
3957         status = cli_close(cli1, fnum1);
3958         if (!NT_STATUS_IS_OK(status)) {
3959                 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
3960                 correct = False;
3961                 goto fail;
3962         }
3963
3964         /* Test 5 ... */
3965         cli_setatr(cli1, fname, 0, 0);
3966         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3967
3968         status = cli_open(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
3969         if (!NT_STATUS_IS_OK(status)) {
3970                 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
3971                 correct = False;
3972                 goto fail;
3973         }
3974
3975         /* This should fail - only allowed on NT opens with DELETE access. */
3976
3977         if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
3978                 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
3979                 correct = False;
3980                 goto fail;
3981         }
3982
3983         status = cli_close(cli1, fnum1);
3984         if (!NT_STATUS_IS_OK(status)) {
3985                 printf("[5] close - 2 failed (%s)\n", nt_errstr(status));
3986                 correct = False;
3987                 goto fail;
3988         }
3989
3990         printf("fifth delete on close test succeeded.\n");
3991
3992         /* Test 6 ... */
3993         cli_setatr(cli1, fname, 0, 0);
3994         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3995
3996         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
3997                              FILE_ATTRIBUTE_NORMAL,
3998                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3999                              FILE_OVERWRITE_IF, 0, 0, &fnum1);
4000         if (!NT_STATUS_IS_OK(status)) {
4001                 printf("[6] open of %s failed (%s)\n", fname,
4002                        nt_errstr(status));
4003                 correct = False;
4004                 goto fail;
4005         }
4006
4007         /* This should fail - only allowed on NT opens with DELETE access. */
4008
4009         if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4010                 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
4011                 correct = False;
4012                 goto fail;
4013         }
4014
4015         status = cli_close(cli1, fnum1);
4016         if (!NT_STATUS_IS_OK(status)) {
4017                 printf("[6] close - 2 failed (%s)\n", nt_errstr(status));
4018                 correct = False;
4019                 goto fail;
4020         }
4021
4022         printf("sixth delete on close test succeeded.\n");
4023
4024         /* Test 7 ... */
4025         cli_setatr(cli1, fname, 0, 0);
4026         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4027
4028         status = cli_ntcreate(cli1, fname, 0,
4029                               FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4030                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
4031                               0, 0, &fnum1);
4032         if (!NT_STATUS_IS_OK(status)) {
4033                 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4034                 correct = False;
4035                 goto fail;
4036         }
4037
4038         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4039                 printf("[7] setting delete_on_close on file failed !\n");
4040                 correct = False;
4041                 goto fail;
4042         }
4043
4044         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, false))) {
4045                 printf("[7] unsetting delete_on_close on file failed !\n");
4046                 correct = False;
4047                 goto fail;
4048         }
4049
4050         status = cli_close(cli1, fnum1);
4051         if (!NT_STATUS_IS_OK(status)) {
4052                 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4053                 correct = False;
4054                 goto fail;
4055         }
4056
4057         /* This next open should succeed - we reset the flag. */
4058         status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4059         if (!NT_STATUS_IS_OK(status)) {
4060                 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4061                 correct = False;
4062                 goto fail;
4063         }
4064
4065         status = cli_close(cli1, fnum1);
4066         if (!NT_STATUS_IS_OK(status)) {
4067                 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4068                 correct = False;
4069                 goto fail;
4070         }
4071
4072         printf("seventh delete on close test succeeded.\n");
4073
4074         /* Test 7 ... */
4075         cli_setatr(cli1, fname, 0, 0);
4076         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4077
4078         if (!torture_open_connection(&cli2, 1)) {
4079                 printf("[8] failed to open second connection.\n");
4080                 correct = False;
4081                 goto fail;
4082         }
4083
4084         cli_sockopt(cli1, sockops);
4085
4086         status = cli_ntcreate(cli1, fname, 0,
4087                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4088                              FILE_ATTRIBUTE_NORMAL,
4089                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4090                              FILE_OVERWRITE_IF, 0, 0, &fnum1);
4091         if (!NT_STATUS_IS_OK(status)) {
4092                 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4093                 correct = False;
4094                 goto fail;
4095         }
4096
4097         status = cli_ntcreate(cli2, fname, 0,
4098                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4099                              FILE_ATTRIBUTE_NORMAL,
4100                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4101                              FILE_OPEN, 0, 0, &fnum2);
4102         if (!NT_STATUS_IS_OK(status)) {
4103                 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4104                 correct = False;
4105                 goto fail;
4106         }
4107
4108         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4109                 printf("[8] setting delete_on_close on file failed !\n");
4110                 correct = False;
4111                 goto fail;
4112         }
4113
4114         status = cli_close(cli1, fnum1);
4115         if (!NT_STATUS_IS_OK(status)) {
4116                 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
4117                 correct = False;
4118                 goto fail;
4119         }
4120
4121         status = cli_close(cli2, fnum2);
4122         if (!NT_STATUS_IS_OK(status)) {
4123                 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
4124                 correct = False;
4125                 goto fail;
4126         }
4127
4128         /* This should fail.. */
4129         status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4130         if (NT_STATUS_IS_OK(status)) {
4131                 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
4132                 goto fail;
4133                 correct = False;
4134         } else
4135                 printf("eighth delete on close test succeeded.\n");
4136
4137         /* This should fail - we need to set DELETE_ACCESS. */
4138         if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0,FILE_READ_DATA|FILE_WRITE_DATA,
4139                                    FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE, 0, &fnum1))) {
4140                 printf("[9] open of %s succeeded should have failed!\n", fname);
4141                 correct = False;
4142                 goto fail;
4143         }
4144
4145         printf("ninth delete on close test succeeded.\n");
4146
4147         status = cli_ntcreate(cli1, fname, 0,
4148                              FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4149                              FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4150                              FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
4151                              0, &fnum1);
4152         if (!NT_STATUS_IS_OK(status)) {
4153                 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
4154                 correct = False;
4155                 goto fail;
4156         }
4157
4158         /* This should delete the file. */
4159         status = cli_close(cli1, fnum1);
4160         if (!NT_STATUS_IS_OK(status)) {
4161                 printf("[10] close failed (%s)\n", nt_errstr(status));
4162                 correct = False;
4163                 goto fail;
4164         }
4165
4166         /* This should fail.. */
4167         if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
4168                 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
4169                 goto fail;
4170                 correct = False;
4171         } else
4172                 printf("tenth delete on close test succeeded.\n");
4173
4174         cli_setatr(cli1, fname, 0, 0);
4175         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4176
4177         /* What error do we get when attempting to open a read-only file with
4178            delete access ? */
4179
4180         /* Create a readonly file. */
4181         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4182                               FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
4183                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4184         if (!NT_STATUS_IS_OK(status)) {
4185                 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
4186                 correct = False;
4187                 goto fail;
4188         }
4189
4190         status = cli_close(cli1, fnum1);
4191         if (!NT_STATUS_IS_OK(status)) {
4192                 printf("[11] close failed (%s)\n", nt_errstr(status));
4193                 correct = False;
4194                 goto fail;
4195         }
4196
4197         /* Now try open for delete access. */
4198         if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES|DELETE_ACCESS,
4199                                    0, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4200                                    FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4201                 printf("[11] open of %s succeeded should have been denied with ACCESS_DENIED!\n", fname);
4202                 cli_close(cli1, fnum1);
4203                 goto fail;
4204                 correct = False;
4205         } else {
4206                 NTSTATUS nterr = cli_nt_error(cli1);
4207                 if (!NT_STATUS_EQUAL(nterr,NT_STATUS_ACCESS_DENIED)) {
4208                         printf("[11] open of %s should have been denied with ACCESS_DENIED! Got error %s\n", fname, nt_errstr(nterr));
4209                         goto fail;
4210                         correct = False;
4211                 } else {
4212                         printf("eleventh delete on close test succeeded.\n");
4213                 }
4214         }
4215
4216         printf("finished delete test\n");
4217
4218   fail:
4219         /* FIXME: This will crash if we aborted before cli2 got
4220          * intialized, because these functions don't handle
4221          * uninitialized connections. */
4222
4223         if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
4224         if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
4225         cli_setatr(cli1, fname, 0, 0);
4226         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4227
4228         if (cli1 && !torture_close_connection(cli1)) {
4229                 correct = False;
4230         }
4231         if (cli2 && !torture_close_connection(cli2)) {
4232                 correct = False;
4233         }
4234         return correct;
4235 }
4236
4237 static bool run_deletetest_ln(int dummy)
4238 {
4239         struct cli_state *cli;
4240         const char *fname = "\\delete1";
4241         const char *fname_ln = "\\delete1_ln";
4242         uint16_t fnum;
4243         uint16_t fnum1;
4244         NTSTATUS status;
4245         bool correct = true;
4246         time_t t;
4247
4248         printf("starting deletetest-ln\n");
4249
4250         if (!torture_open_connection(&cli, 0)) {
4251                 return false;
4252         }
4253
4254         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4255         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4256
4257         cli_sockopt(cli, sockops);
4258
4259         /* Create the file. */
4260         status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
4261         if (!NT_STATUS_IS_OK(status)) {
4262                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4263                 return false;
4264         }
4265
4266         status = cli_close(cli, fnum);
4267         if (!NT_STATUS_IS_OK(status)) {
4268                 printf("close1 failed (%s)\n", nt_errstr(status));
4269                 return false;
4270         }
4271
4272         /* Now create a hardlink. */
4273         status = cli_nt_hardlink(cli, fname, fname_ln);
4274         if (!NT_STATUS_IS_OK(status)) {
4275                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4276                 return false;
4277         }
4278
4279         /* Open the original file. */
4280         status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
4281                         FILE_ATTRIBUTE_NORMAL,
4282                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4283                         FILE_OPEN_IF, 0, 0, &fnum);
4284         if (!NT_STATUS_IS_OK(status)) {
4285                 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
4286                 return false;
4287         }
4288
4289         /* Unlink the hard link path. */
4290         status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
4291                         FILE_ATTRIBUTE_NORMAL,
4292                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4293                         FILE_OPEN_IF, 0, 0, &fnum1);
4294         if (!NT_STATUS_IS_OK(status)) {
4295                 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
4296                 return false;
4297         }
4298         status = cli_nt_delete_on_close(cli, fnum1, true);
4299         if (!NT_STATUS_IS_OK(status)) {
4300                 d_printf("(%s) failed to set delete_on_close %s: %s\n",
4301                         __location__, fname_ln, nt_errstr(status));
4302                 return false;
4303         }
4304
4305         status = cli_close(cli, fnum1);
4306         if (!NT_STATUS_IS_OK(status)) {
4307                 printf("close %s failed (%s)\n",
4308                         fname_ln, nt_errstr(status));
4309                 return false;
4310         }
4311
4312         status = cli_close(cli, fnum);
4313         if (!NT_STATUS_IS_OK(status)) {
4314                 printf("close %s failed (%s)\n",
4315                         fname, nt_errstr(status));
4316                 return false;
4317         }
4318
4319         /* Ensure the original file is still there. */
4320         status = cli_getatr(cli, fname, NULL, NULL, &t);
4321         if (!NT_STATUS_IS_OK(status)) {
4322                 printf("%s getatr on file %s failed (%s)\n",
4323                         __location__,
4324                         fname,
4325                         nt_errstr(status));
4326                 correct = False;
4327         }
4328
4329         /* Ensure the link path is gone. */
4330         status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
4331         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4332                 printf("%s, getatr for file %s returned wrong error code %s "
4333                         "- should have been deleted\n",
4334                         __location__,
4335                         fname_ln, nt_errstr(status));
4336                 correct = False;
4337         }
4338
4339         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4340         cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4341
4342         if (!torture_close_connection(cli)) {
4343                 correct = false;
4344         }
4345
4346         printf("finished deletetest-ln\n");
4347
4348         return correct;
4349 }
4350
4351 /*
4352   print out server properties
4353  */
4354 static bool run_properties(int dummy)
4355 {
4356         struct cli_state *cli;
4357         bool correct = True;
4358
4359         printf("starting properties test\n");
4360
4361         ZERO_STRUCT(cli);
4362
4363         if (!torture_open_connection(&cli, 0)) {
4364                 return False;
4365         }
4366
4367         cli_sockopt(cli, sockops);
4368
4369         d_printf("Capabilities 0x%08x\n", cli->capabilities);
4370
4371         if (!torture_close_connection(cli)) {
4372                 correct = False;
4373         }
4374
4375         return correct;
4376 }
4377
4378
4379
4380 /* FIRST_DESIRED_ACCESS   0xf019f */
4381 #define FIRST_DESIRED_ACCESS   FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
4382                                FILE_READ_EA|                           /* 0xf */ \
4383                                FILE_WRITE_EA|FILE_READ_ATTRIBUTES|     /* 0x90 */ \
4384                                FILE_WRITE_ATTRIBUTES|                  /* 0x100 */ \
4385                                DELETE_ACCESS|READ_CONTROL_ACCESS|\
4386                                WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS     /* 0xf0000 */
4387 /* SECOND_DESIRED_ACCESS  0xe0080 */
4388 #define SECOND_DESIRED_ACCESS  FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
4389                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4390                                WRITE_OWNER_ACCESS                      /* 0xe0000 */
4391
4392 #if 0
4393 #define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
4394                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4395                                FILE_READ_DATA|\
4396                                WRITE_OWNER_ACCESS                      /* */
4397 #endif
4398
4399 /*
4400   Test ntcreate calls made by xcopy
4401  */
4402 static bool run_xcopy(int dummy)
4403 {
4404         static struct cli_state *cli1;
4405         const char *fname = "\\test.txt";
4406         bool correct = True;
4407         uint16_t fnum1, fnum2;
4408         NTSTATUS status;
4409
4410         printf("starting xcopy test\n");
4411
4412         if (!torture_open_connection(&cli1, 0)) {
4413                 return False;
4414         }
4415
4416         status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
4417                               FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
4418                               FILE_OVERWRITE_IF, 0x4044, 0, &fnum1);
4419         if (!NT_STATUS_IS_OK(status)) {
4420                 printf("First open failed - %s\n", nt_errstr(status));
4421                 return False;
4422         }
4423
4424         status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
4425                              FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4426                              FILE_OPEN, 0x200000, 0, &fnum2);
4427         if (!NT_STATUS_IS_OK(status)) {
4428                 printf("second open failed - %s\n", nt_errstr(status));
4429                 return False;
4430         }
4431
4432         if (!torture_close_connection(cli1)) {
4433                 correct = False;
4434         }
4435
4436         return correct;
4437 }
4438
4439 /*
4440   Test rename on files open with share delete and no share delete.
4441  */
4442 static bool run_rename(int dummy)
4443 {
4444         static struct cli_state *cli1;
4445         const char *fname = "\\test.txt";
4446         const char *fname1 = "\\test1.txt";
4447         bool correct = True;
4448         uint16_t fnum1;
4449         uint16_t attr;
4450         NTSTATUS status;
4451
4452         printf("starting rename test\n");
4453
4454         if (!torture_open_connection(&cli1, 0)) {
4455                 return False;
4456         }
4457
4458         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4459         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4460
4461         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4462                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
4463                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4464         if (!NT_STATUS_IS_OK(status)) {
4465                 printf("First open failed - %s\n", nt_errstr(status));
4466                 return False;
4467         }
4468
4469         status = cli_rename(cli1, fname, fname1);
4470         if (!NT_STATUS_IS_OK(status)) {
4471                 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
4472         } else {
4473                 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
4474                 correct = False;
4475         }
4476
4477         status = cli_close(cli1, fnum1);
4478         if (!NT_STATUS_IS_OK(status)) {
4479                 printf("close - 1 failed (%s)\n", nt_errstr(status));
4480                 return False;
4481         }
4482
4483         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4484         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4485         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4486 #if 0
4487                               FILE_SHARE_DELETE|FILE_SHARE_NONE,
4488 #else
4489                               FILE_SHARE_DELETE|FILE_SHARE_READ,
4490 #endif
4491                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4492         if (!NT_STATUS_IS_OK(status)) {
4493                 printf("Second open failed - %s\n", nt_errstr(status));
4494                 return False;
4495         }
4496
4497         status = cli_rename(cli1, fname, fname1);
4498         if (!NT_STATUS_IS_OK(status)) {
4499                 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
4500                 correct = False;
4501         } else {
4502                 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
4503         }
4504
4505         status = cli_close(cli1, fnum1);
4506         if (!NT_STATUS_IS_OK(status)) {
4507                 printf("close - 2 failed (%s)\n", nt_errstr(status));
4508                 return False;
4509         }
4510
4511         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4512         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4513
4514         status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
4515                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4516                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4517         if (!NT_STATUS_IS_OK(status)) {
4518                 printf("Third open failed - %s\n", nt_errstr(status));
4519                 return False;
4520         }
4521
4522
4523 #if 0
4524   {
4525         uint16_t fnum2;
4526
4527         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
4528                                    FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4529                 printf("Fourth open failed - %s\n", cli_errstr(cli1));
4530                 return False;
4531         }
4532         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum2, true))) {
4533                 printf("[8] setting delete_on_close on file failed !\n");
4534                 return False;
4535         }
4536
4537         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
4538                 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
4539                 return False;
4540         }
4541   }
4542 #endif
4543
4544         status = cli_rename(cli1, fname, fname1);
4545         if (!NT_STATUS_IS_OK(status)) {
4546                 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
4547                 correct = False;
4548         } else {
4549                 printf("Third rename succeeded (SHARE_NONE)\n");
4550         }
4551
4552         status = cli_close(cli1, fnum1);
4553         if (!NT_STATUS_IS_OK(status)) {
4554                 printf("close - 3 failed (%s)\n", nt_errstr(status));
4555                 return False;
4556         }
4557
4558         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4559         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4560
4561         /*----*/
4562
4563         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4564                               FILE_ATTRIBUTE_NORMAL,
4565                               FILE_SHARE_READ | FILE_SHARE_WRITE,
4566                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4567         if (!NT_STATUS_IS_OK(status)) {
4568                 printf("Fourth open failed - %s\n", nt_errstr(status));
4569                 return False;
4570         }
4571
4572         status = cli_rename(cli1, fname, fname1);
4573         if (!NT_STATUS_IS_OK(status)) {
4574                 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
4575         } else {
4576                 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
4577                 correct = False;
4578         }
4579
4580         status = cli_close(cli1, fnum1);
4581         if (!NT_STATUS_IS_OK(status)) {
4582                 printf("close - 4 failed (%s)\n", nt_errstr(status));
4583                 return False;
4584         }
4585
4586         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4587         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4588
4589         /*--*/
4590
4591         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4592                          FILE_ATTRIBUTE_NORMAL,
4593                          FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4594                          FILE_OVERWRITE_IF, 0, 0, &fnum1);
4595         if (!NT_STATUS_IS_OK(status)) {
4596                 printf("Fifth open failed - %s\n", nt_errstr(status));
4597                 return False;
4598         }
4599
4600         status = cli_rename(cli1, fname, fname1);
4601         if (!NT_STATUS_IS_OK(status)) {
4602                 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
4603                 correct = False;
4604         } else {
4605                 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
4606         }
4607
4608         /*
4609          * Now check if the first name still exists ...
4610          */
4611
4612         /* if (!NT_STATUS_OP(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4613                                    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4614           printf("Opening original file after rename of open file fails: %s\n",
4615               cli_errstr(cli1));
4616         }
4617         else {
4618           printf("Opening original file after rename of open file works ...\n");
4619           (void)cli_close(cli1, fnum2);
4620           } */
4621
4622         /*--*/
4623         status = cli_close(cli1, fnum1);
4624         if (!NT_STATUS_IS_OK(status)) {
4625                 printf("close - 5 failed (%s)\n", nt_errstr(status));
4626                 return False;
4627         }
4628
4629         /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
4630         status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
4631         if (!NT_STATUS_IS_OK(status)) {
4632                 printf("getatr on file %s failed - %s ! \n",
4633                         fname1, nt_errstr(status));
4634                 correct = False;
4635         } else {
4636                 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
4637                         printf("Renamed file %s has wrong attr 0x%x "
4638                                 "(should be 0x%x)\n",
4639                                 fname1,
4640                                 attr,
4641                                 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
4642                         correct = False;
4643                 } else {
4644                         printf("Renamed file %s has archive bit set\n", fname1);
4645                 }
4646         }
4647
4648         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4649         cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4650
4651         if (!torture_close_connection(cli1)) {
4652                 correct = False;
4653         }
4654
4655         return correct;
4656 }
4657
4658 static bool run_pipe_number(int dummy)
4659 {
4660         struct cli_state *cli1;
4661         const char *pipe_name = "\\SPOOLSS";
4662         uint16_t fnum;
4663         int num_pipes = 0;
4664         NTSTATUS status;
4665
4666         printf("starting pipenumber test\n");
4667         if (!torture_open_connection(&cli1, 0)) {
4668                 return False;
4669         }
4670
4671         cli_sockopt(cli1, sockops);
4672         while(1) {
4673                 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
4674                                       FILE_ATTRIBUTE_NORMAL,
4675                                       FILE_SHARE_READ|FILE_SHARE_WRITE,
4676                                       FILE_OPEN_IF, 0, 0, &fnum);
4677                 if (!NT_STATUS_IS_OK(status)) {
4678                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
4679                         break;
4680                 }
4681                 num_pipes++;
4682                 printf("\r%6d", num_pipes);
4683         }
4684
4685         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
4686         torture_close_connection(cli1);
4687         return True;
4688 }
4689
4690 /*
4691   Test open mode returns on read-only files.
4692  */
4693 static bool run_opentest(int dummy)
4694 {
4695         static struct cli_state *cli1;
4696         static struct cli_state *cli2;
4697         const char *fname = "\\readonly.file";
4698         uint16_t fnum1, fnum2;
4699         char buf[20];
4700         SMB_OFF_T fsize;
4701         bool correct = True;
4702         char *tmp_path;
4703         NTSTATUS status;
4704
4705         printf("starting open test\n");
4706
4707         if (!torture_open_connection(&cli1, 0)) {
4708                 return False;
4709         }
4710
4711         cli_setatr(cli1, fname, 0, 0);
4712         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4713
4714         cli_sockopt(cli1, sockops);
4715
4716         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4717         if (!NT_STATUS_IS_OK(status)) {
4718                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4719                 return False;
4720         }
4721
4722         status = cli_close(cli1, fnum1);
4723         if (!NT_STATUS_IS_OK(status)) {
4724                 printf("close2 failed (%s)\n", nt_errstr(status));
4725                 return False;
4726         }
4727
4728         status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
4729         if (!NT_STATUS_IS_OK(status)) {
4730                 printf("cli_setatr failed (%s)\n", nt_errstr(status));
4731                 return False;
4732         }
4733
4734         status = cli_open(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4735         if (!NT_STATUS_IS_OK(status)) {
4736                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4737                 return False;
4738         }
4739
4740         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
4741         cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4742
4743         if (check_error(__LINE__, cli1, ERRDOS, ERRnoaccess, 
4744                         NT_STATUS_ACCESS_DENIED)) {
4745                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
4746         }
4747
4748         printf("finished open test 1\n");
4749
4750         cli_close(cli1, fnum1);
4751
4752         /* Now try not readonly and ensure ERRbadshare is returned. */
4753
4754         cli_setatr(cli1, fname, 0, 0);
4755
4756         status = cli_open(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4757         if (!NT_STATUS_IS_OK(status)) {
4758                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4759                 return False;
4760         }
4761
4762         /* This will fail - but the error should be ERRshare. */
4763         cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4764
4765         if (check_error(__LINE__, cli1, ERRDOS, ERRbadshare, 
4766                         NT_STATUS_SHARING_VIOLATION)) {
4767                 printf("correct error code ERRDOS/ERRbadshare returned\n");
4768         }
4769
4770         status = cli_close(cli1, fnum1);
4771         if (!NT_STATUS_IS_OK(status)) {
4772                 printf("close2 failed (%s)\n", nt_errstr(status));
4773                 return False;
4774         }
4775
4776         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4777
4778         printf("finished open test 2\n");
4779
4780         /* Test truncate open disposition on file opened for read. */
4781         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4782         if (!NT_STATUS_IS_OK(status)) {
4783                 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
4784                 return False;
4785         }
4786
4787         /* write 20 bytes. */
4788
4789         memset(buf, '\0', 20);
4790
4791         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
4792         if (!NT_STATUS_IS_OK(status)) {
4793                 printf("write failed (%s)\n", nt_errstr(status));
4794                 correct = False;
4795         }
4796
4797         status = cli_close(cli1, fnum1);
4798         if (!NT_STATUS_IS_OK(status)) {
4799                 printf("(3) close1 failed (%s)\n", nt_errstr(status));
4800                 return False;
4801         }
4802
4803         /* Ensure size == 20. */
4804         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
4805         if (!NT_STATUS_IS_OK(status)) {
4806                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
4807                 return False;
4808         }
4809
4810         if (fsize != 20) {
4811                 printf("(3) file size != 20\n");
4812                 return False;
4813         }
4814
4815         /* Now test if we can truncate a file opened for readonly. */
4816         status = cli_open(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
4817         if (!NT_STATUS_IS_OK(status)) {
4818                 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
4819                 return False;
4820         }
4821
4822         status = cli_close(cli1, fnum1);
4823         if (!NT_STATUS_IS_OK(status)) {
4824                 printf("close2 failed (%s)\n", nt_errstr(status));
4825                 return False;
4826         }
4827
4828         /* Ensure size == 0. */
4829         status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
4830         if (!NT_STATUS_IS_OK(status)) {
4831                 printf("(3) getatr failed (%s)\n", nt_errstr(status));
4832                 return False;
4833         }
4834
4835         if (fsize != 0) {
4836                 printf("(3) file size != 0\n");
4837                 return False;
4838         }
4839         printf("finished open test 3\n");
4840
4841         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4842
4843         printf("Do ctemp tests\n");
4844         status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
4845         if (!NT_STATUS_IS_OK(status)) {
4846                 printf("ctemp failed (%s)\n", nt_errstr(status));
4847                 return False;
4848         }
4849
4850         printf("ctemp gave path %s\n", tmp_path);
4851         status = cli_close(cli1, fnum1);
4852         if (!NT_STATUS_IS_OK(status)) {
4853                 printf("close of temp failed (%s)\n", nt_errstr(status));
4854         }
4855
4856         status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4857         if (!NT_STATUS_IS_OK(status)) {
4858                 printf("unlink of temp failed (%s)\n", nt_errstr(status));
4859         }
4860
4861         /* Test the non-io opens... */
4862
4863         if (!torture_open_connection(&cli2, 1)) {
4864                 return False;
4865         }
4866
4867         cli_setatr(cli2, fname, 0, 0);
4868         cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4869
4870         cli_sockopt(cli2, sockops);
4871
4872         printf("TEST #1 testing 2 non-io opens (no delete)\n");
4873         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
4874                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4875                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4876         if (!NT_STATUS_IS_OK(status)) {
4877                 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4878                 return False;
4879         }
4880
4881         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
4882                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4883                               FILE_OPEN_IF, 0, 0, &fnum2);
4884         if (!NT_STATUS_IS_OK(status)) {
4885                 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4886                 return False;
4887         }
4888
4889         status = cli_close(cli1, fnum1);
4890         if (!NT_STATUS_IS_OK(status)) {
4891                 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
4892                 return False;
4893         }
4894
4895         status = cli_close(cli2, fnum2);
4896         if (!NT_STATUS_IS_OK(status)) {
4897                 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
4898                 return False;
4899         }
4900
4901         printf("non-io open test #1 passed.\n");
4902
4903         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4904
4905         printf("TEST #2 testing 2 non-io opens (first with delete)\n");
4906
4907         status = cli_ntcreate(cli1, fname, 0,
4908                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
4909                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4910                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4911         if (!NT_STATUS_IS_OK(status)) {
4912                 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4913                 return False;
4914         }
4915
4916         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
4917                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4918                               FILE_OPEN_IF, 0, 0, &fnum2);
4919         if (!NT_STATUS_IS_OK(status)) {
4920                 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4921                 return False;
4922         }
4923
4924         status = cli_close(cli1, fnum1);
4925         if (!NT_STATUS_IS_OK(status)) {
4926                 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
4927                 return False;
4928         }
4929
4930         status = cli_close(cli2, fnum2);
4931         if (!NT_STATUS_IS_OK(status)) {
4932                 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
4933                 return False;
4934         }
4935
4936         printf("non-io open test #2 passed.\n");
4937
4938         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4939
4940         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
4941
4942         status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
4943                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4944                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4945         if (!NT_STATUS_IS_OK(status)) {
4946                 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4947                 return False;
4948         }
4949
4950         status = cli_ntcreate(cli2, fname, 0,
4951                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
4952                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4953                               FILE_OPEN_IF, 0, 0, &fnum2);
4954         if (!NT_STATUS_IS_OK(status)) {
4955                 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4956                 return False;
4957         }
4958
4959         status = cli_close(cli1, fnum1);
4960         if (!NT_STATUS_IS_OK(status)) {
4961                 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
4962                 return False;
4963         }
4964
4965         status = cli_close(cli2, fnum2);
4966         if (!NT_STATUS_IS_OK(status)) {
4967                 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
4968                 return False;
4969         }
4970
4971         printf("non-io open test #3 passed.\n");
4972
4973         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4974
4975         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
4976
4977         status = cli_ntcreate(cli1, fname, 0,
4978                                DELETE_ACCESS|FILE_READ_ATTRIBUTES,
4979                                FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4980                                FILE_OVERWRITE_IF, 0, 0, &fnum1);
4981         if (!NT_STATUS_IS_OK(status)) {
4982                 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4983                 return False;
4984         }
4985
4986         status = cli_ntcreate(cli2, fname, 0,
4987                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
4988                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4989                               FILE_OPEN_IF, 0, 0, &fnum2);
4990         if (NT_STATUS_IS_OK(status)) {
4991                 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
4992                 return False;
4993         }
4994
4995         printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
4996
4997         status = cli_close(cli1, fnum1);
4998         if (!NT_STATUS_IS_OK(status)) {
4999                 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5000                 return False;
5001         }
5002
5003         printf("non-io open test #4 passed.\n");
5004
5005         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5006
5007         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
5008
5009         status = cli_ntcreate(cli1, fname, 0,
5010                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5011                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5012                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5013         if (!NT_STATUS_IS_OK(status)) {
5014                 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5015                 return False;
5016         }
5017
5018         status = cli_ntcreate(cli2, fname, 0,
5019                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5020                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5021                               FILE_OPEN_IF, 0, 0, &fnum2);
5022         if (!NT_STATUS_IS_OK(status)) {
5023                 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5024                 return False;
5025         }
5026
5027         status = cli_close(cli1, fnum1);
5028         if (!NT_STATUS_IS_OK(status)) {
5029                 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5030                 return False;
5031         }
5032
5033         status = cli_close(cli2, fnum2);
5034         if (!NT_STATUS_IS_OK(status)) {
5035                 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5036                 return False;
5037         }
5038
5039         printf("non-io open test #5 passed.\n");
5040
5041         printf("TEST #6 testing 1 non-io open, one io open\n");
5042
5043         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5044
5045         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5046                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5047                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5048         if (!NT_STATUS_IS_OK(status)) {
5049                 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5050                 return False;
5051         }
5052
5053         status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5054                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
5055                               FILE_OPEN_IF, 0, 0, &fnum2);
5056         if (!NT_STATUS_IS_OK(status)) {
5057                 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5058                 return False;
5059         }
5060
5061         status = cli_close(cli1, fnum1);
5062         if (!NT_STATUS_IS_OK(status)) {
5063                 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5064                 return False;
5065         }
5066
5067         status = cli_close(cli2, fnum2);
5068         if (!NT_STATUS_IS_OK(status)) {
5069                 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5070                 return False;
5071         }
5072
5073         printf("non-io open test #6 passed.\n");
5074
5075         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
5076
5077         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5078
5079         status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5080                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5081                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
5082         if (!NT_STATUS_IS_OK(status)) {
5083                 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5084                 return False;
5085         }
5086
5087         status = cli_ntcreate(cli2, fname, 0,
5088                               DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5089                               FILE_ATTRIBUTE_NORMAL,
5090                               FILE_SHARE_READ|FILE_SHARE_DELETE,
5091                               FILE_OPEN_IF, 0, 0, &fnum2);
5092         if (NT_STATUS_IS_OK(status)) {
5093                 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5094                 return False;
5095         }
5096
5097         printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5098
5099         status = cli_close(cli1, fnum1);
5100         if (!NT_STATUS_IS_OK(status)) {
5101                 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5102                 return False;
5103         }
5104
5105         printf("non-io open test #7 passed.\n");
5106
5107         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5108
5109         printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
5110         status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
5111                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5112                                 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5113         if (!NT_STATUS_IS_OK(status)) {
5114                 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
5115                 correct = false;
5116                 goto out;
5117         }
5118
5119         /* Write to ensure we have to update the file time. */
5120         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5121                               NULL);
5122         if (!NT_STATUS_IS_OK(status)) {
5123                 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
5124                 correct = false;
5125                 goto out;
5126         }
5127
5128         status = cli_close(cli1, fnum1);
5129         if (!NT_STATUS_IS_OK(status)) {
5130                 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
5131                 correct = false;
5132         }
5133
5134   out:
5135
5136         if (!torture_close_connection(cli1)) {
5137                 correct = False;
5138         }
5139         if (!torture_close_connection(cli2)) {
5140                 correct = False;
5141         }
5142
5143         return correct;
5144 }
5145
5146 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
5147 {
5148         uint16 major, minor;
5149         uint32 caplow, caphigh;
5150         NTSTATUS status;
5151
5152         if (!SERVER_HAS_UNIX_CIFS(cli)) {
5153                 printf("Server doesn't support UNIX CIFS extensions.\n");
5154                 return NT_STATUS_NOT_SUPPORTED;
5155         }
5156
5157         status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
5158                                              &caphigh);
5159         if (!NT_STATUS_IS_OK(status)) {
5160                 printf("Server didn't return UNIX CIFS extensions: %s\n",
5161                        nt_errstr(status));
5162                 return status;
5163         }
5164
5165         status = cli_set_unix_extensions_capabilities(cli, major, minor,
5166                                                       caplow, caphigh);
5167         if (!NT_STATUS_IS_OK(status)) {
5168                 printf("Server doesn't support setting UNIX CIFS extensions: "
5169                        "%s.\n", nt_errstr(status));
5170                 return status;
5171         }
5172
5173         return NT_STATUS_OK;
5174 }
5175
5176 /*
5177   Test POSIX open /mkdir calls.
5178  */
5179 static bool run_simple_posix_open_test(int dummy)
5180 {
5181         static struct cli_state *cli1;
5182         const char *fname = "posix:file";
5183         const char *hname = "posix:hlink";
5184         const char *sname = "posix:symlink";
5185         const char *dname = "posix:dir";
5186         char buf[10];
5187         char namebuf[11];
5188         uint16_t fnum1 = (uint16_t)-1;
5189         SMB_STRUCT_STAT sbuf;
5190         bool correct = false;
5191         NTSTATUS status;
5192
5193         printf("Starting simple POSIX open test\n");
5194
5195         if (!torture_open_connection(&cli1, 0)) {
5196                 return false;
5197         }
5198
5199         cli_sockopt(cli1, sockops);
5200
5201         status = torture_setup_unix_extensions(cli1);
5202         if (!NT_STATUS_IS_OK(status)) {
5203                 return false;
5204         }
5205
5206         cli_setatr(cli1, fname, 0, 0);
5207         cli_posix_unlink(cli1, fname);
5208         cli_setatr(cli1, dname, 0, 0);
5209         cli_posix_rmdir(cli1, dname);
5210         cli_setatr(cli1, hname, 0, 0);
5211         cli_posix_unlink(cli1, hname);
5212         cli_setatr(cli1, sname, 0, 0);
5213         cli_posix_unlink(cli1, sname);
5214
5215         /* Create a directory. */
5216         status = cli_posix_mkdir(cli1, dname, 0777);
5217         if (!NT_STATUS_IS_OK(status)) {
5218                 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
5219                 goto out;
5220         }
5221
5222         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5223                                 0600, &fnum1);
5224         if (!NT_STATUS_IS_OK(status)) {
5225                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5226                 goto out;
5227         }
5228
5229         /* Test ftruncate - set file size. */
5230         status = cli_ftruncate(cli1, fnum1, 1000);
5231         if (!NT_STATUS_IS_OK(status)) {
5232                 printf("ftruncate failed (%s)\n", nt_errstr(status));
5233                 goto out;
5234         }
5235
5236         /* Ensure st_size == 1000 */
5237         status = cli_posix_stat(cli1, fname, &sbuf);
5238         if (!NT_STATUS_IS_OK(status)) {
5239                 printf("stat failed (%s)\n", nt_errstr(status));
5240                 goto out;
5241         }
5242
5243         if (sbuf.st_ex_size != 1000) {
5244                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5245                 goto out;
5246         }
5247
5248         /* Test ftruncate - set file size back to zero. */
5249         status = cli_ftruncate(cli1, fnum1, 0);
5250         if (!NT_STATUS_IS_OK(status)) {
5251                 printf("ftruncate failed (%s)\n", nt_errstr(status));
5252                 goto out;
5253         }
5254
5255         status = cli_close(cli1, fnum1);
5256         if (!NT_STATUS_IS_OK(status)) {
5257                 printf("close failed (%s)\n", nt_errstr(status));
5258                 goto out;
5259         }
5260
5261         /* Now open the file again for read only. */
5262         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5263         if (!NT_STATUS_IS_OK(status)) {
5264                 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
5265                 goto out;
5266         }
5267
5268         /* Now unlink while open. */
5269         status = cli_posix_unlink(cli1, fname);
5270         if (!NT_STATUS_IS_OK(status)) {
5271                 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5272                 goto out;
5273         }
5274
5275         status = cli_close(cli1, fnum1);
5276         if (!NT_STATUS_IS_OK(status)) {
5277                 printf("close(2) failed (%s)\n", nt_errstr(status));
5278                 goto out;
5279         }
5280
5281         /* Ensure the file has gone. */
5282         status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5283         if (NT_STATUS_IS_OK(status)) {
5284                 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
5285                 goto out;
5286         }
5287
5288         /* Create again to test open with O_TRUNC. */
5289         if (!NT_STATUS_IS_OK(cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1))) {
5290                 printf("POSIX create of %s failed (%s)\n", fname, cli_errstr(cli1));
5291                 goto out;
5292         }
5293
5294         /* Test ftruncate - set file size. */
5295         if (!NT_STATUS_IS_OK(cli_ftruncate(cli1, fnum1, 1000))) {
5296                 printf("ftruncate failed (%s)\n", cli_errstr(cli1));
5297                 goto out;
5298         }
5299
5300         /* Ensure st_size == 1000 */
5301         if (!NT_STATUS_IS_OK(cli_posix_stat(cli1, fname, &sbuf))) {
5302                 printf("stat failed (%s)\n", cli_errstr(cli1));
5303                 goto out;
5304         }
5305
5306         if (sbuf.st_ex_size != 1000) {
5307                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5308                 goto out;
5309         }
5310
5311         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
5312                 printf("close(2) failed (%s)\n", cli_errstr(cli1));
5313                 goto out;
5314         }
5315
5316         /* Re-open with O_TRUNC. */
5317         if (!NT_STATUS_IS_OK(cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1))) {
5318                 printf("POSIX create of %s failed (%s)\n", fname, cli_errstr(cli1));
5319                 goto out;
5320         }
5321
5322         /* Ensure st_size == 0 */
5323         if (!NT_STATUS_IS_OK(cli_posix_stat(cli1, fname, &sbuf))) {
5324                 printf("stat failed (%s)\n", cli_errstr(cli1));
5325                 goto out;
5326         }
5327
5328         if (sbuf.st_ex_size != 0) {
5329                 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
5330                 goto out;
5331         }
5332
5333         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
5334                 printf("close failed (%s)\n", cli_errstr(cli1));
5335                 goto out;
5336         }
5337
5338         if (!NT_STATUS_IS_OK(cli_posix_unlink(cli1, fname))) {
5339                 printf("POSIX unlink of %s failed (%s)\n", fname, cli_errstr(cli1));
5340                 goto out;
5341         }
5342
5343         if (!NT_STATUS_IS_OK(cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1))) {
5344                 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
5345                         dname, cli_errstr(cli1));
5346                 goto out;
5347         }
5348
5349         cli_close(cli1, fnum1);
5350
5351         /* What happens when we try and POSIX open a directory for write ? */
5352         if (NT_STATUS_IS_OK(cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1))) {
5353                 printf("POSIX open of directory %s succeeded, should have failed.\n", fname);
5354                 goto out;
5355         } else {
5356                 if (!check_error(__LINE__, cli1, ERRDOS, EISDIR,
5357                                 NT_STATUS_FILE_IS_A_DIRECTORY)) {
5358                         goto out;
5359                 }
5360         }
5361
5362         /* Create the file. */
5363         status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5364                                 0600, &fnum1);
5365         if (!NT_STATUS_IS_OK(status)) {
5366                 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5367                 goto out;
5368         }
5369
5370         /* Write some data into it. */
5371         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5372                               NULL);
5373         if (!NT_STATUS_IS_OK(status)) {
5374                 printf("cli_write failed: %s\n", nt_errstr(status));
5375                 goto out;
5376         }
5377
5378         cli_close(cli1, fnum1);
5379
5380         /* Now create a hardlink. */
5381         status = cli_posix_hardlink(cli1, fname, hname);
5382         if (!NT_STATUS_IS_OK(status)) {
5383                 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
5384                 goto out;
5385         }
5386
5387         /* Now create a symlink. */
5388         status = cli_posix_symlink(cli1, fname, sname);
5389         if (!NT_STATUS_IS_OK(status)) {
5390                 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
5391                 goto out;
5392         }
5393
5394         /* Open the hardlink for read. */
5395         status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
5396         if (!NT_STATUS_IS_OK(status)) {
5397                 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
5398                 goto out;
5399         }
5400
5401         if (cli_read(cli1, fnum1, buf, 0, 10) != 10) {
5402                 printf("POSIX read of %s failed (%s)\n", hname, cli_errstr(cli1));
5403                 goto out;
5404         }
5405
5406         if (memcmp(buf, "TEST DATA\n", 10)) {
5407                 printf("invalid data read from hardlink\n");
5408                 goto out;
5409         }
5410
5411         /* Do a POSIX lock/unlock. */
5412         status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
5413         if (!NT_STATUS_IS_OK(status)) {
5414                 printf("POSIX lock failed %s\n", nt_errstr(status));
5415                 goto out;
5416         }
5417
5418         /* Punch a hole in the locked area. */
5419         status = cli_posix_unlock(cli1, fnum1, 10, 80);
5420         if (!NT_STATUS_IS_OK(status)) {
5421                 printf("POSIX unlock failed %s\n", nt_errstr(status));
5422                 goto out;
5423         }
5424
5425         cli_close(cli1, fnum1);
5426
5427         /* Open the symlink for read - this should fail. A POSIX
5428            client should not be doing opens on a symlink. */
5429         status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
5430         if (NT_STATUS_IS_OK(status)) {
5431                 printf("POSIX open of %s succeeded (should have failed)\n", sname);
5432                 goto out;
5433         } else {
5434                 if (!check_error(__LINE__, cli1, ERRDOS, ERRbadpath,
5435                                 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
5436                         printf("POSIX open of %s should have failed "
5437                                 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
5438                                 "failed with %s instead.\n",
5439                                 sname, nt_errstr(status));
5440                         goto out;
5441                 }
5442         }
5443
5444         status = cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf));
5445         if (!NT_STATUS_IS_OK(status)) {
5446                 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
5447                 goto out;
5448         }
5449
5450         if (strcmp(namebuf, fname) != 0) {
5451                 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
5452                         sname, fname, namebuf);
5453                 goto out;
5454         }
5455
5456         status = cli_posix_rmdir(cli1, dname);
5457         if (!NT_STATUS_IS_OK(status)) {
5458                 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
5459                 goto out;
5460         }
5461
5462         printf("Simple POSIX open test passed\n");
5463         correct = true;
5464
5465   out:
5466
5467         if (fnum1 != (uint16_t)-1) {
5468                 cli_close(cli1, fnum1);
5469                 fnum1 = (uint16_t)-1;
5470         }
5471
5472         cli_setatr(cli1, sname, 0, 0);
5473         cli_posix_unlink(cli1, sname);
5474         cli_setatr(cli1, hname, 0, 0);
5475         cli_posix_unlink(cli1, hname);
5476         cli_setatr(cli1, fname, 0, 0);
5477         cli_posix_unlink(cli1, fname);
5478         cli_setatr(cli1, dname, 0, 0);
5479         cli_posix_rmdir(cli1, dname);
5480
5481         if (!torture_close_connection(cli1)) {
5482                 correct = false;
5483         }
5484
5485         return correct;
5486 }
5487
5488
5489 static uint32 open_attrs_table[] = {
5490                 FILE_ATTRIBUTE_NORMAL,
5491                 FILE_ATTRIBUTE_ARCHIVE,
5492                 FILE_ATTRIBUTE_READONLY,
5493                 FILE_ATTRIBUTE_HIDDEN,
5494                 FILE_ATTRIBUTE_SYSTEM,
5495
5496                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
5497                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
5498                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
5499                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5500                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5501                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5502
5503                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5504                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5505                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5506                 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
5507 };
5508
5509 struct trunc_open_results {
5510         unsigned int num;
5511         uint32 init_attr;
5512         uint32 trunc_attr;
5513         uint32 result_attr;
5514 };
5515
5516 static struct trunc_open_results attr_results[] = {
5517         { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5518         { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5519         { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5520         { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5521         { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5522         { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5523         { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5524         { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5525         { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5526         { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5527         { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5528         { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
5529         { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5530         { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5531         { 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 },
5532         { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5533         { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5534         { 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 },
5535         { 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 },
5536         { 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 },
5537         { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5538         { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5539         { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5540         { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5541         { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5542         { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
5543 };
5544
5545 static bool run_openattrtest(int dummy)
5546 {
5547         static struct cli_state *cli1;
5548         const char *fname = "\\openattr.file";
5549         uint16_t fnum1;
5550         bool correct = True;
5551         uint16 attr;
5552         unsigned int i, j, k, l;
5553         NTSTATUS status;
5554
5555         printf("starting open attr test\n");
5556
5557         if (!torture_open_connection(&cli1, 0)) {
5558                 return False;
5559         }
5560
5561         cli_sockopt(cli1, sockops);
5562
5563         for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32); i++) {
5564                 cli_setatr(cli1, fname, 0, 0);
5565                 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5566
5567                 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
5568                                        open_attrs_table[i], FILE_SHARE_NONE,
5569                                        FILE_OVERWRITE_IF, 0, 0, &fnum1);
5570                 if (!NT_STATUS_IS_OK(status)) {
5571                         printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5572                         return False;
5573                 }
5574
5575                 status = cli_close(cli1, fnum1);
5576                 if (!NT_STATUS_IS_OK(status)) {
5577                         printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5578                         return False;
5579                 }
5580
5581                 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32); j++) {
5582                         status = cli_ntcreate(cli1, fname, 0,
5583                                               FILE_READ_DATA|FILE_WRITE_DATA,
5584                                               open_attrs_table[j],
5585                                               FILE_SHARE_NONE, FILE_OVERWRITE,
5586                                               0, 0, &fnum1);
5587                         if (!NT_STATUS_IS_OK(status)) {
5588                                 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5589                                         if (attr_results[l].num == k) {
5590                                                 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
5591                                                                 k, open_attrs_table[i],
5592                                                                 open_attrs_table[j],
5593                                                                 fname, NT_STATUS_V(status), nt_errstr(status));
5594                                                 correct = False;
5595                                         }
5596                                 }
5597
5598                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5599                                         printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
5600                                                         k, open_attrs_table[i], open_attrs_table[j],
5601                                                         nt_errstr(status));
5602                                         correct = False;
5603                                 }
5604 #if 0
5605                                 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
5606 #endif
5607                                 k++;
5608                                 continue;
5609                         }
5610
5611                         status = cli_close(cli1, fnum1);
5612                         if (!NT_STATUS_IS_OK(status)) {
5613                                 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
5614                                 return False;
5615                         }
5616
5617                         status = cli_getatr(cli1, fname, &attr, NULL, NULL);
5618                         if (!NT_STATUS_IS_OK(status)) {
5619                                 printf("getatr(2) failed (%s)\n", nt_errstr(status));
5620                                 return False;
5621                         }
5622
5623 #if 0
5624                         printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
5625                                         k,  open_attrs_table[i],  open_attrs_table[j], attr );
5626 #endif
5627
5628                         for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5629                                 if (attr_results[l].num == k) {
5630                                         if (attr != attr_results[l].result_attr ||
5631                                                         open_attrs_table[i] != attr_results[l].init_attr ||
5632                                                         open_attrs_table[j] != attr_results[l].trunc_attr) {
5633                                                 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
5634                                                 open_attrs_table[i],
5635                                                 open_attrs_table[j],
5636                                                 (unsigned int)attr,
5637                                                 attr_results[l].result_attr);
5638                                                 correct = False;
5639                                         }
5640                                         break;
5641                                 }
5642                         }
5643                         k++;
5644                 }
5645         }
5646
5647         cli_setatr(cli1, fname, 0, 0);
5648         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5649
5650         printf("open attr test %s.\n", correct ? "passed" : "failed");
5651
5652         if (!torture_close_connection(cli1)) {
5653                 correct = False;
5654         }
5655         return correct;
5656 }
5657
5658 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
5659                     const char *name, void *state)
5660 {
5661         int *matched = (int *)state;
5662         if (matched != NULL) {
5663                 *matched += 1;
5664         }
5665         return NT_STATUS_OK;
5666 }
5667
5668 /*
5669   test directory listing speed
5670  */
5671 static bool run_dirtest(int dummy)
5672 {
5673         int i;
5674         static struct cli_state *cli;
5675         uint16_t fnum;
5676         struct timeval core_start;
5677         bool correct = True;
5678         int matched;
5679
5680         printf("starting directory test\n");
5681
5682         if (!torture_open_connection(&cli, 0)) {
5683                 return False;
5684         }
5685
5686         cli_sockopt(cli, sockops);
5687
5688         srandom(0);
5689         for (i=0;i<torture_numops;i++) {
5690                 fstring fname;
5691                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5692                 if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
5693                         fprintf(stderr,"Failed to open %s\n", fname);
5694                         return False;
5695                 }
5696                 cli_close(cli, fnum);
5697         }
5698
5699         core_start = timeval_current();
5700
5701         matched = 0;
5702         cli_list(cli, "a*.*", 0, list_fn, &matched);
5703         printf("Matched %d\n", matched);
5704
5705         matched = 0;
5706         cli_list(cli, "b*.*", 0, list_fn, &matched);
5707         printf("Matched %d\n", matched);
5708
5709         matched = 0;
5710         cli_list(cli, "xyzabc", 0, list_fn, &matched);
5711         printf("Matched %d\n", matched);
5712
5713         printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
5714
5715         srandom(0);
5716         for (i=0;i<torture_numops;i++) {
5717                 fstring fname;
5718                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5719                 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5720         }
5721
5722         if (!torture_close_connection(cli)) {
5723                 correct = False;
5724         }
5725
5726         printf("finished dirtest\n");
5727
5728         return correct;
5729 }
5730
5731 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
5732                    void *state)
5733 {
5734         struct cli_state *pcli = (struct cli_state *)state;
5735         fstring fname;
5736         slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
5737
5738         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
5739                 return NT_STATUS_OK;
5740
5741         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
5742                 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
5743                         printf("del_fn: failed to rmdir %s\n,", fname );
5744         } else {
5745                 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
5746                         printf("del_fn: failed to unlink %s\n,", fname );
5747         }
5748         return NT_STATUS_OK;
5749 }
5750
5751
5752 /*
5753   sees what IOCTLs are supported
5754  */
5755 bool torture_ioctl_test(int dummy)
5756 {
5757         static struct cli_state *cli;
5758         uint16_t device, function;
5759         uint16_t fnum;
5760         const char *fname = "\\ioctl.dat";
5761         DATA_BLOB blob;
5762         NTSTATUS status;
5763
5764         if (!torture_open_connection(&cli, 0)) {
5765                 return False;
5766         }
5767
5768         printf("starting ioctl test\n");
5769
5770         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5771
5772         status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5773         if (!NT_STATUS_IS_OK(status)) {
5774                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5775                 return False;
5776         }
5777
5778         status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
5779         printf("ioctl device info: %s\n", nt_errstr(status));
5780
5781         status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
5782         printf("ioctl job info: %s\n", nt_errstr(status));
5783
5784         for (device=0;device<0x100;device++) {
5785                 printf("ioctl test with device = 0x%x\n", device);
5786                 for (function=0;function<0x100;function++) {
5787                         uint32 code = (device<<16) | function;
5788
5789                         status = cli_raw_ioctl(cli, fnum, code, &blob);
5790
5791                         if (NT_STATUS_IS_OK(status)) {
5792                                 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
5793                                        (int)blob.length);
5794                                 data_blob_free(&blob);
5795                         }
5796                 }
5797         }
5798
5799         if (!torture_close_connection(cli)) {
5800                 return False;
5801         }
5802
5803         return True;
5804 }
5805
5806
5807 /*
5808   tries varients of chkpath
5809  */
5810 bool torture_chkpath_test(int dummy)
5811 {
5812         static struct cli_state *cli;
5813         uint16_t fnum;
5814         bool ret;
5815         NTSTATUS status;
5816
5817         if (!torture_open_connection(&cli, 0)) {
5818                 return False;
5819         }
5820
5821         printf("starting chkpath test\n");
5822
5823         /* cleanup from an old run */
5824         cli_rmdir(cli, "\\chkpath.dir\\dir2");
5825         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5826         cli_rmdir(cli, "\\chkpath.dir");
5827
5828         status = cli_mkdir(cli, "\\chkpath.dir");
5829         if (!NT_STATUS_IS_OK(status)) {
5830                 printf("mkdir1 failed : %s\n", nt_errstr(status));
5831                 return False;
5832         }
5833
5834         status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
5835         if (!NT_STATUS_IS_OK(status)) {
5836                 printf("mkdir2 failed : %s\n", nt_errstr(status));
5837                 return False;
5838         }
5839
5840         status = cli_open(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
5841                           DENY_NONE, &fnum);
5842         if (!NT_STATUS_IS_OK(status)) {
5843                 printf("open1 failed (%s)\n", nt_errstr(status));
5844                 return False;
5845         }
5846         cli_close(cli, fnum);
5847
5848         status = cli_chkpath(cli, "\\chkpath.dir");
5849         if (!NT_STATUS_IS_OK(status)) {
5850                 printf("chkpath1 failed: %s\n", nt_errstr(status));
5851                 ret = False;
5852         }
5853
5854         status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
5855         if (!NT_STATUS_IS_OK(status)) {
5856                 printf("chkpath2 failed: %s\n", nt_errstr(status));
5857                 ret = False;
5858         }
5859
5860         status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
5861         if (!NT_STATUS_IS_OK(status)) {
5862                 ret = check_error(__LINE__, cli, ERRDOS, ERRbadpath, 
5863                                   NT_STATUS_NOT_A_DIRECTORY);
5864         } else {
5865                 printf("* chkpath on a file should fail\n");
5866                 ret = False;
5867         }
5868
5869         if (!NT_STATUS_IS_OK(cli_chkpath(cli, "\\chkpath.dir\\bar.txt"))) {
5870                 ret = check_error(__LINE__, cli, ERRDOS, ERRbadfile, 
5871                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
5872         } else {
5873                 printf("* chkpath on a non existant file should fail\n");
5874                 ret = False;
5875         }
5876
5877         if (!NT_STATUS_IS_OK(cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt"))) {
5878                 ret = check_error(__LINE__, cli, ERRDOS, ERRbadpath, 
5879                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
5880         } else {
5881                 printf("* chkpath on a non existent component should fail\n");
5882                 ret = False;
5883         }
5884
5885         cli_rmdir(cli, "\\chkpath.dir\\dir2");
5886         cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5887         cli_rmdir(cli, "\\chkpath.dir");
5888
5889         if (!torture_close_connection(cli)) {
5890                 return False;
5891         }
5892
5893         return ret;
5894 }
5895
5896 static bool run_eatest(int dummy)
5897 {
5898         static struct cli_state *cli;
5899         const char *fname = "\\eatest.txt";
5900         bool correct = True;
5901         uint16_t fnum;
5902         int i;
5903         size_t num_eas;
5904         struct ea_struct *ea_list = NULL;
5905         TALLOC_CTX *mem_ctx = talloc_init("eatest");
5906         NTSTATUS status;
5907
5908         printf("starting eatest\n");
5909
5910         if (!torture_open_connection(&cli, 0)) {
5911                 talloc_destroy(mem_ctx);
5912                 return False;
5913         }
5914
5915         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5916
5917         status = cli_ntcreate(cli, fname, 0,
5918                               FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
5919                               FILE_SHARE_NONE, FILE_OVERWRITE_IF,
5920                               0x4044, 0, &fnum);
5921         if (!NT_STATUS_IS_OK(status)) {
5922                 printf("open failed - %s\n", nt_errstr(status));
5923                 talloc_destroy(mem_ctx);
5924                 return False;
5925         }
5926
5927         for (i = 0; i < 10; i++) {
5928                 fstring ea_name, ea_val;
5929
5930                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
5931                 memset(ea_val, (char)i+1, i+1);
5932                 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
5933                 if (!NT_STATUS_IS_OK(status)) {
5934                         printf("ea_set of name %s failed - %s\n", ea_name,
5935                                nt_errstr(status));
5936                         talloc_destroy(mem_ctx);
5937                         return False;
5938                 }
5939         }
5940
5941         cli_close(cli, fnum);
5942         for (i = 0; i < 10; i++) {
5943                 fstring ea_name, ea_val;
5944
5945                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
5946                 memset(ea_val, (char)i+1, i+1);
5947                 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
5948                 if (!NT_STATUS_IS_OK(status)) {
5949                         printf("ea_set of name %s failed - %s\n", ea_name,
5950                                nt_errstr(status));
5951                         talloc_destroy(mem_ctx);
5952                         return False;
5953                 }
5954         }
5955
5956         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
5957         if (!NT_STATUS_IS_OK(status)) {
5958                 printf("ea_get list failed - %s\n", nt_errstr(status));
5959                 correct = False;
5960         }
5961
5962         printf("num_eas = %d\n", (int)num_eas);
5963
5964         if (num_eas != 20) {
5965                 printf("Should be 20 EA's stored... failing.\n");
5966                 correct = False;
5967         }
5968
5969         for (i = 0; i < num_eas; i++) {
5970                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
5971                 dump_data(0, ea_list[i].value.data,
5972                           ea_list[i].value.length);
5973         }
5974
5975         /* Setting EA's to zero length deletes them. Test this */
5976         printf("Now deleting all EA's - case indepenent....\n");
5977
5978 #if 1
5979         cli_set_ea_path(cli, fname, "", "", 0);
5980 #else
5981         for (i = 0; i < 20; i++) {
5982                 fstring ea_name;
5983                 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
5984                 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
5985                 if (!NT_STATUS_IS_OK(status)) {
5986                         printf("ea_set of name %s failed - %s\n", ea_name,
5987                                nt_errstr(status));
5988                         talloc_destroy(mem_ctx);
5989                         return False;
5990                 }
5991         }
5992 #endif
5993
5994         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
5995         if (!NT_STATUS_IS_OK(status)) {
5996                 printf("ea_get list failed - %s\n", nt_errstr(status));
5997                 correct = False;
5998         }
5999
6000         printf("num_eas = %d\n", (int)num_eas);
6001         for (i = 0; i < num_eas; i++) {
6002                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6003                 dump_data(0, ea_list[i].value.data,
6004                           ea_list[i].value.length);
6005         }
6006
6007         if (num_eas != 0) {
6008                 printf("deleting EA's failed.\n");
6009                 correct = False;
6010         }
6011
6012         /* Try and delete a non existant EA. */
6013         status = cli_set_ea_path(cli, fname, "foo", "", 0);
6014         if (!NT_STATUS_IS_OK(status)) {
6015                 printf("deleting non-existant EA 'foo' should succeed. %s\n",
6016                        nt_errstr(status));
6017                 correct = False;
6018         }
6019
6020         talloc_destroy(mem_ctx);
6021         if (!torture_close_connection(cli)) {
6022                 correct = False;
6023         }
6024
6025         return correct;
6026 }
6027
6028 static bool run_dirtest1(int dummy)
6029 {
6030         int i;
6031         static struct cli_state *cli;
6032         uint16_t fnum;
6033         int num_seen;
6034         bool correct = True;
6035
6036         printf("starting directory test\n");
6037
6038         if (!torture_open_connection(&cli, 0)) {
6039                 return False;
6040         }
6041
6042         cli_sockopt(cli, sockops);
6043
6044         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6045         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6046         cli_rmdir(cli, "\\LISTDIR");
6047         cli_mkdir(cli, "\\LISTDIR");
6048
6049         /* Create 1000 files and 1000 directories. */
6050         for (i=0;i<1000;i++) {
6051                 fstring fname;
6052                 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
6053                 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6054                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum))) {
6055                         fprintf(stderr,"Failed to open %s\n", fname);
6056                         return False;
6057                 }
6058                 cli_close(cli, fnum);
6059         }
6060         for (i=0;i<1000;i++) {
6061                 fstring fname;
6062                 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
6063                 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
6064                         fprintf(stderr,"Failed to open %s\n", fname);
6065                         return False;
6066                 }
6067         }
6068
6069         /* Now ensure that doing an old list sees both files and directories. */
6070         num_seen = 0;
6071         cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6072         printf("num_seen = %d\n", num_seen );
6073         /* We should see 100 files + 1000 directories + . and .. */
6074         if (num_seen != 2002)
6075                 correct = False;
6076
6077         /* Ensure if we have the "must have" bits we only see the
6078          * relevent entries.
6079          */
6080         num_seen = 0;
6081         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6082         printf("num_seen = %d\n", num_seen );
6083         if (num_seen != 1002)
6084                 correct = False;
6085
6086         num_seen = 0;
6087         cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6088         printf("num_seen = %d\n", num_seen );
6089         if (num_seen != 1000)
6090                 correct = False;
6091
6092         /* Delete everything. */
6093         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6094         cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6095         cli_rmdir(cli, "\\LISTDIR");
6096
6097 #if 0
6098         printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
6099         printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
6100         printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
6101 #endif
6102
6103         if (!torture_close_connection(cli)) {
6104                 correct = False;
6105         }
6106
6107         printf("finished dirtest1\n");
6108
6109         return correct;
6110 }
6111
6112 static bool run_error_map_extract(int dummy) {
6113
6114         static struct cli_state *c_dos;
6115         static struct cli_state *c_nt;
6116         NTSTATUS status;
6117
6118         uint32 error;
6119
6120         uint32 flgs2, errnum;
6121         uint8 errclass;
6122
6123         NTSTATUS nt_status;
6124
6125         fstring user;
6126
6127         /* NT-Error connection */
6128
6129         if (!(c_nt = open_nbt_connection())) {
6130                 return False;
6131         }
6132
6133         c_nt->use_spnego = False;
6134
6135         status = cli_negprot(c_nt);
6136
6137         if (!NT_STATUS_IS_OK(status)) {
6138                 printf("%s rejected the NT-error negprot (%s)\n", host,
6139                        nt_errstr(status));
6140                 cli_shutdown(c_nt);
6141                 return False;
6142         }
6143
6144         status = cli_session_setup(c_nt, "", "", 0, "", 0, workgroup);
6145         if (!NT_STATUS_IS_OK(status)) {
6146                 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
6147                 return False;
6148         }
6149
6150         /* DOS-Error connection */
6151
6152         if (!(c_dos = open_nbt_connection())) {
6153                 return False;
6154         }
6155
6156         c_dos->use_spnego = False;
6157         c_dos->force_dos_errors = True;
6158
6159         status = cli_negprot(c_dos);
6160         if (!NT_STATUS_IS_OK(status)) {
6161                 printf("%s rejected the DOS-error negprot (%s)\n", host,
6162                        nt_errstr(status));
6163                 cli_shutdown(c_dos);
6164                 return False;
6165         }
6166
6167         status = cli_session_setup(c_dos, "", "", 0, "", 0, workgroup);
6168         if (!NT_STATUS_IS_OK(status)) {
6169                 printf("%s rejected the DOS-error initial session setup (%s)\n",
6170                         host, nt_errstr(status));
6171                 return False;
6172         }
6173
6174         for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
6175                 fstr_sprintf(user, "%X", error);
6176
6177                 status = cli_session_setup(c_nt, user,
6178                                            password, strlen(password),
6179                                            password, strlen(password),
6180                                            workgroup);
6181                 if (NT_STATUS_IS_OK(status)) {
6182                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
6183                 }
6184
6185                 flgs2 = SVAL(c_nt->inbuf,smb_flg2);
6186
6187                 /* Case #1: 32-bit NT errors */
6188                 if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) {
6189                         nt_status = NT_STATUS(IVAL(c_nt->inbuf,smb_rcls));
6190                 } else {
6191                         printf("/** Dos error on NT connection! (%s) */\n", 
6192                                cli_errstr(c_nt));
6193                         nt_status = NT_STATUS(0xc0000000);
6194                 }
6195
6196                 if (NT_STATUS_IS_OK(cli_session_setup(c_dos, user, 
6197                                                       password, strlen(password),
6198                                                       password, strlen(password),
6199                                                       workgroup))) {
6200                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
6201                 }
6202                 flgs2 = SVAL(c_dos->inbuf,smb_flg2), errnum;
6203
6204                 /* Case #1: 32-bit NT errors */
6205                 if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) {
6206                         printf("/** NT error on DOS connection! (%s) */\n", 
6207                                cli_errstr(c_nt));
6208                         errnum = errclass = 0;
6209                 } else {
6210                         cli_dos_error(c_dos, &errclass, &errnum);
6211                 }
6212
6213                 if (NT_STATUS_V(nt_status) != error) { 
6214                         printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n", 
6215                                get_nt_error_c_code(talloc_tos(), NT_STATUS(error)), 
6216                                get_nt_error_c_code(talloc_tos(), nt_status));
6217                 }
6218
6219                 printf("\t{%s,\t%s,\t%s},\n", 
6220                        smb_dos_err_class(errclass), 
6221                        smb_dos_err_name(errclass, errnum), 
6222                        get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
6223         }
6224         return True;
6225 }
6226
6227 static bool run_sesssetup_bench(int dummy)
6228 {
6229         static struct cli_state *c;
6230         const char *fname = "\\file.dat";
6231         uint16_t fnum;
6232         NTSTATUS status;
6233         int i;
6234
6235         if (!torture_open_connection(&c, 0)) {
6236                 return false;
6237         }
6238
6239         status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6240                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6241                               FILE_DELETE_ON_CLOSE, 0, &fnum);
6242         if (!NT_STATUS_IS_OK(status)) {
6243                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
6244                 return false;
6245         }
6246
6247         for (i=0; i<torture_numops; i++) {
6248                 status = cli_session_setup(
6249                         c, username,
6250                         password, strlen(password),
6251                         password, strlen(password),
6252                         workgroup);
6253                 if (!NT_STATUS_IS_OK(status)) {
6254                         d_printf("(%s) cli_session_setup failed: %s\n",
6255                                  __location__, nt_errstr(status));
6256                         return false;
6257                 }
6258
6259                 d_printf("\r%d   ", (int)c->vuid);
6260
6261                 status = cli_ulogoff(c);
6262                 if (!NT_STATUS_IS_OK(status)) {
6263                         d_printf("(%s) cli_ulogoff failed: %s\n",
6264                                  __location__, nt_errstr(status));
6265                         return false;
6266                 }
6267                 c->vuid = 0;
6268         }
6269
6270         return true;
6271 }
6272
6273 static bool subst_test(const char *str, const char *user, const char *domain,
6274                        uid_t uid, gid_t gid, const char *expected)
6275 {
6276         char *subst;
6277         bool result = true;
6278
6279         subst = talloc_sub_specified(talloc_tos(), str, user, domain, uid, gid);
6280
6281         if (strcmp(subst, expected) != 0) {
6282                 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
6283                        "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
6284                        expected);
6285                 result = false;
6286         }
6287
6288         TALLOC_FREE(subst);
6289         return result;
6290 }
6291
6292 static void chain1_open_completion(struct tevent_req *req)
6293 {
6294         uint16_t fnum;
6295         NTSTATUS status;
6296         status = cli_open_recv(req, &fnum);
6297         TALLOC_FREE(req);
6298
6299         d_printf("cli_open_recv returned %s: %d\n",
6300                  nt_errstr(status),
6301                  NT_STATUS_IS_OK(status) ? fnum : -1);
6302 }
6303
6304 static void chain1_write_completion(struct tevent_req *req)
6305 {
6306         size_t written;
6307         NTSTATUS status;
6308         status = cli_write_andx_recv(req, &written);
6309         TALLOC_FREE(req);
6310
6311         d_printf("cli_write_andx_recv returned %s: %d\n",
6312                  nt_errstr(status),
6313                  NT_STATUS_IS_OK(status) ? (int)written : -1);
6314 }
6315
6316 static void chain1_close_completion(struct tevent_req *req)
6317 {
6318         NTSTATUS status;
6319         bool *done = (bool *)tevent_req_callback_data_void(req);
6320
6321         status = cli_close_recv(req);
6322         *done = true;
6323
6324         TALLOC_FREE(req);
6325
6326         d_printf("cli_close returned %s\n", nt_errstr(status));
6327 }
6328
6329 static bool run_chain1(int dummy)
6330 {
6331         struct cli_state *cli1;
6332         struct event_context *evt = event_context_init(NULL);
6333         struct tevent_req *reqs[3], *smbreqs[3];
6334         bool done = false;
6335         const char *str = "foobar";
6336         NTSTATUS status;
6337
6338         printf("starting chain1 test\n");
6339         if (!torture_open_connection(&cli1, 0)) {
6340                 return False;
6341         }
6342
6343         cli_sockopt(cli1, sockops);
6344
6345         reqs[0] = cli_open_create(talloc_tos(), evt, cli1, "\\test",
6346                                   O_CREAT|O_RDWR, 0, &smbreqs[0]);
6347         if (reqs[0] == NULL) return false;
6348         tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
6349
6350
6351         reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
6352                                         (const uint8_t *)str, 0, strlen(str)+1,
6353                                         smbreqs, 1, &smbreqs[1]);
6354         if (reqs[1] == NULL) return false;
6355         tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
6356
6357         reqs[2] = cli_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
6358         if (reqs[2] == NULL) return false;
6359         tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
6360
6361         status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
6362         if (!NT_STATUS_IS_OK(status)) {
6363                 return false;
6364         }
6365
6366         while (!done) {
6367                 event_loop_once(evt);
6368         }
6369
6370         torture_close_connection(cli1);
6371         return True;
6372 }
6373
6374 static void chain2_sesssetup_completion(struct tevent_req *req)
6375 {
6376         NTSTATUS status;
6377         status = cli_session_setup_guest_recv(req);
6378         d_printf("sesssetup returned %s\n", nt_errstr(status));
6379 }
6380
6381 static void chain2_tcon_completion(struct tevent_req *req)
6382 {
6383         bool *done = (bool *)tevent_req_callback_data_void(req);
6384         NTSTATUS status;
6385         status = cli_tcon_andx_recv(req);
6386         d_printf("tcon_and_x returned %s\n", nt_errstr(status));
6387         *done = true;
6388 }
6389
6390 static bool run_chain2(int dummy)
6391 {
6392         struct cli_state *cli1;
6393         struct event_context *evt = event_context_init(NULL);
6394         struct tevent_req *reqs[2], *smbreqs[2];
6395         bool done = false;
6396         NTSTATUS status;
6397
6398         printf("starting chain2 test\n");
6399         status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
6400                                       port_to_use, Undefined, 0);
6401         if (!NT_STATUS_IS_OK(status)) {
6402                 return False;
6403         }
6404
6405         cli_sockopt(cli1, sockops);
6406
6407         reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
6408                                                  &smbreqs[0]);
6409         if (reqs[0] == NULL) return false;
6410         tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
6411
6412         reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
6413                                        "?????", NULL, 0, &smbreqs[1]);
6414         if (reqs[1] == NULL) return false;
6415         tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
6416
6417         status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
6418         if (!NT_STATUS_IS_OK(status)) {
6419                 return false;
6420         }
6421
6422         while (!done) {
6423                 event_loop_once(evt);
6424         }
6425
6426         torture_close_connection(cli1);
6427         return True;
6428 }
6429
6430
6431 struct torture_createdel_state {
6432         struct tevent_context *ev;
6433         struct cli_state *cli;
6434 };
6435
6436 static void torture_createdel_created(struct tevent_req *subreq);
6437 static void torture_createdel_closed(struct tevent_req *subreq);
6438
6439 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
6440                                                  struct tevent_context *ev,
6441                                                  struct cli_state *cli,
6442                                                  const char *name)
6443 {
6444         struct tevent_req *req, *subreq;
6445         struct torture_createdel_state *state;
6446
6447         req = tevent_req_create(mem_ctx, &state,
6448                                 struct torture_createdel_state);
6449         if (req == NULL) {
6450                 return NULL;
6451         }
6452         state->ev = ev;
6453         state->cli = cli;
6454
6455         subreq = cli_ntcreate_send(
6456                 state, ev, cli, name, 0,
6457                 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
6458                 FILE_ATTRIBUTE_NORMAL,
6459                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6460                 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
6461
6462         if (tevent_req_nomem(subreq, req)) {
6463                 return tevent_req_post(req, ev);
6464         }
6465         tevent_req_set_callback(subreq, torture_createdel_created, req);
6466         return req;
6467 }
6468
6469 static void torture_createdel_created(struct tevent_req *subreq)
6470 {
6471         struct tevent_req *req = tevent_req_callback_data(
6472                 subreq, struct tevent_req);
6473         struct torture_createdel_state *state = tevent_req_data(
6474                 req, struct torture_createdel_state);
6475         NTSTATUS status;
6476         uint16_t fnum;
6477
6478         status = cli_ntcreate_recv(subreq, &fnum);
6479         TALLOC_FREE(subreq);
6480         if (!NT_STATUS_IS_OK(status)) {
6481                 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
6482                            nt_errstr(status)));
6483                 tevent_req_nterror(req, status);
6484                 return;
6485         }
6486
6487         subreq = cli_close_send(state, state->ev, state->cli, fnum);
6488         if (tevent_req_nomem(subreq, req)) {
6489                 return;
6490         }
6491         tevent_req_set_callback(subreq, torture_createdel_closed, req);
6492 }
6493
6494 static void torture_createdel_closed(struct tevent_req *subreq)
6495 {
6496         struct tevent_req *req = tevent_req_callback_data(
6497                 subreq, struct tevent_req);
6498         NTSTATUS status;
6499
6500         status = cli_close_recv(subreq);
6501         if (!NT_STATUS_IS_OK(status)) {
6502                 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
6503                 tevent_req_nterror(req, status);
6504                 return;
6505         }
6506         tevent_req_done(req);
6507 }
6508
6509 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
6510 {
6511         return tevent_req_simple_recv_ntstatus(req);
6512 }
6513
6514 struct torture_createdels_state {
6515         struct tevent_context *ev;
6516         struct cli_state *cli;
6517         const char *base_name;
6518         int sent;
6519         int received;
6520         int num_files;
6521         struct tevent_req **reqs;
6522 };
6523
6524 static void torture_createdels_done(struct tevent_req *subreq);
6525
6526 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
6527                                                   struct tevent_context *ev,
6528                                                   struct cli_state *cli,
6529                                                   const char *base_name,
6530                                                   int num_parallel,
6531                                                   int num_files)
6532 {
6533         struct tevent_req *req;
6534         struct torture_createdels_state *state;
6535         int i;
6536
6537         req = tevent_req_create(mem_ctx, &state,
6538                                 struct torture_createdels_state);
6539         if (req == NULL) {
6540                 return NULL;
6541         }
6542         state->ev = ev;
6543         state->cli = cli;
6544         state->base_name = talloc_strdup(state, base_name);
6545         if (tevent_req_nomem(state->base_name, req)) {
6546                 return tevent_req_post(req, ev);
6547         }
6548         state->num_files = MAX(num_parallel, num_files);
6549         state->sent = 0;
6550         state->received = 0;
6551
6552         state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
6553         if (tevent_req_nomem(state->reqs, req)) {
6554                 return tevent_req_post(req, ev);
6555         }
6556
6557         for (i=0; i<num_parallel; i++) {
6558                 char *name;
6559
6560                 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6561                                        state->sent);
6562                 if (tevent_req_nomem(name, req)) {
6563                         return tevent_req_post(req, ev);
6564                 }
6565                 state->reqs[i] = torture_createdel_send(
6566                         state->reqs, state->ev, state->cli, name);
6567                 if (tevent_req_nomem(state->reqs[i], req)) {
6568                         return tevent_req_post(req, ev);
6569                 }
6570                 name = talloc_move(state->reqs[i], &name);
6571                 tevent_req_set_callback(state->reqs[i],
6572                                         torture_createdels_done, req);
6573                 state->sent += 1;
6574         }
6575         return req;
6576 }
6577
6578 static void torture_createdels_done(struct tevent_req *subreq)
6579 {
6580         struct tevent_req *req = tevent_req_callback_data(
6581                 subreq, struct tevent_req);
6582         struct torture_createdels_state *state = tevent_req_data(
6583                 req, struct torture_createdels_state);
6584         size_t num_parallel = talloc_array_length(state->reqs);
6585         NTSTATUS status;
6586         char *name;
6587         int i;
6588
6589         status = torture_createdel_recv(subreq);
6590         if (!NT_STATUS_IS_OK(status)){
6591                 DEBUG(10, ("torture_createdel_recv returned %s\n",
6592                            nt_errstr(status)));
6593                 TALLOC_FREE(subreq);
6594                 tevent_req_nterror(req, status);
6595                 return;
6596         }
6597
6598         for (i=0; i<num_parallel; i++) {
6599                 if (subreq == state->reqs[i]) {
6600                         break;
6601                 }
6602         }
6603         if (i == num_parallel) {
6604                 DEBUG(10, ("received something we did not send\n"));
6605                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
6606                 return;
6607         }
6608         TALLOC_FREE(state->reqs[i]);
6609
6610         if (state->sent >= state->num_files) {
6611                 tevent_req_done(req);
6612                 return;
6613         }
6614
6615         name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6616                                state->sent);
6617         if (tevent_req_nomem(name, req)) {
6618                 return;
6619         }
6620         state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
6621                                                 state->cli, name);
6622         if (tevent_req_nomem(state->reqs[i], req)) {
6623                 return;
6624         }
6625         name = talloc_move(state->reqs[i], &name);
6626         tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
6627         state->sent += 1;
6628 }
6629
6630 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
6631 {
6632         return tevent_req_simple_recv_ntstatus(req);
6633 }
6634
6635 struct swallow_notify_state {
6636         struct tevent_context *ev;
6637         struct cli_state *cli;
6638         uint16_t fnum;
6639         uint32_t completion_filter;
6640         bool recursive;
6641         bool (*fn)(uint32_t action, const char *name, void *priv);
6642         void *priv;
6643 };
6644
6645 static void swallow_notify_done(struct tevent_req *subreq);
6646
6647 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
6648                                               struct tevent_context *ev,
6649                                               struct cli_state *cli,
6650                                               uint16_t fnum,
6651                                               uint32_t completion_filter,
6652                                               bool recursive,
6653                                               bool (*fn)(uint32_t action,
6654                                                          const char *name,
6655                                                          void *priv),
6656                                               void *priv)
6657 {
6658         struct tevent_req *req, *subreq;
6659         struct swallow_notify_state *state;
6660
6661         req = tevent_req_create(mem_ctx, &state,
6662                                 struct swallow_notify_state);
6663         if (req == NULL) {
6664                 return NULL;
6665         }
6666         state->ev = ev;
6667         state->cli = cli;
6668         state->fnum = fnum;
6669         state->completion_filter = completion_filter;
6670         state->recursive = recursive;
6671         state->fn = fn;
6672         state->priv = priv;
6673
6674         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6675                                  0xffff, state->completion_filter,
6676                                  state->recursive);
6677         if (tevent_req_nomem(subreq, req)) {
6678                 return tevent_req_post(req, ev);
6679         }
6680         tevent_req_set_callback(subreq, swallow_notify_done, req);
6681         return req;
6682 }
6683
6684 static void swallow_notify_done(struct tevent_req *subreq)
6685 {
6686         struct tevent_req *req = tevent_req_callback_data(
6687                 subreq, struct tevent_req);
6688         struct swallow_notify_state *state = tevent_req_data(
6689                 req, struct swallow_notify_state);
6690         NTSTATUS status;
6691         uint32_t i, num_changes;
6692         struct notify_change *changes;
6693
6694         status = cli_notify_recv(subreq, state, &num_changes, &changes);
6695         TALLOC_FREE(subreq);
6696         if (!NT_STATUS_IS_OK(status)) {
6697                 DEBUG(10, ("cli_notify_recv returned %s\n",
6698                            nt_errstr(status)));
6699                 tevent_req_nterror(req, status);
6700                 return;
6701         }
6702
6703         for (i=0; i<num_changes; i++) {
6704                 state->fn(changes[i].action, changes[i].name, state->priv);
6705         }
6706         TALLOC_FREE(changes);
6707
6708         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6709                                  0xffff, state->completion_filter,
6710                                  state->recursive);
6711         if (tevent_req_nomem(subreq, req)) {
6712                 return;
6713         }
6714         tevent_req_set_callback(subreq, swallow_notify_done, req);
6715 }
6716
6717 static bool print_notifies(uint32_t action, const char *name, void *priv)
6718 {
6719         if (DEBUGLEVEL > 5) {
6720                 d_printf("%d %s\n", (int)action, name);
6721         }
6722         return true;
6723 }
6724
6725 static void notify_bench_done(struct tevent_req *req)
6726 {
6727         int *num_finished = (int *)tevent_req_callback_data_void(req);
6728         *num_finished += 1;
6729 }
6730
6731 static bool run_notify_bench(int dummy)
6732 {
6733         const char *dname = "\\notify-bench";
6734         struct tevent_context *ev;
6735         NTSTATUS status;
6736         uint16_t dnum;
6737         struct tevent_req *req1;
6738         struct tevent_req *req2 = NULL;
6739         int i, num_unc_names;
6740         int num_finished = 0;
6741
6742         printf("starting notify-bench test\n");
6743
6744         if (use_multishare_conn) {
6745                 char **unc_list;
6746                 unc_list = file_lines_load(multishare_conn_fname,
6747                                            &num_unc_names, 0, NULL);
6748                 if (!unc_list || num_unc_names <= 0) {
6749                         d_printf("Failed to load unc names list from '%s'\n",
6750                                  multishare_conn_fname);
6751                         return false;
6752                 }
6753                 TALLOC_FREE(unc_list);
6754         } else {
6755                 num_unc_names = 1;
6756         }
6757
6758         ev = tevent_context_init(talloc_tos());
6759         if (ev == NULL) {
6760                 d_printf("tevent_context_init failed\n");
6761                 return false;
6762         }
6763
6764         for (i=0; i<num_unc_names; i++) {
6765                 struct cli_state *cli;
6766                 char *base_fname;
6767
6768                 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
6769                                              dname, i);
6770                 if (base_fname == NULL) {
6771                         return false;
6772                 }
6773
6774                 if (!torture_open_connection(&cli, i)) {
6775                         return false;
6776                 }
6777
6778                 status = cli_ntcreate(cli, dname, 0,
6779                                       MAXIMUM_ALLOWED_ACCESS,
6780                                       0, FILE_SHARE_READ|FILE_SHARE_WRITE|
6781                                       FILE_SHARE_DELETE,
6782                                       FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
6783                                       &dnum);
6784
6785                 if (!NT_STATUS_IS_OK(status)) {
6786                         d_printf("Could not create %s: %s\n", dname,
6787                                  nt_errstr(status));
6788                         return false;
6789                 }
6790
6791                 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
6792                                            FILE_NOTIFY_CHANGE_FILE_NAME |
6793                                            FILE_NOTIFY_CHANGE_DIR_NAME |
6794                                            FILE_NOTIFY_CHANGE_ATTRIBUTES |
6795                                            FILE_NOTIFY_CHANGE_LAST_WRITE,
6796                                            false, print_notifies, NULL);
6797                 if (req1 == NULL) {
6798                         d_printf("Could not create notify request\n");
6799                         return false;
6800                 }
6801
6802                 req2 = torture_createdels_send(talloc_tos(), ev, cli,
6803                                                base_fname, 10, torture_numops);
6804                 if (req2 == NULL) {
6805                         d_printf("Could not create createdels request\n");
6806                         return false;
6807                 }
6808                 TALLOC_FREE(base_fname);
6809
6810                 tevent_req_set_callback(req2, notify_bench_done,
6811                                         &num_finished);
6812         }
6813
6814         while (num_finished < num_unc_names) {
6815                 int ret;
6816                 ret = tevent_loop_once(ev);
6817                 if (ret != 0) {
6818                         d_printf("tevent_loop_once failed\n");
6819                         return false;
6820                 }
6821         }
6822
6823         if (!tevent_req_poll(req2, ev)) {
6824                 d_printf("tevent_req_poll failed\n");
6825         }
6826
6827         status = torture_createdels_recv(req2);
6828         d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
6829
6830         return true;
6831 }
6832
6833 static bool run_mangle1(int dummy)
6834 {
6835         struct cli_state *cli;
6836         const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
6837         uint16_t fnum;
6838         fstring alt_name;
6839         NTSTATUS status;
6840         time_t change_time, access_time, write_time;
6841         SMB_OFF_T size;
6842         uint16_t mode;
6843
6844         printf("starting mangle1 test\n");
6845         if (!torture_open_connection(&cli, 0)) {
6846                 return False;
6847         }
6848
6849         cli_sockopt(cli, sockops);
6850
6851         status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6852                               FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6853                               0, 0, &fnum);
6854         if (!NT_STATUS_IS_OK(status)) {
6855                 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
6856                 return false;
6857         }
6858         cli_close(cli, fnum);
6859
6860         status = cli_qpathinfo_alt_name(cli, fname, alt_name);
6861         if (!NT_STATUS_IS_OK(status)) {
6862                 d_printf("cli_qpathinfo_alt_name failed: %s\n",
6863                          nt_errstr(status));
6864                 return false;
6865         }
6866         d_printf("alt_name: %s\n", alt_name);
6867
6868         status = cli_open(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
6869         if (!NT_STATUS_IS_OK(status)) {
6870                 d_printf("cli_open(%s) failed: %s\n", alt_name,
6871                          nt_errstr(status));
6872                 return false;
6873         }
6874         cli_close(cli, fnum);
6875
6876         status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
6877                                 &write_time, &size, &mode);
6878         if (!NT_STATUS_IS_OK(status)) {
6879                 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
6880                          nt_errstr(status));
6881                 return false;
6882         }
6883
6884         return true;
6885 }
6886
6887 static size_t null_source(uint8_t *buf, size_t n, void *priv)
6888 {
6889         size_t *to_pull = (size_t *)priv;
6890         size_t thistime = *to_pull;
6891
6892         thistime = MIN(thistime, n);
6893         if (thistime == 0) {
6894                 return 0;
6895         }
6896
6897         memset(buf, 0, thistime);
6898         *to_pull -= thistime;
6899         return thistime;
6900 }
6901
6902 static bool run_windows_write(int dummy)
6903 {
6904         struct cli_state *cli1;
6905         uint16_t fnum;
6906         int i;
6907         bool ret = false;
6908         const char *fname = "\\writetest.txt";
6909         struct timeval start_time;
6910         double seconds;
6911         double kbytes;
6912         NTSTATUS status;
6913
6914         printf("starting windows_write test\n");
6915         if (!torture_open_connection(&cli1, 0)) {
6916                 return False;
6917         }
6918
6919         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6920         if (!NT_STATUS_IS_OK(status)) {
6921                 printf("open failed (%s)\n", nt_errstr(status));
6922                 return False;
6923         }
6924
6925         cli_sockopt(cli1, sockops);
6926
6927         start_time = timeval_current();
6928
6929         for (i=0; i<torture_numops; i++) {
6930                 uint8_t c = 0;
6931                 off_t start = i * torture_blocksize;
6932                 size_t to_pull = torture_blocksize - 1;
6933
6934                 status = cli_writeall(cli1, fnum, 0, &c,
6935                                       start + torture_blocksize - 1, 1, NULL);
6936                 if (!NT_STATUS_IS_OK(status)) {
6937                         printf("cli_write failed: %s\n", nt_errstr(status));
6938                         goto fail;
6939                 }
6940
6941                 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
6942                                   null_source, &to_pull);
6943                 if (!NT_STATUS_IS_OK(status)) {
6944                         printf("cli_push returned: %s\n", nt_errstr(status));
6945                         goto fail;
6946                 }
6947         }
6948
6949         seconds = timeval_elapsed(&start_time);
6950         kbytes = (double)torture_blocksize * torture_numops;
6951         kbytes /= 1024;
6952
6953         printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
6954                (double)seconds, (int)(kbytes/seconds));
6955
6956         ret = true;
6957  fail:
6958         cli_close(cli1, fnum);
6959         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6960         torture_close_connection(cli1);
6961         return ret;
6962 }
6963
6964 static bool run_cli_echo(int dummy)
6965 {
6966         struct cli_state *cli;
6967         NTSTATUS status;
6968
6969         printf("starting cli_echo test\n");
6970         if (!torture_open_connection(&cli, 0)) {
6971                 return false;
6972         }
6973         cli_sockopt(cli, sockops);
6974
6975         status = cli_echo(cli, 5, data_blob_const("hello", 5));
6976
6977         d_printf("cli_echo returned %s\n", nt_errstr(status));
6978
6979         torture_close_connection(cli);
6980         return NT_STATUS_IS_OK(status);
6981 }
6982
6983 static bool run_uid_regression_test(int dummy)
6984 {
6985         static struct cli_state *cli;
6986         int16_t old_vuid;
6987         int16_t old_cnum;
6988         bool correct = True;
6989         NTSTATUS status;
6990
6991         printf("starting uid regression test\n");
6992
6993         if (!torture_open_connection(&cli, 0)) {
6994                 return False;
6995         }
6996
6997         cli_sockopt(cli, sockops);
6998
6999         /* Ok - now save then logoff our current user. */
7000         old_vuid = cli->vuid;
7001
7002         status = cli_ulogoff(cli);
7003         if (!NT_STATUS_IS_OK(status)) {
7004                 d_printf("(%s) cli_ulogoff failed: %s\n",
7005                          __location__, nt_errstr(status));
7006                 correct = false;
7007                 goto out;
7008         }
7009
7010         cli->vuid = old_vuid;
7011
7012         /* Try an operation. */
7013         status = cli_mkdir(cli, "\\uid_reg_test");
7014         if (NT_STATUS_IS_OK(status)) {
7015                 d_printf("(%s) cli_mkdir succeeded\n",
7016                          __location__);
7017                 correct = false;
7018                 goto out;
7019         } else {
7020                 /* Should be bad uid. */
7021                 if (!check_error(__LINE__, cli, ERRSRV, ERRbaduid,
7022                                 NT_STATUS_USER_SESSION_DELETED)) {
7023                         correct = false;
7024                         goto out;
7025                 }
7026         }
7027
7028         old_cnum = cli->cnum;
7029
7030         /* Now try a SMBtdis with the invald vuid set to zero. */
7031         cli->vuid = 0;
7032
7033         /* This should succeed. */
7034         status = cli_tdis(cli);
7035
7036         if (NT_STATUS_IS_OK(status)) {
7037                 d_printf("First tdis with invalid vuid should succeed.\n");
7038         } else {
7039                 d_printf("First tdis failed (%s)\n", nt_errstr(status));
7040                 correct = false;
7041                 goto out;
7042         }
7043
7044         cli->vuid = old_vuid;
7045         cli->cnum = old_cnum;
7046
7047         /* This should fail. */
7048         status = cli_tdis(cli);
7049         if (NT_STATUS_IS_OK(status)) {
7050                 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
7051                 correct = false;
7052                 goto out;
7053         } else {
7054                 /* Should be bad tid. */
7055                 if (!check_error(__LINE__, cli, ERRSRV, ERRinvnid,
7056                                 NT_STATUS_NETWORK_NAME_DELETED)) {
7057                         correct = false;
7058                         goto out;
7059                 }
7060         }
7061
7062         cli_rmdir(cli, "\\uid_reg_test");
7063
7064   out:
7065
7066         cli_shutdown(cli);
7067         return correct;
7068 }
7069
7070
7071 static const char *illegal_chars = "*\\/?<>|\":";
7072 static char force_shortname_chars[] = " +,.[];=\177";
7073
7074 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
7075                              const char *mask, void *state)
7076 {
7077         struct cli_state *pcli = (struct cli_state *)state;
7078         fstring fname;
7079         NTSTATUS status = NT_STATUS_OK;
7080
7081         slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
7082
7083         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
7084                 return NT_STATUS_OK;
7085
7086         if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
7087                 status = cli_rmdir(pcli, fname);
7088                 if (!NT_STATUS_IS_OK(status)) {
7089                         printf("del_fn: failed to rmdir %s\n,", fname );
7090                 }
7091         } else {
7092                 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7093                 if (!NT_STATUS_IS_OK(status)) {
7094                         printf("del_fn: failed to unlink %s\n,", fname );
7095                 }
7096         }
7097         return status;
7098 }
7099
7100 struct sn_state {
7101         int matched;
7102         int i;
7103         bool val;
7104 };
7105
7106 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
7107                               const char *name, void *state)
7108 {
7109         struct sn_state *s = (struct sn_state  *)state;
7110         int i = s->i;
7111
7112 #if 0
7113         printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
7114                 i, finfo->name, finfo->short_name);
7115 #endif
7116
7117         if (strchr(force_shortname_chars, i)) {
7118                 if (!finfo->short_name) {
7119                         /* Shortname not created when it should be. */
7120                         d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
7121                                 __location__, finfo->name, i);
7122                         s->val = true;
7123                 }
7124         } else if (finfo->short_name){
7125                 /* Shortname created when it should not be. */
7126                 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
7127                         __location__, finfo->short_name, finfo->name);
7128                 s->val = true;
7129         }
7130         s->matched += 1;
7131         return NT_STATUS_OK;
7132 }
7133
7134 static bool run_shortname_test(int dummy)
7135 {
7136         static struct cli_state *cli;
7137         bool correct = True;
7138         int i;
7139         struct sn_state s;
7140         char fname[20];
7141         NTSTATUS status;
7142
7143         printf("starting shortname test\n");
7144
7145         if (!torture_open_connection(&cli, 0)) {
7146                 return False;
7147         }
7148
7149         cli_sockopt(cli, sockops);
7150
7151         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7152         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7153         cli_rmdir(cli, "\\shortname");
7154
7155         status = cli_mkdir(cli, "\\shortname");
7156         if (!NT_STATUS_IS_OK(status)) {
7157                 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
7158                         __location__, nt_errstr(status));
7159                 correct = false;
7160                 goto out;
7161         }
7162
7163         strlcpy(fname, "\\shortname\\", sizeof(fname));
7164         strlcat(fname, "test .txt", sizeof(fname));
7165
7166         s.val = false;
7167
7168         for (i = 32; i < 128; i++) {
7169                 uint16_t fnum = (uint16_t)-1;
7170
7171                 s.i = i;
7172
7173                 if (strchr(illegal_chars, i)) {
7174                         continue;
7175                 }
7176                 fname[15] = i;
7177
7178                 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
7179                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum);
7180                 if (!NT_STATUS_IS_OK(status)) {
7181                         d_printf("(%s) cli_nt_create of %s failed: %s\n",
7182                                 __location__, fname, nt_errstr(status));
7183                         correct = false;
7184                         goto out;
7185                 }
7186                 cli_close(cli, fnum);
7187
7188                 s.matched = 0;
7189                 cli_list(cli, "\\shortname\\test*.*", 0, shortname_list_fn,
7190                          &s);
7191                 if (s.matched != 1) {
7192                         d_printf("(%s) failed to list %s: %s\n",
7193                                 __location__, fname, cli_errstr(cli));
7194                         correct = false;
7195                         goto out;
7196                 }
7197
7198                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7199                 if (!NT_STATUS_IS_OK(status)) {
7200                         d_printf("(%s) failed to delete %s: %s\n",
7201                                 __location__, fname, nt_errstr(status));
7202                         correct = false;
7203                         goto out;
7204                 }
7205
7206                 if (s.val) {
7207                         correct = false;
7208                         goto out;
7209                 }
7210         }
7211
7212   out:
7213
7214         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7215         cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7216         cli_rmdir(cli, "\\shortname");
7217         torture_close_connection(cli);
7218         return correct;
7219 }
7220
7221 static void pagedsearch_cb(struct tevent_req *req)
7222 {
7223         int rc;
7224         struct tldap_message *msg;
7225         char *dn;
7226
7227         rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
7228         if (rc != TLDAP_SUCCESS) {
7229                 d_printf("tldap_search_paged_recv failed: %s\n",
7230                          tldap_err2string(rc));
7231                 return;
7232         }
7233         if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
7234                 TALLOC_FREE(msg);
7235                 return;
7236         }
7237         if (!tldap_entry_dn(msg, &dn)) {
7238                 d_printf("tldap_entry_dn failed\n");
7239                 return;
7240         }
7241         d_printf("%s\n", dn);
7242         TALLOC_FREE(msg);
7243 }
7244
7245 static bool run_tldap(int dummy)
7246 {
7247         struct tldap_context *ld;
7248         int fd, rc;
7249         NTSTATUS status;
7250         struct sockaddr_storage addr;
7251         struct tevent_context *ev;
7252         struct tevent_req *req;
7253         char *basedn;
7254         const char *filter;
7255
7256         if (!resolve_name(host, &addr, 0, false)) {
7257                 d_printf("could not find host %s\n", host);
7258                 return false;
7259         }
7260         status = open_socket_out(&addr, 389, 9999, &fd);
7261         if (!NT_STATUS_IS_OK(status)) {
7262                 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
7263                 return false;
7264         }
7265
7266         ld = tldap_context_create(talloc_tos(), fd);
7267         if (ld == NULL) {
7268                 close(fd);
7269                 d_printf("tldap_context_create failed\n");
7270                 return false;
7271         }
7272
7273         rc = tldap_fetch_rootdse(ld);
7274         if (rc != TLDAP_SUCCESS) {
7275                 d_printf("tldap_fetch_rootdse failed: %s\n",
7276                          tldap_errstr(talloc_tos(), ld, rc));
7277                 return false;
7278         }
7279
7280         basedn = tldap_talloc_single_attribute(
7281                 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
7282         if (basedn == NULL) {
7283                 d_printf("no defaultNamingContext\n");
7284                 return false;
7285         }
7286         d_printf("defaultNamingContext: %s\n", basedn);
7287
7288         ev = tevent_context_init(talloc_tos());
7289         if (ev == NULL) {
7290                 d_printf("tevent_context_init failed\n");
7291                 return false;
7292         }
7293
7294         req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
7295                                       TLDAP_SCOPE_SUB, "(objectclass=*)",
7296                                       NULL, 0, 0,
7297                                       NULL, 0, NULL, 0, 0, 0, 0, 5);
7298         if (req == NULL) {
7299                 d_printf("tldap_search_paged_send failed\n");
7300                 return false;
7301         }
7302         tevent_req_set_callback(req, pagedsearch_cb, NULL);
7303
7304         tevent_req_poll(req, ev);
7305
7306         TALLOC_FREE(req);
7307
7308         /* test search filters against rootDSE */
7309         filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
7310                    "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
7311
7312         rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
7313                           NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
7314                           talloc_tos(), NULL, NULL);
7315         if (rc != TLDAP_SUCCESS) {
7316                 d_printf("tldap_search with complex filter failed: %s\n",
7317                          tldap_errstr(talloc_tos(), ld, rc));
7318                 return false;
7319         }
7320
7321         TALLOC_FREE(ld);
7322         return true;
7323 }
7324
7325 /* Torture test to ensure no regression of :
7326 https://bugzilla.samba.org/show_bug.cgi?id=7084
7327 */
7328
7329 static bool run_dir_createtime(int dummy)
7330 {
7331         struct cli_state *cli;
7332         const char *dname = "\\testdir";
7333         const char *fname = "\\testdir\\testfile";
7334         NTSTATUS status;
7335         struct timespec create_time;
7336         struct timespec create_time1;
7337         uint16_t fnum;
7338         bool ret = false;
7339
7340         if (!torture_open_connection(&cli, 0)) {
7341                 return false;
7342         }
7343
7344         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7345         cli_rmdir(cli, dname);
7346
7347         status = cli_mkdir(cli, dname);
7348         if (!NT_STATUS_IS_OK(status)) {
7349                 printf("mkdir failed: %s\n", nt_errstr(status));
7350                 goto out;
7351         }
7352
7353         status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
7354                                 NULL, NULL, NULL);
7355         if (!NT_STATUS_IS_OK(status)) {
7356                 printf("cli_qpathinfo2 returned %s\n",
7357                        nt_errstr(status));
7358                 goto out;
7359         }
7360
7361         /* Sleep 3 seconds, then create a file. */
7362         sleep(3);
7363
7364         status = cli_open(cli, fname, O_RDWR | O_CREAT | O_EXCL,
7365                          DENY_NONE, &fnum);
7366         if (!NT_STATUS_IS_OK(status)) {
7367                 printf("cli_open failed: %s\n", nt_errstr(status));
7368                 goto out;
7369         }
7370
7371         status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
7372                                 NULL, NULL, NULL);
7373         if (!NT_STATUS_IS_OK(status)) {
7374                 printf("cli_qpathinfo2 (2) returned %s\n",
7375                        nt_errstr(status));
7376                 goto out;
7377         }
7378
7379         if (timespec_compare(&create_time1, &create_time)) {
7380                 printf("run_dir_createtime: create time was updated (error)\n");
7381         } else {
7382                 printf("run_dir_createtime: create time was not updated (correct)\n");
7383                 ret = true;
7384         }
7385
7386   out:
7387
7388         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7389         cli_rmdir(cli, dname);
7390         if (!torture_close_connection(cli)) {
7391                 ret = false;
7392         }
7393         return ret;
7394 }
7395
7396
7397 static bool run_streamerror(int dummy)
7398 {
7399         struct cli_state *cli;
7400         const char *dname = "\\testdir";
7401         const char *streamname =
7402                 "testdir:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
7403         NTSTATUS status;
7404         time_t change_time, access_time, write_time;
7405         SMB_OFF_T size;
7406         uint16_t mode, fnum;
7407         bool ret = true;
7408
7409         if (!torture_open_connection(&cli, 0)) {
7410                 return false;
7411         }
7412
7413         cli_unlink(cli, "\\testdir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7414         cli_rmdir(cli, dname);
7415
7416         status = cli_mkdir(cli, dname);
7417         if (!NT_STATUS_IS_OK(status)) {
7418                 printf("mkdir failed: %s\n", nt_errstr(status));
7419                 return false;
7420         }
7421
7422         cli_qpathinfo1(cli, streamname, &change_time, &access_time, &write_time,
7423                       &size, &mode);
7424         status = cli_nt_error(cli);
7425
7426         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7427                 printf("pathinfo returned %s, expected "
7428                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
7429                        nt_errstr(status));
7430                 ret = false;
7431         }
7432
7433         status = cli_ntcreate(cli, streamname, 0x16,
7434                               FILE_READ_DATA|FILE_READ_EA|
7435                               FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
7436                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7437                               FILE_OPEN, 0, 0, &fnum);
7438
7439         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7440                 printf("ntcreate returned %s, expected "
7441                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
7442                        nt_errstr(status));
7443                 ret = false;
7444         }
7445
7446
7447         cli_rmdir(cli, dname);
7448         return ret;
7449 }
7450
7451 static bool run_local_substitute(int dummy)
7452 {
7453         bool ok = true;
7454
7455         ok &= subst_test("%U", "bla", "", -1, -1, "bla");
7456         ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
7457         ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
7458         ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
7459         ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
7460         ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
7461         ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
7462         ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
7463
7464         /* Different captialization rules in sub_basic... */
7465
7466         ok &=  (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
7467                        "blaDOM") == 0);
7468
7469         return ok;
7470 }
7471
7472 static bool run_local_base64(int dummy)
7473 {
7474         int i;
7475         bool ret = true;
7476
7477         for (i=1; i<2000; i++) {
7478                 DATA_BLOB blob1, blob2;
7479                 char *b64;
7480
7481                 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
7482                 blob1.length = i;
7483                 generate_random_buffer(blob1.data, blob1.length);
7484
7485                 b64 = base64_encode_data_blob(talloc_tos(), blob1);
7486                 if (b64 == NULL) {
7487                         d_fprintf(stderr, "base64_encode_data_blob failed "
7488                                   "for %d bytes\n", i);
7489                         ret = false;
7490                 }
7491                 blob2 = base64_decode_data_blob(b64);
7492                 TALLOC_FREE(b64);
7493
7494                 if (data_blob_cmp(&blob1, &blob2)) {
7495                         d_fprintf(stderr, "data_blob_cmp failed for %d "
7496                                   "bytes\n", i);
7497                         ret = false;
7498                 }
7499                 TALLOC_FREE(blob1.data);
7500                 data_blob_free(&blob2);
7501         }
7502         return ret;
7503 }
7504
7505 static bool run_local_gencache(int dummy)
7506 {
7507         char *val;
7508         time_t tm;
7509         DATA_BLOB blob;
7510
7511         if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
7512                 d_printf("%s: gencache_set() failed\n", __location__);
7513                 return False;
7514         }
7515
7516         if (!gencache_get("foo", NULL, NULL)) {
7517                 d_printf("%s: gencache_get() failed\n", __location__);
7518                 return False;
7519         }
7520
7521         if (!gencache_get("foo", &val, &tm)) {
7522                 d_printf("%s: gencache_get() failed\n", __location__);
7523                 return False;
7524         }
7525
7526         if (strcmp(val, "bar") != 0) {
7527                 d_printf("%s: gencache_get() returned %s, expected %s\n",
7528                          __location__, val, "bar");
7529                 SAFE_FREE(val);
7530                 return False;
7531         }
7532
7533         SAFE_FREE(val);
7534
7535         if (!gencache_del("foo")) {
7536                 d_printf("%s: gencache_del() failed\n", __location__);
7537                 return False;
7538         }
7539         if (gencache_del("foo")) {
7540                 d_printf("%s: second gencache_del() succeeded\n",
7541                          __location__);
7542                 return False;
7543         }
7544
7545         if (gencache_get("foo", &val, &tm)) {
7546                 d_printf("%s: gencache_get() on deleted entry "
7547                          "succeeded\n", __location__);
7548                 return False;
7549         }
7550
7551         blob = data_blob_string_const_null("bar");
7552         tm = time(NULL) + 60;
7553
7554         if (!gencache_set_data_blob("foo", &blob, tm)) {
7555                 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
7556                 return False;
7557         }
7558
7559         if (!gencache_get_data_blob("foo", &blob, NULL, NULL)) {
7560                 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
7561                 return False;
7562         }
7563
7564         if (strcmp((const char *)blob.data, "bar") != 0) {
7565                 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
7566                          __location__, (const char *)blob.data, "bar");
7567                 data_blob_free(&blob);
7568                 return False;
7569         }
7570
7571         data_blob_free(&blob);
7572
7573         if (!gencache_del("foo")) {
7574                 d_printf("%s: gencache_del() failed\n", __location__);
7575                 return False;
7576         }
7577         if (gencache_del("foo")) {
7578                 d_printf("%s: second gencache_del() succeeded\n",
7579                          __location__);
7580                 return False;
7581         }
7582
7583         if (gencache_get_data_blob("foo", &blob, NULL, NULL)) {
7584                 d_printf("%s: gencache_get_data_blob() on deleted entry "
7585                          "succeeded\n", __location__);
7586                 return False;
7587         }
7588
7589         return True;
7590 }
7591
7592 static bool rbt_testval(struct db_context *db, const char *key,
7593                         const char *value)
7594 {
7595         struct db_record *rec;
7596         TDB_DATA data = string_tdb_data(value);
7597         bool ret = false;
7598         NTSTATUS status;
7599
7600         rec = db->fetch_locked(db, db, string_tdb_data(key));
7601         if (rec == NULL) {
7602                 d_fprintf(stderr, "fetch_locked failed\n");
7603                 goto done;
7604         }
7605         status = rec->store(rec, data, 0);
7606         if (!NT_STATUS_IS_OK(status)) {
7607                 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
7608                 goto done;
7609         }
7610         TALLOC_FREE(rec);
7611
7612         rec = db->fetch_locked(db, db, string_tdb_data(key));
7613         if (rec == NULL) {
7614                 d_fprintf(stderr, "second fetch_locked failed\n");
7615                 goto done;
7616         }
7617         if ((rec->value.dsize != data.dsize)
7618             || (memcmp(rec->value.dptr, data.dptr, data.dsize) != 0)) {
7619                 d_fprintf(stderr, "Got wrong data back\n");
7620                 goto done;
7621         }
7622
7623         ret = true;
7624  done:
7625         TALLOC_FREE(rec);
7626         return ret;
7627 }
7628
7629 static bool run_local_rbtree(int dummy)
7630 {
7631         struct db_context *db;
7632         bool ret = false;
7633         int i;
7634
7635         db = db_open_rbt(NULL);
7636
7637         if (db == NULL) {
7638                 d_fprintf(stderr, "db_open_rbt failed\n");
7639                 return false;
7640         }
7641
7642         for (i=0; i<1000; i++) {
7643                 char *key, *value;
7644
7645                 if (asprintf(&key, "key%ld", random()) == -1) {
7646                         goto done;
7647                 }
7648                 if (asprintf(&value, "value%ld", random()) == -1) {
7649                         SAFE_FREE(key);
7650                         goto done;
7651                 }
7652
7653                 if (!rbt_testval(db, key, value)) {
7654                         SAFE_FREE(key);
7655                         SAFE_FREE(value);
7656                         goto done;
7657                 }
7658
7659                 SAFE_FREE(value);
7660                 if (asprintf(&value, "value%ld", random()) == -1) {
7661                         SAFE_FREE(key);
7662                         goto done;
7663                 }
7664
7665                 if (!rbt_testval(db, key, value)) {
7666                         SAFE_FREE(key);
7667                         SAFE_FREE(value);
7668                         goto done;
7669                 }
7670
7671                 SAFE_FREE(key);
7672                 SAFE_FREE(value);
7673         }
7674
7675         ret = true;
7676
7677  done:
7678         TALLOC_FREE(db);
7679         return ret;
7680 }
7681
7682
7683 /*
7684   local test for character set functions
7685
7686   This is a very simple test for the functionality in convert_string_error()
7687  */
7688 static bool run_local_convert_string(int dummy)
7689 {
7690         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
7691         const char *test_strings[2] = { "March", "M\303\244rz" };
7692         char dst[7];
7693         int i;
7694
7695         for (i=0; i<2; i++) {
7696                 const char *str = test_strings[i];
7697                 int len = strlen(str);
7698                 size_t converted_size;
7699                 bool ret;
7700
7701                 memset(dst, 'X', sizeof(dst));
7702
7703                 /* first try with real source length */
7704                 ret = convert_string_error(CH_UNIX, CH_UTF8,
7705                                            str, len,
7706                                            dst, sizeof(dst),
7707                                            &converted_size);
7708                 if (ret != true) {
7709                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
7710                         goto failed;
7711                 }
7712
7713                 if (converted_size != len) {
7714                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
7715                                   str, len, (int)converted_size);
7716                         goto failed;
7717                 }
7718
7719                 if (strncmp(str, dst, converted_size) != 0) {
7720                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
7721                         goto failed;
7722                 }
7723
7724                 if (strlen(str) != converted_size) {
7725                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
7726                                   (int)strlen(str), (int)converted_size);
7727                         goto failed;
7728                 }
7729
7730                 if (dst[converted_size] != 'X') {
7731                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
7732                         goto failed;
7733                 }
7734
7735                 /* now with srclen==-1, this causes the nul to be
7736                  * converted too */
7737                 ret = convert_string_error(CH_UNIX, CH_UTF8,
7738                                            str, -1,
7739                                            dst, sizeof(dst),
7740                                            &converted_size);
7741                 if (ret != true) {
7742                         d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
7743                         goto failed;
7744                 }
7745
7746                 if (converted_size != len+1) {
7747                         d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
7748                                   str, len, (int)converted_size);
7749                         goto failed;
7750                 }
7751
7752                 if (strncmp(str, dst, converted_size) != 0) {
7753                         d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
7754                         goto failed;
7755                 }
7756
7757                 if (len+1 != converted_size) {
7758                         d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
7759                                   len+1, (int)converted_size);
7760                         goto failed;
7761                 }
7762
7763                 if (dst[converted_size] != 'X') {
7764                         d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
7765                         goto failed;
7766                 }
7767
7768         }
7769
7770
7771         TALLOC_FREE(tmp_ctx);
7772         return true;
7773 failed:
7774         TALLOC_FREE(tmp_ctx);
7775         return false;
7776 }
7777
7778
7779 struct talloc_dict_test {
7780         int content;
7781 };
7782
7783 static int talloc_dict_traverse_fn(DATA_BLOB key, void *data, void *priv)
7784 {
7785         int *count = (int *)priv;
7786         *count += 1;
7787         return 0;
7788 }
7789
7790 static bool run_local_talloc_dict(int dummy)
7791 {
7792         struct talloc_dict *dict;
7793         struct talloc_dict_test *t;
7794         int key, count;
7795
7796         dict = talloc_dict_init(talloc_tos());
7797         if (dict == NULL) {
7798                 return false;
7799         }
7800
7801         t = talloc(talloc_tos(), struct talloc_dict_test);
7802         if (t == NULL) {
7803                 return false;
7804         }
7805
7806         key = 1;
7807         t->content = 1;
7808         if (!talloc_dict_set(dict, data_blob_const(&key, sizeof(key)), t)) {
7809                 return false;
7810         }
7811
7812         count = 0;
7813         if (talloc_dict_traverse(dict, talloc_dict_traverse_fn, &count) != 0) {
7814                 return false;
7815         }
7816
7817         if (count != 1) {
7818                 return false;
7819         }
7820
7821         TALLOC_FREE(dict);
7822
7823         return true;
7824 }
7825
7826 static bool run_local_string_to_sid(int dummy) {
7827         struct dom_sid sid;
7828
7829         if (string_to_sid(&sid, "S--1-5-32-545")) {
7830                 printf("allowing S--1-5-32-545\n");
7831                 return false;
7832         }
7833         if (string_to_sid(&sid, "S-1-5-32-+545")) {
7834                 printf("allowing S-1-5-32-+545\n");
7835                 return false;
7836         }
7837         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")) {
7838                 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
7839                 return false;
7840         }
7841         if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
7842                 printf("allowing S-1-5-32-545-abc\n");
7843                 return false;
7844         }
7845         if (!string_to_sid(&sid, "S-1-5-32-545")) {
7846                 printf("could not parse S-1-5-32-545\n");
7847                 return false;
7848         }
7849         if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
7850                 printf("mis-parsed S-1-5-32-545 as %s\n",
7851                        sid_string_tos(&sid));
7852                 return false;
7853         }
7854         return true;
7855 }
7856
7857 static bool run_local_binary_to_sid(int dummy) {
7858         struct dom_sid *sid = talloc(NULL, struct dom_sid);
7859         static const char good_binary_sid[] = {
7860                 0x1, /* revision number */
7861                 15, /* num auths */
7862                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
7863                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
7864                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
7865                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
7866                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
7867                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
7868                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
7869                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
7870                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
7871                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
7872                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
7873                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
7874                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
7875                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
7876                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
7877                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
7878         };
7879
7880         static const char long_binary_sid[] = {
7881                 0x1, /* revision number */
7882                 15, /* num auths */
7883                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
7884                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
7885                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
7886                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
7887                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
7888                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
7889                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
7890                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
7891                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
7892                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
7893                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
7894                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
7895                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
7896                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
7897                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
7898                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
7899                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
7900                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
7901                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
7902         };
7903
7904         static const char long_binary_sid2[] = {
7905                 0x1, /* revision number */
7906                 32, /* num auths */
7907                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
7908                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
7909                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
7910                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
7911                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
7912                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
7913                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
7914                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
7915                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
7916                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
7917                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
7918                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
7919                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
7920                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
7921                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
7922                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
7923                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
7924                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
7925                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
7926                 0x1, 0x1, 0x1, 0x1, /* auth[18] */
7927                 0x1, 0x1, 0x1, 0x1, /* auth[19] */
7928                 0x1, 0x1, 0x1, 0x1, /* auth[20] */
7929                 0x1, 0x1, 0x1, 0x1, /* auth[21] */
7930                 0x1, 0x1, 0x1, 0x1, /* auth[22] */
7931                 0x1, 0x1, 0x1, 0x1, /* auth[23] */
7932                 0x1, 0x1, 0x1, 0x1, /* auth[24] */
7933                 0x1, 0x1, 0x1, 0x1, /* auth[25] */
7934                 0x1, 0x1, 0x1, 0x1, /* auth[26] */
7935                 0x1, 0x1, 0x1, 0x1, /* auth[27] */
7936                 0x1, 0x1, 0x1, 0x1, /* auth[28] */
7937                 0x1, 0x1, 0x1, 0x1, /* auth[29] */
7938                 0x1, 0x1, 0x1, 0x1, /* auth[30] */
7939                 0x1, 0x1, 0x1, 0x1, /* auth[31] */
7940         };
7941
7942         if (!sid_parse(good_binary_sid, sizeof(good_binary_sid), sid)) {
7943                 return false;
7944         }
7945         if (sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid)) {
7946                 return false;
7947         }
7948         if (sid_parse(long_binary_sid, sizeof(long_binary_sid), sid)) {
7949                 return false;
7950         }
7951         return true;
7952 }
7953
7954 /* Split a path name into filename and stream name components. Canonicalise
7955  * such that an implicit $DATA token is always explicit.
7956  *
7957  * The "specification" of this function can be found in the
7958  * run_local_stream_name() function in torture.c, I've tried those
7959  * combinations against a W2k3 server.
7960  */
7961
7962 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
7963                                        char **pbase, char **pstream)
7964 {
7965         char *base = NULL;
7966         char *stream = NULL;
7967         char *sname; /* stream name */
7968         const char *stype; /* stream type */
7969
7970         DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
7971
7972         sname = strchr_m(fname, ':');
7973
7974         if (lp_posix_pathnames() || (sname == NULL)) {
7975                 if (pbase != NULL) {
7976                         base = talloc_strdup(mem_ctx, fname);
7977                         NT_STATUS_HAVE_NO_MEMORY(base);
7978                 }
7979                 goto done;
7980         }
7981
7982         if (pbase != NULL) {
7983                 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
7984                 NT_STATUS_HAVE_NO_MEMORY(base);
7985         }
7986
7987         sname += 1;
7988
7989         stype = strchr_m(sname, ':');
7990
7991         if (stype == NULL) {
7992                 sname = talloc_strdup(mem_ctx, sname);
7993                 stype = "$DATA";
7994         }
7995         else {
7996                 if (strcasecmp_m(stype, ":$DATA") != 0) {
7997                         /*
7998                          * If there is an explicit stream type, so far we only
7999                          * allow $DATA. Is there anything else allowed? -- vl
8000                          */
8001                         DEBUG(10, ("[%s] is an invalid stream type\n", stype));
8002                         TALLOC_FREE(base);
8003                         return NT_STATUS_OBJECT_NAME_INVALID;
8004                 }
8005                 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
8006                 stype += 1;
8007         }
8008
8009         if (sname == NULL) {
8010                 TALLOC_FREE(base);
8011                 return NT_STATUS_NO_MEMORY;
8012         }
8013
8014         if (sname[0] == '\0') {
8015                 /*
8016                  * no stream name, so no stream
8017                  */
8018                 goto done;
8019         }
8020
8021         if (pstream != NULL) {
8022                 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
8023                 if (stream == NULL) {
8024                         TALLOC_FREE(sname);
8025                         TALLOC_FREE(base);
8026                         return NT_STATUS_NO_MEMORY;
8027                 }
8028                 /*
8029                  * upper-case the type field
8030                  */
8031                 strupper_m(strchr_m(stream, ':')+1);
8032         }
8033
8034  done:
8035         if (pbase != NULL) {
8036                 *pbase = base;
8037         }
8038         if (pstream != NULL) {
8039                 *pstream = stream;
8040         }
8041         return NT_STATUS_OK;
8042 }
8043
8044 static bool test_stream_name(const char *fname, const char *expected_base,
8045                              const char *expected_stream,
8046                              NTSTATUS expected_status)
8047 {
8048         NTSTATUS status;
8049         char *base = NULL;
8050         char *stream = NULL;
8051
8052         status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
8053         if (!NT_STATUS_EQUAL(status, expected_status)) {
8054                 goto error;
8055         }
8056
8057         if (!NT_STATUS_IS_OK(status)) {
8058                 return true;
8059         }
8060
8061         if (base == NULL) goto error;
8062
8063         if (strcmp(expected_base, base) != 0) goto error;
8064
8065         if ((expected_stream != NULL) && (stream == NULL)) goto error;
8066         if ((expected_stream == NULL) && (stream != NULL)) goto error;
8067
8068         if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
8069                 goto error;
8070
8071         TALLOC_FREE(base);
8072         TALLOC_FREE(stream);
8073         return true;
8074
8075  error:
8076         d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
8077                   fname, expected_base ? expected_base : "<NULL>",
8078                   expected_stream ? expected_stream : "<NULL>",
8079                   nt_errstr(expected_status));
8080         d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
8081                   base ? base : "<NULL>", stream ? stream : "<NULL>",
8082                   nt_errstr(status));
8083         TALLOC_FREE(base);
8084         TALLOC_FREE(stream);
8085         return false;
8086 }
8087
8088 static bool run_local_stream_name(int dummy)
8089 {
8090         bool ret = true;
8091
8092         ret &= test_stream_name(
8093                 "bla", "bla", NULL, NT_STATUS_OK);
8094         ret &= test_stream_name(
8095                 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
8096         ret &= test_stream_name(
8097                 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8098         ret &= test_stream_name(
8099                 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
8100         ret &= test_stream_name(
8101                 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8102         ret &= test_stream_name(
8103                 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
8104         ret &= test_stream_name(
8105                 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
8106         ret &= test_stream_name(
8107                 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
8108
8109         return ret;
8110 }
8111
8112 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
8113 {
8114         if (a.length != b.length) {
8115                 printf("a.length=%d != b.length=%d\n",
8116                        (int)a.length, (int)b.length);
8117                 return false;
8118         }
8119         if (memcmp(a.data, b.data, a.length) != 0) {
8120                 printf("a.data and b.data differ\n");
8121                 return false;
8122         }
8123         return true;
8124 }
8125
8126 static bool run_local_memcache(int dummy)
8127 {
8128         struct memcache *cache;
8129         DATA_BLOB k1, k2;
8130         DATA_BLOB d1, d2, d3;
8131         DATA_BLOB v1, v2, v3;
8132
8133         TALLOC_CTX *mem_ctx;
8134         char *str1, *str2;
8135         size_t size1, size2;
8136         bool ret = false;
8137
8138         cache = memcache_init(NULL, 100);
8139
8140         if (cache == NULL) {
8141                 printf("memcache_init failed\n");
8142                 return false;
8143         }
8144
8145         d1 = data_blob_const("d1", 2);
8146         d2 = data_blob_const("d2", 2);
8147         d3 = data_blob_const("d3", 2);
8148
8149         k1 = data_blob_const("d1", 2);
8150         k2 = data_blob_const("d2", 2);
8151
8152         memcache_add(cache, STAT_CACHE, k1, d1);
8153         memcache_add(cache, GETWD_CACHE, k2, d2);
8154
8155         if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
8156                 printf("could not find k1\n");
8157                 return false;
8158         }
8159         if (!data_blob_equal(d1, v1)) {
8160                 return false;
8161         }
8162
8163         if (!memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8164                 printf("could not find k2\n");
8165                 return false;
8166         }
8167         if (!data_blob_equal(d2, v2)) {
8168                 return false;
8169         }
8170
8171         memcache_add(cache, STAT_CACHE, k1, d3);
8172
8173         if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
8174                 printf("could not find replaced k1\n");
8175                 return false;
8176         }
8177         if (!data_blob_equal(d3, v3)) {
8178                 return false;
8179         }
8180
8181         memcache_add(cache, GETWD_CACHE, k1, d1);
8182
8183         if (memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8184                 printf("Did find k2, should have been purged\n");
8185                 return false;
8186         }
8187
8188         TALLOC_FREE(cache);
8189
8190         cache = memcache_init(NULL, 0);
8191
8192         mem_ctx = talloc_init("foo");
8193
8194         str1 = talloc_strdup(mem_ctx, "string1");
8195         str2 = talloc_strdup(mem_ctx, "string2");
8196
8197         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8198                             data_blob_string_const("torture"), &str1);
8199         size1 = talloc_total_size(cache);
8200
8201         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8202                             data_blob_string_const("torture"), &str2);
8203         size2 = talloc_total_size(cache);
8204
8205         printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
8206
8207         if (size2 > size1) {
8208                 printf("memcache leaks memory!\n");
8209                 goto fail;
8210         }
8211
8212         ret = true;
8213  fail:
8214         TALLOC_FREE(cache);
8215         return ret;
8216 }
8217
8218 static void wbclient_done(struct tevent_req *req)
8219 {
8220         wbcErr wbc_err;
8221         struct winbindd_response *wb_resp;
8222         int *i = (int *)tevent_req_callback_data_void(req);
8223
8224         wbc_err = wb_trans_recv(req, req, &wb_resp);
8225         TALLOC_FREE(req);
8226         *i += 1;
8227         d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
8228 }
8229
8230 static bool run_local_wbclient(int dummy)
8231 {
8232         struct event_context *ev;
8233         struct wb_context **wb_ctx;
8234         struct winbindd_request wb_req;
8235         bool result = false;
8236         int i, j;
8237
8238         BlockSignals(True, SIGPIPE);
8239
8240         ev = tevent_context_init_byname(talloc_tos(), "epoll");
8241         if (ev == NULL) {
8242                 goto fail;
8243         }
8244
8245         wb_ctx = talloc_array(ev, struct wb_context *, nprocs);
8246         if (wb_ctx == NULL) {
8247                 goto fail;
8248         }
8249
8250         ZERO_STRUCT(wb_req);
8251         wb_req.cmd = WINBINDD_PING;
8252
8253         d_printf("nprocs=%d, numops=%d\n", (int)nprocs, (int)torture_numops);
8254
8255         for (i=0; i<nprocs; i++) {
8256                 wb_ctx[i] = wb_context_init(ev, NULL);
8257                 if (wb_ctx[i] == NULL) {
8258                         goto fail;
8259                 }
8260                 for (j=0; j<torture_numops; j++) {
8261                         struct tevent_req *req;
8262                         req = wb_trans_send(ev, ev, wb_ctx[i],
8263                                             (j % 2) == 0, &wb_req);
8264                         if (req == NULL) {
8265                                 goto fail;
8266                         }
8267                         tevent_req_set_callback(req, wbclient_done, &i);
8268                 }
8269         }
8270
8271         i = 0;
8272
8273         while (i < nprocs * torture_numops) {
8274                 event_loop_once(ev);
8275         }
8276
8277         result = true;
8278  fail:
8279         TALLOC_FREE(ev);
8280         return result;
8281 }
8282
8283 static void getaddrinfo_finished(struct tevent_req *req)
8284 {
8285         char *name = (char *)tevent_req_callback_data_void(req);
8286         struct addrinfo *ainfo;
8287         int res;
8288
8289         res = getaddrinfo_recv(req, &ainfo);
8290         if (res != 0) {
8291                 d_printf("gai(%s) returned %s\n", name, gai_strerror(res));
8292                 return;
8293         }
8294         d_printf("gai(%s) succeeded\n", name);
8295         freeaddrinfo(ainfo);
8296 }
8297
8298 static bool run_getaddrinfo_send(int dummy)
8299 {
8300         TALLOC_CTX *frame = talloc_stackframe();
8301         struct fncall_context *ctx;
8302         struct tevent_context *ev;
8303         bool result = false;
8304         const char *names[4] = { "www.samba.org", "notfound.samba.org",
8305                                  "www.slashdot.org", "heise.de" };
8306         struct tevent_req *reqs[4];
8307         int i;
8308
8309         ev = event_context_init(frame);
8310         if (ev == NULL) {
8311                 goto fail;
8312         }
8313
8314         ctx = fncall_context_init(frame, 4);
8315
8316         for (i=0; i<ARRAY_SIZE(names); i++) {
8317                 reqs[i] = getaddrinfo_send(frame, ev, ctx, names[i], NULL,
8318                                            NULL);
8319                 if (reqs[i] == NULL) {
8320                         goto fail;
8321                 }
8322                 tevent_req_set_callback(reqs[i], getaddrinfo_finished,
8323                                         discard_const_p(void, names[i]));
8324         }
8325
8326         for (i=0; i<ARRAY_SIZE(reqs); i++) {
8327                 tevent_loop_once(ev);
8328         }
8329
8330         result = true;
8331 fail:
8332         TALLOC_FREE(frame);
8333         return result;
8334 }
8335
8336 static bool dbtrans_inc(struct db_context *db)
8337 {
8338         struct db_record *rec;
8339         uint32_t *val;
8340         bool ret = false;
8341         NTSTATUS status;
8342
8343         rec = db->fetch_locked(db, db, string_term_tdb_data("transtest"));
8344         if (rec == NULL) {
8345                 printf(__location__ "fetch_lock failed\n");
8346                 return false;
8347         }
8348
8349         if (rec->value.dsize != sizeof(uint32_t)) {
8350                 printf(__location__ "value.dsize = %d\n",
8351                        (int)rec->value.dsize);
8352                 goto fail;
8353         }
8354
8355         val = (uint32_t *)rec->value.dptr;
8356         *val += 1;
8357
8358         status = rec->store(rec, make_tdb_data((uint8_t *)val,
8359                                                sizeof(uint32_t)),
8360                             0);
8361         if (!NT_STATUS_IS_OK(status)) {
8362                 printf(__location__ "store failed: %s\n",
8363                        nt_errstr(status));
8364                 goto fail;
8365         }
8366
8367         ret = true;
8368 fail:
8369         TALLOC_FREE(rec);
8370         return ret;
8371 }
8372
8373 static bool run_local_dbtrans(int dummy)
8374 {
8375         struct db_context *db;
8376         struct db_record *rec;
8377         NTSTATUS status;
8378         uint32_t initial;
8379         int res;
8380
8381         db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
8382                      O_RDWR|O_CREAT, 0600);
8383         if (db == NULL) {
8384                 printf("Could not open transtest.db\n");
8385                 return false;
8386         }
8387
8388         res = db->transaction_start(db);
8389         if (res != 0) {
8390                 printf(__location__ "transaction_start failed\n");
8391                 return false;
8392         }
8393
8394         rec = db->fetch_locked(db, db, string_term_tdb_data("transtest"));
8395         if (rec == NULL) {
8396                 printf(__location__ "fetch_lock failed\n");
8397                 return false;
8398         }
8399
8400         if (rec->value.dptr == NULL) {
8401                 initial = 0;
8402                 status = rec->store(
8403                         rec, make_tdb_data((uint8_t *)&initial,
8404                                            sizeof(initial)),
8405                         0);
8406                 if (!NT_STATUS_IS_OK(status)) {
8407                         printf(__location__ "store returned %s\n",
8408                                nt_errstr(status));
8409                         return false;
8410                 }
8411         }
8412
8413         TALLOC_FREE(rec);
8414
8415         res = db->transaction_commit(db);
8416         if (res != 0) {
8417                 printf(__location__ "transaction_commit failed\n");
8418                 return false;
8419         }
8420
8421         while (true) {
8422                 uint32_t val, val2;
8423                 int i;
8424
8425                 res = db->transaction_start(db);
8426                 if (res != 0) {
8427                         printf(__location__ "transaction_start failed\n");
8428                         break;
8429                 }
8430
8431                 if (!dbwrap_fetch_uint32(db, "transtest", &val)) {
8432                         printf(__location__ "dbwrap_fetch_uint32 failed\n");
8433                         break;
8434                 }
8435
8436                 for (i=0; i<10; i++) {
8437                         if (!dbtrans_inc(db)) {
8438                                 return false;
8439                         }
8440                 }
8441
8442                 if (!dbwrap_fetch_uint32(db, "transtest", &val2)) {
8443                         printf(__location__ "dbwrap_fetch_uint32 failed\n");
8444                         break;
8445                 }
8446
8447                 if (val2 != val + 10) {
8448                         printf(__location__ "val=%d, val2=%d\n",
8449                                (int)val, (int)val2);
8450                         break;
8451                 }
8452
8453                 printf("val2=%d\r", val2);
8454
8455                 res = db->transaction_commit(db);
8456                 if (res != 0) {
8457                         printf(__location__ "transaction_commit failed\n");
8458                         break;
8459                 }
8460         }
8461
8462         TALLOC_FREE(db);
8463         return true;
8464 }
8465
8466 /*
8467  * Just a dummy test to be run under a debugger. There's no real way
8468  * to inspect the tevent_select specific function from outside of
8469  * tevent_select.c.
8470  */
8471
8472 static bool run_local_tevent_select(int dummy)
8473 {
8474         struct tevent_context *ev;
8475         struct tevent_fd *fd1, *fd2;
8476         bool result = false;
8477
8478         ev = tevent_context_init_byname(NULL, "select");
8479         if (ev == NULL) {
8480                 d_fprintf(stderr, "tevent_context_init_byname failed\n");
8481                 goto fail;
8482         }
8483
8484         fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
8485         if (fd1 == NULL) {
8486                 d_fprintf(stderr, "tevent_add_fd failed\n");
8487                 goto fail;
8488         }
8489         fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
8490         if (fd2 == NULL) {
8491                 d_fprintf(stderr, "tevent_add_fd failed\n");
8492                 goto fail;
8493         }
8494         TALLOC_FREE(fd2);
8495
8496         fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
8497         if (fd2 == NULL) {
8498                 d_fprintf(stderr, "tevent_add_fd failed\n");
8499                 goto fail;
8500         }
8501
8502         result = true;
8503 fail:
8504         TALLOC_FREE(ev);
8505         return result;
8506 }
8507
8508 static double create_procs(bool (*fn)(int), bool *result)
8509 {
8510         int i, status;
8511         volatile pid_t *child_status;
8512         volatile bool *child_status_out;
8513         int synccount;
8514         int tries = 8;
8515         struct timeval start;
8516
8517         synccount = 0;
8518
8519         child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*nprocs);
8520         if (!child_status) {
8521                 printf("Failed to setup shared memory\n");
8522                 return -1;
8523         }
8524
8525         child_status_out = (volatile bool *)shm_setup(sizeof(bool)*nprocs);
8526         if (!child_status_out) {
8527                 printf("Failed to setup result status shared memory\n");
8528                 return -1;
8529         }
8530
8531         for (i = 0; i < nprocs; i++) {
8532                 child_status[i] = 0;
8533                 child_status_out[i] = True;
8534         }
8535
8536         start = timeval_current();
8537
8538         for (i=0;i<nprocs;i++) {
8539                 procnum = i;
8540                 if (fork() == 0) {
8541                         pid_t mypid = getpid();
8542                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
8543
8544                         slprintf(myname,sizeof(myname),"CLIENT%d", i);
8545
8546                         while (1) {
8547                                 if (torture_open_connection(&current_cli, i)) break;
8548                                 if (tries-- == 0) {
8549                                         printf("pid %d failed to start\n", (int)getpid());
8550                                         _exit(1);
8551                                 }
8552                                 smb_msleep(10); 
8553                         }
8554
8555                         child_status[i] = getpid();
8556
8557                         while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
8558
8559                         child_status_out[i] = fn(i);
8560                         _exit(0);
8561                 }
8562         }
8563
8564         do {
8565                 synccount = 0;
8566                 for (i=0;i<nprocs;i++) {
8567                         if (child_status[i]) synccount++;
8568                 }
8569                 if (synccount == nprocs) break;
8570                 smb_msleep(10);
8571         } while (timeval_elapsed(&start) < 30);
8572
8573         if (synccount != nprocs) {
8574                 printf("FAILED TO START %d CLIENTS (started %d)\n", nprocs, synccount);
8575                 *result = False;
8576                 return timeval_elapsed(&start);
8577         }
8578
8579         /* start the client load */
8580         start = timeval_current();
8581
8582         for (i=0;i<nprocs;i++) {
8583                 child_status[i] = 0;
8584         }
8585
8586         printf("%d clients started\n", nprocs);
8587
8588         for (i=0;i<nprocs;i++) {
8589                 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
8590         }
8591
8592         printf("\n");
8593
8594         for (i=0;i<nprocs;i++) {
8595                 if (!child_status_out[i]) {
8596                         *result = False;
8597                 }
8598         }
8599         return timeval_elapsed(&start);
8600 }
8601
8602 #define FLAG_MULTIPROC 1
8603
8604 static struct {
8605         const char *name;
8606         bool (*fn)(int);
8607         unsigned flags;
8608 } torture_ops[] = {
8609         {"FDPASS", run_fdpasstest, 0},
8610         {"LOCK1",  run_locktest1,  0},
8611         {"LOCK2",  run_locktest2,  0},
8612         {"LOCK3",  run_locktest3,  0},
8613         {"LOCK4",  run_locktest4,  0},
8614         {"LOCK5",  run_locktest5,  0},
8615         {"LOCK6",  run_locktest6,  0},
8616         {"LOCK7",  run_locktest7,  0},
8617         {"LOCK8",  run_locktest8,  0},
8618         {"LOCK9",  run_locktest9,  0},
8619         {"UNLINK", run_unlinktest, 0},
8620         {"BROWSE", run_browsetest, 0},
8621         {"ATTR",   run_attrtest,   0},
8622         {"TRANS2", run_trans2test, 0},
8623         {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
8624         {"TORTURE",run_torture,    FLAG_MULTIPROC},
8625         {"RANDOMIPC", run_randomipc, 0},
8626         {"NEGNOWAIT", run_negprot_nowait, 0},
8627         {"NBENCH",  run_nbench, 0},
8628         {"NBENCH2", run_nbench2, 0},
8629         {"OPLOCK1",  run_oplock1, 0},
8630         {"OPLOCK2",  run_oplock2, 0},
8631         {"OPLOCK4",  run_oplock4, 0},
8632         {"DIR",  run_dirtest, 0},
8633         {"DIR1",  run_dirtest1, 0},
8634         {"DIR-CREATETIME",  run_dir_createtime, 0},
8635         {"DENY1",  torture_denytest1, 0},
8636         {"DENY2",  torture_denytest2, 0},
8637         {"TCON",  run_tcon_test, 0},
8638         {"TCONDEV",  run_tcon_devtype_test, 0},
8639         {"RW1",  run_readwritetest, 0},
8640         {"RW2",  run_readwritemulti, FLAG_MULTIPROC},
8641         {"RW3",  run_readwritelarge, 0},
8642         {"RW-SIGNING",  run_readwritelarge_signtest, 0},
8643         {"OPEN", run_opentest, 0},
8644         {"POSIX", run_simple_posix_open_test, 0},
8645         {"POSIX-APPEND", run_posix_append, 0},
8646         {"CASE-INSENSITIVE-CREATE", run_case_insensitive_create, 0},
8647         {"ASYNC-ECHO", run_async_echo, 0},
8648         { "UID-REGRESSION-TEST", run_uid_regression_test, 0},
8649         { "SHORTNAME-TEST", run_shortname_test, 0},
8650         { "ADDRCHANGE", run_addrchange, 0},
8651 #if 1
8652         {"OPENATTR", run_openattrtest, 0},
8653 #endif
8654         {"XCOPY", run_xcopy, 0},
8655         {"RENAME", run_rename, 0},
8656         {"DELETE", run_deletetest, 0},
8657         {"DELETE-LN", run_deletetest_ln, 0},
8658         {"PROPERTIES", run_properties, 0},
8659         {"MANGLE", torture_mangle, 0},
8660         {"MANGLE1", run_mangle1, 0},
8661         {"W2K", run_w2ktest, 0},
8662         {"TRANS2SCAN", torture_trans2_scan, 0},
8663         {"NTTRANSSCAN", torture_nttrans_scan, 0},
8664         {"UTABLE", torture_utable, 0},
8665         {"CASETABLE", torture_casetable, 0},
8666         {"ERRMAPEXTRACT", run_error_map_extract, 0},
8667         {"PIPE_NUMBER", run_pipe_number, 0},
8668         {"TCON2",  run_tcon2_test, 0},
8669         {"IOCTL",  torture_ioctl_test, 0},
8670         {"CHKPATH",  torture_chkpath_test, 0},
8671         {"FDSESS", run_fdsesstest, 0},
8672         { "EATEST", run_eatest, 0},
8673         { "SESSSETUP_BENCH", run_sesssetup_bench, 0},
8674         { "CHAIN1", run_chain1, 0},
8675         { "CHAIN2", run_chain2, 0},
8676         { "WINDOWS-WRITE", run_windows_write, 0},
8677         { "NTTRANS-CREATE", run_nttrans_create, 0},
8678         { "CLI_ECHO", run_cli_echo, 0},
8679         { "GETADDRINFO", run_getaddrinfo_send, 0},
8680         { "TLDAP", run_tldap },
8681         { "STREAMERROR", run_streamerror },
8682         { "NOTIFY-BENCH", run_notify_bench },
8683         { "BAD-NBT-SESSION", run_bad_nbt_session },
8684         { "SMB-ANY-CONNECT", run_smb_any_connect },
8685         { "NOTIFY-ONLINE", run_notify_online },
8686         { "LOCAL-SUBSTITUTE", run_local_substitute, 0},
8687         { "LOCAL-GENCACHE", run_local_gencache, 0},
8688         { "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0},
8689         { "LOCAL-BASE64", run_local_base64, 0},
8690         { "LOCAL-RBTREE", run_local_rbtree, 0},
8691         { "LOCAL-MEMCACHE", run_local_memcache, 0},
8692         { "LOCAL-STREAM-NAME", run_local_stream_name, 0},
8693         { "LOCAL-WBCLIENT", run_local_wbclient, 0},
8694         { "LOCAL-string_to_sid", run_local_string_to_sid, 0},
8695         { "LOCAL-binary_to_sid", run_local_binary_to_sid, 0},
8696         { "LOCAL-DBTRANS", run_local_dbtrans, 0},
8697         { "LOCAL-TEVENT-SELECT", run_local_tevent_select, 0},
8698         { "LOCAL-CONVERT-STRING", run_local_convert_string, 0},
8699         {NULL, NULL, 0}};
8700
8701
8702
8703 /****************************************************************************
8704 run a specified test or "ALL"
8705 ****************************************************************************/
8706 static bool run_test(const char *name)
8707 {
8708         bool ret = True;
8709         bool result = True;
8710         bool found = False;
8711         int i;
8712         double t;
8713         if (strequal(name,"ALL")) {
8714                 for (i=0;torture_ops[i].name;i++) {
8715                         run_test(torture_ops[i].name);
8716                 }
8717                 found = True;
8718         }
8719
8720         for (i=0;torture_ops[i].name;i++) {
8721                 fstr_sprintf(randomfname, "\\XX%x", 
8722                          (unsigned)random());
8723
8724                 if (strequal(name, torture_ops[i].name)) {
8725                         found = True;
8726                         printf("Running %s\n", name);
8727                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
8728                                 t = create_procs(torture_ops[i].fn, &result);
8729                                 if (!result) { 
8730                                         ret = False;
8731                                         printf("TEST %s FAILED!\n", name);
8732                                 }
8733                         } else {
8734                                 struct timeval start;
8735                                 start = timeval_current();
8736                                 if (!torture_ops[i].fn(0)) {
8737                                         ret = False;
8738                                         printf("TEST %s FAILED!\n", name);
8739                                 }
8740                                 t = timeval_elapsed(&start);
8741                         }
8742                         printf("%s took %g secs\n\n", name, t);
8743                 }
8744         }
8745
8746         if (!found) {
8747                 printf("Did not find a test named %s\n", name);
8748                 ret = False;
8749         }
8750
8751         return ret;
8752 }
8753
8754
8755 static void usage(void)
8756 {
8757         int i;
8758
8759         printf("WARNING samba4 test suite is much more complete nowadays.\n");
8760         printf("Please use samba4 torture.\n\n");
8761
8762         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
8763
8764         printf("\t-d debuglevel\n");
8765         printf("\t-U user%%pass\n");
8766         printf("\t-k               use kerberos\n");
8767         printf("\t-N numprocs\n");
8768         printf("\t-n my_netbios_name\n");
8769         printf("\t-W workgroup\n");
8770         printf("\t-o num_operations\n");
8771         printf("\t-O socket_options\n");
8772         printf("\t-m maximum protocol\n");
8773         printf("\t-L use oplocks\n");
8774         printf("\t-c CLIENT.TXT   specify client load file for NBENCH\n");
8775         printf("\t-A showall\n");
8776         printf("\t-p port\n");
8777         printf("\t-s seed\n");
8778         printf("\t-b unclist_filename   specify multiple shares for multiple connections\n");
8779         printf("\t-f filename   filename to test\n");
8780         printf("\n\n");
8781
8782         printf("tests are:");
8783         for (i=0;torture_ops[i].name;i++) {
8784                 printf(" %s", torture_ops[i].name);
8785         }
8786         printf("\n");
8787
8788         printf("default test is ALL\n");
8789
8790         exit(1);
8791 }
8792
8793 /****************************************************************************
8794   main program
8795 ****************************************************************************/
8796  int main(int argc,char *argv[])
8797 {
8798         int opt, i;
8799         char *p;
8800         int gotuser = 0;
8801         int gotpass = 0;
8802         bool correct = True;
8803         TALLOC_CTX *frame = talloc_stackframe();
8804         int seed = time(NULL);
8805
8806 #ifdef HAVE_SETBUFFER
8807         setbuffer(stdout, NULL, 0);
8808 #endif
8809
8810         setup_logging("smbtorture", DEBUG_STDOUT);
8811
8812         load_case_tables();
8813
8814         if (is_default_dyn_CONFIGFILE()) {
8815                 if(getenv("SMB_CONF_PATH")) {
8816                         set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
8817                 }
8818         }
8819         lp_load(get_dyn_CONFIGFILE(),True,False,False,True);
8820         load_interfaces();
8821
8822         if (argc < 2) {
8823                 usage();
8824         }
8825
8826         for(p = argv[1]; *p; p++)
8827           if(*p == '\\')
8828             *p = '/';
8829
8830         if (strncmp(argv[1], "//", 2)) {
8831                 usage();
8832         }
8833
8834         fstrcpy(host, &argv[1][2]);
8835         p = strchr_m(&host[2],'/');
8836         if (!p) {
8837                 usage();
8838         }
8839         *p = 0;
8840         fstrcpy(share, p+1);
8841
8842         fstrcpy(myname, get_myname(talloc_tos()));
8843         if (!*myname) {
8844                 fprintf(stderr, "Failed to get my hostname.\n");
8845                 return 1;
8846         }
8847
8848         if (*username == 0 && getenv("LOGNAME")) {
8849           fstrcpy(username,getenv("LOGNAME"));
8850         }
8851
8852         argc--;
8853         argv++;
8854
8855         fstrcpy(workgroup, lp_workgroup());
8856
8857         while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
8858                != EOF) {
8859                 switch (opt) {
8860                 case 'p':
8861                         port_to_use = atoi(optarg);
8862                         break;
8863                 case 's':
8864                         seed = atoi(optarg);
8865                         break;
8866                 case 'W':
8867                         fstrcpy(workgroup,optarg);
8868                         break;
8869                 case 'm':
8870                         max_protocol = interpret_protocol(optarg, max_protocol);
8871                         break;
8872                 case 'N':
8873                         nprocs = atoi(optarg);
8874                         break;
8875                 case 'o':
8876                         torture_numops = atoi(optarg);
8877                         break;
8878                 case 'd':
8879                         lp_set_cmdline("log level", optarg);
8880                         break;
8881                 case 'O':
8882                         sockops = optarg;
8883                         break;
8884                 case 'L':
8885                         use_oplocks = True;
8886                         break;
8887                 case 'l':
8888                         local_path = optarg;
8889                         break;
8890                 case 'A':
8891                         torture_showall = True;
8892                         break;
8893                 case 'n':
8894                         fstrcpy(myname, optarg);
8895                         break;
8896                 case 'c':
8897                         client_txt = optarg;
8898                         break;
8899                 case 'e':
8900                         do_encrypt = true;
8901                         break;
8902                 case 'k':
8903 #ifdef HAVE_KRB5
8904                         use_kerberos = True;
8905 #else
8906                         d_printf("No kerberos support compiled in\n");
8907                         exit(1);
8908 #endif
8909                         break;
8910                 case 'U':
8911                         gotuser = 1;
8912                         fstrcpy(username,optarg);
8913                         p = strchr_m(username,'%');
8914                         if (p) {
8915                                 *p = 0;
8916                                 fstrcpy(password, p+1);
8917                                 gotpass = 1;
8918                         }
8919                         break;
8920                 case 'b':
8921                         fstrcpy(multishare_conn_fname, optarg);
8922                         use_multishare_conn = True;
8923                         break;
8924                 case 'B':
8925                         torture_blocksize = atoi(optarg);
8926                         break;
8927                 case 'f':
8928                         test_filename = SMB_STRDUP(optarg);
8929                         break;
8930                 default:
8931                         printf("Unknown option %c (%d)\n", (char)opt, opt);
8932                         usage();
8933                 }
8934         }
8935
8936         d_printf("using seed %d\n", seed);
8937
8938         srandom(seed);
8939
8940         if(use_kerberos && !gotuser) gotpass = True;
8941
8942         while (!gotpass) {
8943                 p = getpass("Password:");
8944                 if (p) {
8945                         fstrcpy(password, p);
8946                         gotpass = 1;
8947                 }
8948         }
8949
8950         printf("host=%s share=%s user=%s myname=%s\n", 
8951                host, share, username, myname);
8952
8953         if (argc == optind) {
8954                 correct = run_test("ALL");
8955         } else {
8956                 for (i=optind;i<argc;i++) {
8957                         if (!run_test(argv[i])) {
8958                                 correct = False;
8959                         }
8960                 }
8961         }
8962
8963         TALLOC_FREE(frame);
8964
8965         if (correct) {
8966                 return(0);
8967         } else {
8968                 return(1);
8969         }
8970 }