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