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