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