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