ba0e6b883f246f0f4a4bdbde33ad87e7a3dc1d84
[ira/wip.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;
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
4002 /*
4003   print out server properties
4004  */
4005 static bool run_properties(int dummy)
4006 {
4007         struct cli_state *cli;
4008         bool correct = True;
4009
4010         printf("starting properties test\n");
4011
4012         ZERO_STRUCT(cli);
4013
4014         if (!torture_open_connection(&cli, 0)) {
4015                 return False;
4016         }
4017
4018         cli_sockopt(cli, sockops);
4019
4020         d_printf("Capabilities 0x%08x\n", cli->capabilities);
4021
4022         if (!torture_close_connection(cli)) {
4023                 correct = False;
4024         }
4025
4026         return correct;
4027 }
4028
4029
4030
4031 /* FIRST_DESIRED_ACCESS   0xf019f */
4032 #define FIRST_DESIRED_ACCESS   FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
4033                                FILE_READ_EA|                           /* 0xf */ \
4034                                FILE_WRITE_EA|FILE_READ_ATTRIBUTES|     /* 0x90 */ \
4035                                FILE_WRITE_ATTRIBUTES|                  /* 0x100 */ \
4036                                DELETE_ACCESS|READ_CONTROL_ACCESS|\
4037                                WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS     /* 0xf0000 */
4038 /* SECOND_DESIRED_ACCESS  0xe0080 */
4039 #define SECOND_DESIRED_ACCESS  FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
4040                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4041                                WRITE_OWNER_ACCESS                      /* 0xe0000 */
4042
4043 #if 0
4044 #define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
4045                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4046                                FILE_READ_DATA|\
4047                                WRITE_OWNER_ACCESS                      /* */
4048 #endif
4049
4050 /*
4051   Test ntcreate calls made by xcopy
4052  */
4053 static bool run_xcopy(int dummy)
4054 {
4055         static struct cli_state *cli1;
4056         const char *fname = "\\test.txt";
4057         bool correct = True;
4058         uint16_t fnum1, fnum2;
4059
4060         printf("starting xcopy test\n");
4061
4062         if (!torture_open_connection(&cli1, 0)) {
4063                 return False;
4064         }
4065
4066         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0,
4067                                    FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
4068                                    FILE_SHARE_NONE, FILE_OVERWRITE_IF, 
4069                                    0x4044, 0, &fnum1))) {
4070                 printf("First open failed - %s\n", cli_errstr(cli1));
4071                 return False;
4072         }
4073
4074         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0,
4075                                    SECOND_DESIRED_ACCESS, 0,
4076                                    FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 
4077                                    0x200000, 0, &fnum2))) {
4078                 printf("second open failed - %s\n", cli_errstr(cli1));
4079                 return False;
4080         }
4081
4082         if (!torture_close_connection(cli1)) {
4083                 correct = False;
4084         }
4085
4086         return correct;
4087 }
4088
4089 /*
4090   Test rename on files open with share delete and no share delete.
4091  */
4092 static bool run_rename(int dummy)
4093 {
4094         static struct cli_state *cli1;
4095         const char *fname = "\\test.txt";
4096         const char *fname1 = "\\test1.txt";
4097         bool correct = True;
4098         uint16_t fnum1;
4099         uint16_t attr;
4100         NTSTATUS status;
4101
4102         printf("starting rename test\n");
4103
4104         if (!torture_open_connection(&cli1, 0)) {
4105                 return False;
4106         }
4107
4108         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4109         cli_unlink(cli1, fname1, aSYSTEM | aHIDDEN);
4110         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4111                                    FILE_SHARE_READ, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4112                 printf("First open failed - %s\n", cli_errstr(cli1));
4113                 return False;
4114         }
4115
4116         if (!NT_STATUS_IS_OK(cli_rename(cli1, fname, fname1))) {
4117                 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", cli_errstr(cli1));
4118         } else {
4119                 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
4120                 correct = False;
4121         }
4122
4123         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4124                 printf("close - 1 failed (%s)\n", cli_errstr(cli1));
4125                 return False;
4126         }
4127
4128         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4129         cli_unlink(cli1, fname1, aSYSTEM | aHIDDEN);
4130         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4131 #if 0
4132                               FILE_SHARE_DELETE|FILE_SHARE_NONE,
4133 #else
4134                               FILE_SHARE_DELETE|FILE_SHARE_READ,
4135 #endif
4136                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
4137         if (!NT_STATUS_IS_OK(status)) {
4138                 printf("Second open failed - %s\n", cli_errstr(cli1));
4139                 return False;
4140         }
4141
4142         if (!NT_STATUS_IS_OK(cli_rename(cli1, fname, fname1))) {
4143                 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", cli_errstr(cli1));
4144                 correct = False;
4145         } else {
4146                 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
4147         }
4148
4149         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4150                 printf("close - 2 failed (%s)\n", cli_errstr(cli1));
4151                 return False;
4152         }
4153
4154         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4155         cli_unlink(cli1, fname1, aSYSTEM | aHIDDEN);
4156
4157         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS, FILE_ATTRIBUTE_NORMAL,
4158                                    FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4159                 printf("Third open failed - %s\n", cli_errstr(cli1));
4160                 return False;
4161         }
4162
4163
4164 #if 0
4165   {
4166         uint16_t fnum2;
4167
4168         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
4169                                    FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4170                 printf("Fourth open failed - %s\n", cli_errstr(cli1));
4171                 return False;
4172         }
4173         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum2, true))) {
4174                 printf("[8] setting delete_on_close on file failed !\n");
4175                 return False;
4176         }
4177
4178         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
4179                 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
4180                 return False;
4181         }
4182   }
4183 #endif
4184
4185         if (!NT_STATUS_IS_OK(cli_rename(cli1, fname, fname1))) {
4186                 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", cli_errstr(cli1));
4187                 correct = False;
4188         } else {
4189                 printf("Third rename succeeded (SHARE_NONE)\n");
4190         }
4191
4192         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4193                 printf("close - 3 failed (%s)\n", cli_errstr(cli1));
4194                 return False;
4195         }
4196
4197         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4198         cli_unlink(cli1, fname1, aSYSTEM | aHIDDEN);
4199
4200         /*----*/
4201
4202         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4203                                    FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4204                 printf("Fourth open failed - %s\n", cli_errstr(cli1));
4205                 return False;
4206         }
4207
4208         if (!NT_STATUS_IS_OK(cli_rename(cli1, fname, fname1))) {
4209                 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", cli_errstr(cli1));
4210         } else {
4211                 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
4212                 correct = False;
4213         }
4214
4215         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4216                 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
4217                 return False;
4218         }
4219
4220         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4221         cli_unlink(cli1, fname1, aSYSTEM | aHIDDEN);
4222
4223         /*--*/
4224
4225         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4226                                    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4227                 printf("Fifth open failed - %s\n", cli_errstr(cli1));
4228                 return False;
4229         }
4230
4231         if (!NT_STATUS_IS_OK(cli_rename(cli1, fname, fname1))) {
4232                 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n",
4233                         cli_errstr(cli1));
4234                 correct = False;
4235         } else {
4236                 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", cli_errstr(cli1));
4237         }
4238
4239         /*
4240          * Now check if the first name still exists ...
4241          */
4242
4243         /* if (!NT_STATUS_OP(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4244                                    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4245           printf("Opening original file after rename of open file fails: %s\n",
4246               cli_errstr(cli1));
4247         }
4248         else {
4249           printf("Opening original file after rename of open file works ...\n");
4250           (void)cli_close(cli1, fnum2);
4251           } */
4252
4253         /*--*/
4254         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4255                 printf("close - 5 failed (%s)\n", cli_errstr(cli1));
4256                 return False;
4257         }
4258
4259         /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
4260         if (!NT_STATUS_IS_OK(cli_getatr(cli1, fname1, &attr, NULL, NULL))) {
4261                 printf("getatr on file %s failed - %s ! \n",
4262                         fname1,
4263                         cli_errstr(cli1));
4264                 correct = False;
4265         } else {
4266                 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
4267                         printf("Renamed file %s has wrong attr 0x%x "
4268                                 "(should be 0x%x)\n",
4269                                 fname1,
4270                                 attr,
4271                                 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
4272                         correct = False;
4273                 } else {
4274                         printf("Renamed file %s has archive bit set\n", fname1);
4275                 }
4276         }
4277
4278         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4279         cli_unlink(cli1, fname1, aSYSTEM | aHIDDEN);
4280
4281         if (!torture_close_connection(cli1)) {
4282                 correct = False;
4283         }
4284
4285         return correct;
4286 }
4287
4288 static bool run_pipe_number(int dummy)
4289 {
4290         struct cli_state *cli1;
4291         const char *pipe_name = "\\SPOOLSS";
4292         uint16_t fnum;
4293         int num_pipes = 0;
4294
4295         printf("starting pipenumber test\n");
4296         if (!torture_open_connection(&cli1, 0)) {
4297                 return False;
4298         }
4299
4300         cli_sockopt(cli1, sockops);
4301         while(1) {
4302                 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
4303                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN_IF, 0, 0, &fnum))) {
4304                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, cli_errstr(cli1));
4305                         break;
4306                 }
4307                 num_pipes++;
4308                 printf("\r%6d", num_pipes);
4309         }
4310
4311         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
4312         torture_close_connection(cli1);
4313         return True;
4314 }
4315
4316 /*
4317   Test open mode returns on read-only files.
4318  */
4319 static bool run_opentest(int dummy)
4320 {
4321         static struct cli_state *cli1;
4322         static struct cli_state *cli2;
4323         const char *fname = "\\readonly.file";
4324         uint16_t fnum1, fnum2;
4325         char buf[20];
4326         SMB_OFF_T fsize;
4327         bool correct = True;
4328         char *tmp_path;
4329
4330         printf("starting open test\n");
4331
4332         if (!torture_open_connection(&cli1, 0)) {
4333                 return False;
4334         }
4335
4336         cli_setatr(cli1, fname, 0, 0);
4337         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4338
4339         cli_sockopt(cli1, sockops);
4340
4341         if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1))) {
4342                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1));
4343                 return False;
4344         }
4345
4346         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4347                 printf("close2 failed (%s)\n", cli_errstr(cli1));
4348                 return False;
4349         }
4350
4351         if (!NT_STATUS_IS_OK(cli_setatr(cli1, fname, aRONLY, 0))) {
4352                 printf("cli_setatr failed (%s)\n", cli_errstr(cli1));
4353                 return False;
4354         }
4355
4356         if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1))) {
4357                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1));
4358                 return False;
4359         }
4360
4361         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
4362         cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4363
4364         if (check_error(__LINE__, cli1, ERRDOS, ERRnoaccess, 
4365                         NT_STATUS_ACCESS_DENIED)) {
4366                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
4367         }
4368
4369         printf("finished open test 1\n");
4370
4371         cli_close(cli1, fnum1);
4372
4373         /* Now try not readonly and ensure ERRbadshare is returned. */
4374
4375         cli_setatr(cli1, fname, 0, 0);
4376
4377         if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1))) {
4378                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1));
4379                 return False;
4380         }
4381
4382         /* This will fail - but the error should be ERRshare. */
4383         cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4384
4385         if (check_error(__LINE__, cli1, ERRDOS, ERRbadshare, 
4386                         NT_STATUS_SHARING_VIOLATION)) {
4387                 printf("correct error code ERRDOS/ERRbadshare returned\n");
4388         }
4389
4390         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4391                 printf("close2 failed (%s)\n", cli_errstr(cli1));
4392                 return False;
4393         }
4394
4395         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4396
4397         printf("finished open test 2\n");
4398
4399         /* Test truncate open disposition on file opened for read. */
4400
4401         if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1))) {
4402                 printf("(3) open (1) of %s failed (%s)\n", fname, cli_errstr(cli1));
4403                 return False;
4404         }
4405
4406         /* write 20 bytes. */
4407
4408         memset(buf, '\0', 20);
4409
4410         if (cli_write(cli1, fnum1, 0, buf, 0, 20) != 20) {
4411                 printf("write failed (%s)\n", cli_errstr(cli1));
4412                 correct = False;
4413         }
4414
4415         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4416                 printf("(3) close1 failed (%s)\n", cli_errstr(cli1));
4417                 return False;
4418         }
4419
4420         /* Ensure size == 20. */
4421         if (!NT_STATUS_IS_OK(cli_getatr(cli1, fname, NULL, &fsize, NULL))) {
4422                 printf("(3) getatr failed (%s)\n", cli_errstr(cli1));
4423                 return False;
4424         }
4425
4426         if (fsize != 20) {
4427                 printf("(3) file size != 20\n");
4428                 return False;
4429         }
4430
4431         /* Now test if we can truncate a file opened for readonly. */
4432
4433         if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1))) {
4434                 printf("(3) open (2) of %s failed (%s)\n", fname, cli_errstr(cli1));
4435                 return False;
4436         }
4437
4438         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4439                 printf("close2 failed (%s)\n", cli_errstr(cli1));
4440                 return False;
4441         }
4442
4443         /* Ensure size == 0. */
4444         if (!NT_STATUS_IS_OK(cli_getatr(cli1, fname, NULL, &fsize, NULL))) {
4445                 printf("(3) getatr failed (%s)\n", cli_errstr(cli1));
4446                 return False;
4447         }
4448
4449         if (fsize != 0) {
4450                 printf("(3) file size != 0\n");
4451                 return False;
4452         }
4453         printf("finished open test 3\n");
4454
4455         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4456
4457         printf("Do ctemp tests\n");
4458         if (!NT_STATUS_IS_OK(cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path))) {
4459                 printf("ctemp failed (%s)\n", cli_errstr(cli1));
4460                 return False;
4461         }
4462         printf("ctemp gave path %s\n", tmp_path);
4463         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4464                 printf("close of temp failed (%s)\n", cli_errstr(cli1));
4465         }
4466         if (!NT_STATUS_IS_OK(cli_unlink(cli1, tmp_path, aSYSTEM | aHIDDEN))) {
4467                 printf("unlink of temp failed (%s)\n", cli_errstr(cli1));
4468         }
4469
4470         /* Test the non-io opens... */
4471
4472         if (!torture_open_connection(&cli2, 1)) {
4473                 return False;
4474         }
4475
4476         cli_setatr(cli2, fname, 0, 0);
4477         cli_unlink(cli2, fname, aSYSTEM | aHIDDEN);
4478
4479         cli_sockopt(cli2, sockops);
4480
4481         printf("TEST #1 testing 2 non-io opens (no delete)\n");
4482
4483         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4484                                    FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4485                 printf("TEST #1 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4486                 return False;
4487         }
4488
4489         if (!NT_STATUS_IS_OK(cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4490                                    FILE_SHARE_NONE, FILE_OPEN_IF, 0, 0, &fnum2))) {
4491                 printf("TEST #1 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4492                 return False;
4493         }
4494
4495         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4496                 printf("TEST #1 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4497                 return False;
4498         }
4499         if (!NT_STATUS_IS_OK(cli_close(cli2, fnum2))) {
4500                 printf("TEST #1 close 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4501                 return False;
4502         }
4503
4504         printf("non-io open test #1 passed.\n");
4505
4506         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4507
4508         printf("TEST #2 testing 2 non-io opens (first with delete)\n");
4509
4510         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4511                                    FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4512                 printf("TEST #2 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4513                 return False;
4514         }
4515
4516         if (!NT_STATUS_IS_OK(cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4517                                    FILE_SHARE_NONE, FILE_OPEN_IF, 0, 0, &fnum2))) {
4518                 printf("TEST #2 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4519                 return False;
4520         }
4521
4522         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4523                 printf("TEST #2 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4524                 return False;
4525         }
4526         if (!NT_STATUS_IS_OK(cli_close(cli2, fnum2))) {
4527                 printf("TEST #2 close 2 of %s failed (%s)\n", fname, cli_errstr(cli1));
4528                 return False;
4529         }
4530
4531         printf("non-io open test #2 passed.\n");
4532
4533         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4534
4535         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
4536
4537         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4538                                    FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4539                 printf("TEST #3 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4540                 return False;
4541         }
4542
4543         if (!NT_STATUS_IS_OK(cli_ntcreate(cli2, fname, 0, DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4544                                    FILE_SHARE_NONE, FILE_OPEN_IF, 0, 0, &fnum2))) {
4545                 printf("TEST #3 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4546                 return False;
4547         }
4548
4549         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4550                 printf("TEST #3 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4551                 return False;
4552         }
4553         if (!NT_STATUS_IS_OK(cli_close(cli2, fnum2))) {
4554                 printf("TEST #3 close 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4555                 return False;
4556         }
4557
4558         printf("non-io open test #3 passed.\n");
4559
4560         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4561
4562         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
4563
4564         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4565                                    FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4566                 printf("TEST #4 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4567                 return False;
4568         }
4569
4570         if (NT_STATUS_IS_OK(cli_ntcreate(cli2, fname, 0, DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4571                                    FILE_SHARE_NONE, FILE_OPEN_IF, 0, 0, &fnum2))) {
4572                 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, cli_errstr(cli2));
4573                 return False;
4574         }
4575
4576         printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, cli_errstr(cli2), "sharing violation");
4577
4578         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4579                 printf("TEST #4 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4580                 return False;
4581         }
4582
4583         printf("non-io open test #4 passed.\n");
4584
4585         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4586
4587         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
4588
4589         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4590                                    FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4591                 printf("TEST #5 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4592                 return False;
4593         }
4594
4595         if (!NT_STATUS_IS_OK(cli_ntcreate(cli2, fname, 0, DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4596                                    FILE_SHARE_DELETE, FILE_OPEN_IF, 0, 0, &fnum2))) {
4597                 printf("TEST #5 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4598                 return False;
4599         }
4600
4601         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4602                 printf("TEST #5 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4603                 return False;
4604         }
4605
4606         if (!NT_STATUS_IS_OK(cli_close(cli2, fnum2))) {
4607                 printf("TEST #5 close 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4608                 return False;
4609         }
4610
4611         printf("non-io open test #5 passed.\n");
4612
4613         printf("TEST #6 testing 1 non-io open, one io open\n");
4614
4615         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4616
4617         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
4618                                    FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4619                 printf("TEST #6 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4620                 return False;
4621         }
4622
4623         if (!NT_STATUS_IS_OK(cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4624                                    FILE_SHARE_READ, FILE_OPEN_IF, 0, 0, &fnum2))) {
4625                 printf("TEST #6 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4626                 return False;
4627         }
4628
4629         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4630                 printf("TEST #6 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4631                 return False;
4632         }
4633
4634         if (!NT_STATUS_IS_OK(cli_close(cli2, fnum2))) {
4635                 printf("TEST #6 close 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4636                 return False;
4637         }
4638
4639         printf("non-io open test #6 passed.\n");
4640
4641         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
4642
4643         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4644
4645         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
4646                                    FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4647                 printf("TEST #7 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4648                 return False;
4649         }
4650
4651         if (NT_STATUS_IS_OK(cli_ntcreate(cli2, fname, 0, DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4652                                    FILE_SHARE_READ|FILE_SHARE_DELETE, FILE_OPEN_IF, 0, 0, &fnum2))) {
4653                 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, cli_errstr(cli2));
4654                 return False;
4655         }
4656
4657         printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, cli_errstr(cli2), "sharing violation");
4658
4659         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4660                 printf("TEST #7 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4661                 return False;
4662         }
4663
4664         printf("non-io open test #7 passed.\n");
4665
4666         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4667
4668         if (!torture_close_connection(cli1)) {
4669                 correct = False;
4670         }
4671         if (!torture_close_connection(cli2)) {
4672                 correct = False;
4673         }
4674
4675         return correct;
4676 }
4677
4678 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
4679 {
4680         uint16 major, minor;
4681         uint32 caplow, caphigh;
4682         NTSTATUS status;
4683
4684         if (!SERVER_HAS_UNIX_CIFS(cli)) {
4685                 printf("Server doesn't support UNIX CIFS extensions.\n");
4686                 return NT_STATUS_NOT_SUPPORTED;
4687         }
4688
4689         status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
4690                                              &caphigh);
4691         if (!NT_STATUS_IS_OK(status)) {
4692                 printf("Server didn't return UNIX CIFS extensions: %s\n",
4693                        nt_errstr(status));
4694                 return status;
4695         }
4696
4697         status = cli_set_unix_extensions_capabilities(cli, major, minor,
4698                                                       caplow, caphigh);
4699         if (!NT_STATUS_IS_OK(status)) {
4700                 printf("Server doesn't support setting UNIX CIFS extensions: "
4701                        "%s.\n", nt_errstr(status));
4702                 return status;
4703         }
4704
4705         return NT_STATUS_OK;
4706 }
4707
4708 /*
4709   Test POSIX open /mkdir calls.
4710  */
4711 static bool run_simple_posix_open_test(int dummy)
4712 {
4713         static struct cli_state *cli1;
4714         const char *fname = "posix:file";
4715         const char *hname = "posix:hlink";
4716         const char *sname = "posix:symlink";
4717         const char *dname = "posix:dir";
4718         char buf[10];
4719         char namebuf[11];
4720         uint16_t fnum1 = (uint16_t)-1;
4721         SMB_STRUCT_STAT sbuf;
4722         bool correct = false;
4723         NTSTATUS status;
4724
4725         printf("Starting simple POSIX open test\n");
4726
4727         if (!torture_open_connection(&cli1, 0)) {
4728                 return false;
4729         }
4730
4731         cli_sockopt(cli1, sockops);
4732
4733         status = torture_setup_unix_extensions(cli1);
4734         if (!NT_STATUS_IS_OK(status)) {
4735                 return false;
4736         }
4737
4738         cli_setatr(cli1, fname, 0, 0);
4739         cli_posix_unlink(cli1, fname);
4740         cli_setatr(cli1, dname, 0, 0);
4741         cli_posix_rmdir(cli1, dname);
4742         cli_setatr(cli1, hname, 0, 0);
4743         cli_posix_unlink(cli1, hname);
4744         cli_setatr(cli1, sname, 0, 0);
4745         cli_posix_unlink(cli1, sname);
4746
4747         /* Create a directory. */
4748         if (!NT_STATUS_IS_OK(cli_posix_mkdir(cli1, dname, 0777))) {
4749                 printf("POSIX mkdir of %s failed (%s)\n", dname, cli_errstr(cli1));
4750                 goto out;
4751         }
4752
4753         if (!NT_STATUS_IS_OK(cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1))) {
4754                 printf("POSIX create of %s failed (%s)\n", fname, cli_errstr(cli1));
4755                 goto out;
4756         }
4757
4758         /* Test ftruncate - set file size. */
4759         if (!NT_STATUS_IS_OK(cli_ftruncate(cli1, fnum1, 1000))) {
4760                 printf("ftruncate failed (%s)\n", cli_errstr(cli1));
4761                 goto out;
4762         }
4763
4764         /* Ensure st_size == 1000 */
4765         if (!NT_STATUS_IS_OK(cli_posix_stat(cli1, fname, &sbuf))) {
4766                 printf("stat failed (%s)\n", cli_errstr(cli1));
4767                 goto out;
4768         }
4769
4770         if (sbuf.st_ex_size != 1000) {
4771                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
4772                 goto out;
4773         }
4774
4775         /* Test ftruncate - set file size back to zero. */
4776         if (!NT_STATUS_IS_OK(cli_ftruncate(cli1, fnum1, 0))) {
4777                 printf("ftruncate failed (%s)\n", cli_errstr(cli1));
4778                 goto out;
4779         }
4780
4781         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4782                 printf("close failed (%s)\n", cli_errstr(cli1));
4783                 goto out;
4784         }
4785
4786         /* Now open the file again for read only. */
4787         if (!NT_STATUS_IS_OK(cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1))) {
4788                 printf("POSIX open of %s failed (%s)\n", fname, cli_errstr(cli1));
4789                 goto out;
4790         }
4791
4792         /* Now unlink while open. */
4793         if (!NT_STATUS_IS_OK(cli_posix_unlink(cli1, fname))) {
4794                 printf("POSIX unlink of %s failed (%s)\n", fname, cli_errstr(cli1));
4795                 goto out;
4796         }
4797
4798         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4799                 printf("close(2) failed (%s)\n", cli_errstr(cli1));
4800                 goto out;
4801         }
4802
4803         /* Ensure the file has gone. */
4804         if (NT_STATUS_IS_OK(cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1))) {
4805                 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
4806                 goto out;
4807         }
4808
4809         /* What happens when we try and POSIX open a directory ? */
4810         if (NT_STATUS_IS_OK(cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1))) {
4811                 printf("POSIX open of directory %s succeeded, should have failed.\n", fname);
4812                 goto out;
4813         } else {
4814                 if (!check_error(__LINE__, cli1, ERRDOS, EISDIR,
4815                                 NT_STATUS_FILE_IS_A_DIRECTORY)) {
4816                         goto out;
4817                 }
4818         }
4819
4820         /* Create the file. */
4821         if (!NT_STATUS_IS_OK(cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1))) {
4822                 printf("POSIX create of %s failed (%s)\n", fname, cli_errstr(cli1));
4823                 goto out;
4824         }
4825
4826         /* Write some data into it. */
4827         if (cli_write(cli1, fnum1, 0, "TEST DATA\n", 0, 10) != 10) {
4828                 printf("cli_write failed: %s\n", cli_errstr(cli1));
4829                 goto out;
4830         }
4831
4832         cli_close(cli1, fnum1);
4833
4834         /* Now create a hardlink. */
4835         if (!NT_STATUS_IS_OK(cli_posix_hardlink(cli1, fname, hname))) {
4836                 printf("POSIX hardlink of %s failed (%s)\n", hname, cli_errstr(cli1));
4837                 goto out;
4838         }
4839
4840         /* Now create a symlink. */
4841         if (!NT_STATUS_IS_OK(cli_posix_symlink(cli1, fname, sname))) {
4842                 printf("POSIX symlink of %s failed (%s)\n", sname, cli_errstr(cli1));
4843                 goto out;
4844         }
4845
4846         /* Open the hardlink for read. */
4847         if (!NT_STATUS_IS_OK(cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1))) {
4848                 printf("POSIX open of %s failed (%s)\n", hname, cli_errstr(cli1));
4849                 goto out;
4850         }
4851
4852         if (cli_read(cli1, fnum1, buf, 0, 10) != 10) {
4853                 printf("POSIX read of %s failed (%s)\n", hname, cli_errstr(cli1));
4854                 goto out;
4855         }
4856
4857         if (memcmp(buf, "TEST DATA\n", 10)) {
4858                 printf("invalid data read from hardlink\n");
4859                 goto out;
4860         }
4861
4862         /* Do a POSIX lock/unlock. */
4863         if (!NT_STATUS_IS_OK(cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK))) {
4864                 printf("POSIX lock failed %s\n", cli_errstr(cli1));
4865                 goto out;
4866         }
4867
4868         /* Punch a hole in the locked area. */
4869         if (!NT_STATUS_IS_OK(cli_posix_unlock(cli1, fnum1, 10, 80))) {
4870                 printf("POSIX unlock failed %s\n", cli_errstr(cli1));
4871                 goto out;
4872         }
4873
4874         cli_close(cli1, fnum1);
4875
4876         /* Open the symlink for read - this should fail. A POSIX
4877            client should not be doing opens on a symlink. */
4878         if (NT_STATUS_IS_OK(cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1))) {
4879                 printf("POSIX open of %s succeeded (should have failed)\n", sname);
4880                 goto out;
4881         } else {
4882                 if (!check_error(__LINE__, cli1, ERRDOS, ERRbadpath,
4883                                 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
4884                         printf("POSIX open of %s should have failed "
4885                                 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
4886                                 "failed with %s instead.\n",
4887                                 sname, cli_errstr(cli1));
4888                         goto out;
4889                 }
4890         }
4891
4892         if (!NT_STATUS_IS_OK(cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf)))) {
4893                 printf("POSIX readlink on %s failed (%s)\n", sname, cli_errstr(cli1));
4894                 goto out;
4895         }
4896
4897         if (strcmp(namebuf, fname) != 0) {
4898                 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
4899                         sname, fname, namebuf);
4900                 goto out;
4901         }
4902
4903         if (!NT_STATUS_IS_OK(cli_posix_rmdir(cli1, dname))) {
4904                 printf("POSIX rmdir failed (%s)\n", cli_errstr(cli1));
4905                 goto out;
4906         }
4907
4908         printf("Simple POSIX open test passed\n");
4909         correct = true;
4910
4911   out:
4912
4913         if (fnum1 != (uint16_t)-1) {
4914                 cli_close(cli1, fnum1);
4915                 fnum1 = (uint16_t)-1;
4916         }
4917
4918         cli_setatr(cli1, sname, 0, 0);
4919         cli_posix_unlink(cli1, sname);
4920         cli_setatr(cli1, hname, 0, 0);
4921         cli_posix_unlink(cli1, hname);
4922         cli_setatr(cli1, fname, 0, 0);
4923         cli_posix_unlink(cli1, fname);
4924         cli_setatr(cli1, dname, 0, 0);
4925         cli_posix_rmdir(cli1, dname);
4926
4927         if (!torture_close_connection(cli1)) {
4928                 correct = false;
4929         }
4930
4931         return correct;
4932 }
4933
4934
4935 static uint32 open_attrs_table[] = {
4936                 FILE_ATTRIBUTE_NORMAL,
4937                 FILE_ATTRIBUTE_ARCHIVE,
4938                 FILE_ATTRIBUTE_READONLY,
4939                 FILE_ATTRIBUTE_HIDDEN,
4940                 FILE_ATTRIBUTE_SYSTEM,
4941
4942                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
4943                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
4944                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
4945                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
4946                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
4947                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
4948
4949                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
4950                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
4951                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
4952                 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
4953 };
4954
4955 struct trunc_open_results {
4956         unsigned int num;
4957         uint32 init_attr;
4958         uint32 trunc_attr;
4959         uint32 result_attr;
4960 };
4961
4962 static struct trunc_open_results attr_results[] = {
4963         { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
4964         { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
4965         { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
4966         { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
4967         { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
4968         { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
4969         { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
4970         { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
4971         { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
4972         { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
4973         { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
4974         { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
4975         { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
4976         { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
4977         { 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 },
4978         { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
4979         { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
4980         { 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 },
4981         { 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 },
4982         { 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 },
4983         { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
4984         { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
4985         { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
4986         { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
4987         { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
4988         { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
4989 };
4990
4991 static bool run_openattrtest(int dummy)
4992 {
4993         static struct cli_state *cli1;
4994         const char *fname = "\\openattr.file";
4995         uint16_t fnum1;
4996         bool correct = True;
4997         uint16 attr;
4998         unsigned int i, j, k, l;
4999
5000         printf("starting open attr test\n");
5001
5002         if (!torture_open_connection(&cli1, 0)) {
5003                 return False;
5004         }
5005
5006         cli_sockopt(cli1, sockops);
5007
5008         for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32); i++) {
5009                 cli_setatr(cli1, fname, 0, 0);
5010                 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
5011                 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, open_attrs_table[i],
5012                                    FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
5013                         printf("open %d (1) of %s failed (%s)\n", i, fname, cli_errstr(cli1));
5014                         return False;
5015                 }
5016
5017                 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
5018                         printf("close %d (1) of %s failed (%s)\n", i, fname, cli_errstr(cli1));
5019                         return False;
5020                 }
5021
5022                 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32); j++) {
5023                         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA, open_attrs_table[j],
5024                                            FILE_SHARE_NONE, FILE_OVERWRITE, 0, 0, &fnum1))) {
5025                                 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5026                                         if (attr_results[l].num == k) {
5027                                                 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
5028                                                                 k, open_attrs_table[i],
5029                                                                 open_attrs_table[j],
5030                                                                 fname, NT_STATUS_V(cli_nt_error(cli1)), cli_errstr(cli1));
5031                                                 correct = False;
5032                                         }
5033                                 }
5034                                 if (NT_STATUS_V(cli_nt_error(cli1)) != NT_STATUS_V(NT_STATUS_ACCESS_DENIED)) {
5035                                         printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
5036                                                         k, open_attrs_table[i], open_attrs_table[j],
5037                                                         cli_errstr(cli1));
5038                                         correct = False;
5039                                 }
5040 #if 0
5041                                 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
5042 #endif
5043                                 k++;
5044                                 continue;
5045                         }
5046
5047                         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
5048                                 printf("close %d (2) of %s failed (%s)\n", j, fname, cli_errstr(cli1));
5049                                 return False;
5050                         }
5051
5052                         if (!NT_STATUS_IS_OK(cli_getatr(cli1, fname, &attr, NULL, NULL))) {
5053                                 printf("getatr(2) failed (%s)\n", cli_errstr(cli1));
5054                                 return False;
5055                         }
5056
5057 #if 0
5058                         printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
5059                                         k,  open_attrs_table[i],  open_attrs_table[j], attr );
5060 #endif
5061
5062                         for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5063                                 if (attr_results[l].num == k) {
5064                                         if (attr != attr_results[l].result_attr ||
5065                                                         open_attrs_table[i] != attr_results[l].init_attr ||
5066                                                         open_attrs_table[j] != attr_results[l].trunc_attr) {
5067                                                 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
5068                                                 open_attrs_table[i],
5069                                                 open_attrs_table[j],
5070                                                 (unsigned int)attr,
5071                                                 attr_results[l].result_attr);
5072                                                 correct = False;
5073                                         }
5074                                         break;
5075                                 }
5076                         }
5077                         k++;
5078                 }
5079         }
5080
5081         cli_setatr(cli1, fname, 0, 0);
5082         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
5083
5084         printf("open attr test %s.\n", correct ? "passed" : "failed");
5085
5086         if (!torture_close_connection(cli1)) {
5087                 correct = False;
5088         }
5089         return correct;
5090 }
5091
5092 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
5093                     const char *name, void *state)
5094 {
5095         int *matched = (int *)state;
5096         if (matched != NULL) {
5097                 *matched += 1;
5098         }
5099         return NT_STATUS_OK;
5100 }
5101
5102 /*
5103   test directory listing speed
5104  */
5105 static bool run_dirtest(int dummy)
5106 {
5107         int i;
5108         static struct cli_state *cli;
5109         uint16_t fnum;
5110         struct timeval core_start;
5111         bool correct = True;
5112         int matched;
5113
5114         printf("starting directory test\n");
5115
5116         if (!torture_open_connection(&cli, 0)) {
5117                 return False;
5118         }
5119
5120         cli_sockopt(cli, sockops);
5121
5122         srandom(0);
5123         for (i=0;i<torture_numops;i++) {
5124                 fstring fname;
5125                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5126                 if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
5127                         fprintf(stderr,"Failed to open %s\n", fname);
5128                         return False;
5129                 }
5130                 cli_close(cli, fnum);
5131         }
5132
5133         core_start = timeval_current();
5134
5135         matched = 0;
5136         cli_list(cli, "a*.*", 0, list_fn, &matched);
5137         printf("Matched %d\n", matched);
5138
5139         matched = 0;
5140         cli_list(cli, "b*.*", 0, list_fn, &matched);
5141         printf("Matched %d\n", matched);
5142
5143         matched = 0;
5144         cli_list(cli, "xyzabc", 0, list_fn, &matched);
5145         printf("Matched %d\n", matched);
5146
5147         printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
5148
5149         srandom(0);
5150         for (i=0;i<torture_numops;i++) {
5151                 fstring fname;
5152                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5153                 cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
5154         }
5155
5156         if (!torture_close_connection(cli)) {
5157                 correct = False;
5158         }
5159
5160         printf("finished dirtest\n");
5161
5162         return correct;
5163 }
5164
5165 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
5166                    void *state)
5167 {
5168         struct cli_state *pcli = (struct cli_state *)state;
5169         fstring fname;
5170         slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
5171
5172         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
5173                 return NT_STATUS_OK;
5174
5175         if (finfo->mode & aDIR) {
5176                 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
5177                         printf("del_fn: failed to rmdir %s\n,", fname );
5178         } else {
5179                 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, aSYSTEM | aHIDDEN)))
5180                         printf("del_fn: failed to unlink %s\n,", fname );
5181         }
5182         return NT_STATUS_OK;
5183 }
5184
5185
5186 /*
5187   sees what IOCTLs are supported
5188  */
5189 bool torture_ioctl_test(int dummy)
5190 {
5191         static struct cli_state *cli;
5192         uint16_t device, function;
5193         uint16_t fnum;
5194         const char *fname = "\\ioctl.dat";
5195         DATA_BLOB blob;
5196         NTSTATUS status;
5197
5198         if (!torture_open_connection(&cli, 0)) {
5199                 return False;
5200         }
5201
5202         printf("starting ioctl test\n");
5203
5204         cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
5205
5206         if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum))) {
5207                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli));
5208                 return False;
5209         }
5210
5211         status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
5212         printf("ioctl device info: %s\n", nt_errstr(status));
5213
5214         status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
5215         printf("ioctl job info: %s\n", nt_errstr(status));
5216
5217         for (device=0;device<0x100;device++) {
5218                 printf("ioctl test with device = 0x%x\n", device);
5219                 for (function=0;function<0x100;function++) {
5220                         uint32 code = (device<<16) | function;
5221
5222                         status = cli_raw_ioctl(cli, fnum, code, &blob);
5223
5224                         if (NT_STATUS_IS_OK(status)) {
5225                                 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
5226                                        (int)blob.length);
5227                                 data_blob_free(&blob);
5228                         }
5229                 }
5230         }
5231
5232         if (!torture_close_connection(cli)) {
5233                 return False;
5234         }
5235
5236         return True;
5237 }
5238
5239
5240 /*
5241   tries varients of chkpath
5242  */
5243 bool torture_chkpath_test(int dummy)
5244 {
5245         static struct cli_state *cli;
5246         uint16_t fnum;
5247         bool ret;
5248
5249         if (!torture_open_connection(&cli, 0)) {
5250                 return False;
5251         }
5252
5253         printf("starting chkpath test\n");
5254
5255         /* cleanup from an old run */
5256         cli_rmdir(cli, "\\chkpath.dir\\dir2");
5257         cli_unlink(cli, "\\chkpath.dir\\*", aSYSTEM | aHIDDEN);
5258         cli_rmdir(cli, "\\chkpath.dir");
5259
5260         if (!NT_STATUS_IS_OK(cli_mkdir(cli, "\\chkpath.dir"))) {
5261                 printf("mkdir1 failed : %s\n", cli_errstr(cli));
5262                 return False;
5263         }
5264
5265         if (!NT_STATUS_IS_OK(cli_mkdir(cli, "\\chkpath.dir\\dir2"))) {
5266                 printf("mkdir2 failed : %s\n", cli_errstr(cli));
5267                 return False;
5268         }
5269
5270         if (!NT_STATUS_IS_OK(cli_open(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum))) {
5271                 printf("open1 failed (%s)\n", cli_errstr(cli));
5272                 return False;
5273         }
5274         cli_close(cli, fnum);
5275
5276         if (!NT_STATUS_IS_OK(cli_chkpath(cli, "\\chkpath.dir"))) {
5277                 printf("chkpath1 failed: %s\n", cli_errstr(cli));
5278                 ret = False;
5279         }
5280
5281         if (!NT_STATUS_IS_OK(cli_chkpath(cli, "\\chkpath.dir\\dir2"))) {
5282                 printf("chkpath2 failed: %s\n", cli_errstr(cli));
5283                 ret = False;
5284         }
5285
5286         if (!NT_STATUS_IS_OK(cli_chkpath(cli, "\\chkpath.dir\\foo.txt"))) {
5287                 ret = check_error(__LINE__, cli, ERRDOS, ERRbadpath, 
5288                                   NT_STATUS_NOT_A_DIRECTORY);
5289         } else {
5290                 printf("* chkpath on a file should fail\n");
5291                 ret = False;
5292         }
5293
5294         if (!NT_STATUS_IS_OK(cli_chkpath(cli, "\\chkpath.dir\\bar.txt"))) {
5295                 ret = check_error(__LINE__, cli, ERRDOS, ERRbadfile, 
5296                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
5297         } else {
5298                 printf("* chkpath on a non existant file should fail\n");
5299                 ret = False;
5300         }
5301
5302         if (!NT_STATUS_IS_OK(cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt"))) {
5303                 ret = check_error(__LINE__, cli, ERRDOS, ERRbadpath, 
5304                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
5305         } else {
5306                 printf("* chkpath on a non existent component should fail\n");
5307                 ret = False;
5308         }
5309
5310         cli_rmdir(cli, "\\chkpath.dir\\dir2");
5311         cli_unlink(cli, "\\chkpath.dir\\*", aSYSTEM | aHIDDEN);
5312         cli_rmdir(cli, "\\chkpath.dir");
5313
5314         if (!torture_close_connection(cli)) {
5315                 return False;
5316         }
5317
5318         return ret;
5319 }
5320
5321 static bool run_eatest(int dummy)
5322 {
5323         static struct cli_state *cli;
5324         const char *fname = "\\eatest.txt";
5325         bool correct = True;
5326         uint16_t fnum;
5327         int i;
5328         size_t num_eas;
5329         struct ea_struct *ea_list = NULL;
5330         TALLOC_CTX *mem_ctx = talloc_init("eatest");
5331         NTSTATUS status;
5332
5333         printf("starting eatest\n");
5334
5335         if (!torture_open_connection(&cli, 0)) {
5336                 talloc_destroy(mem_ctx);
5337                 return False;
5338         }
5339
5340         cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
5341         if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0,
5342                                    FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
5343                                    FILE_SHARE_NONE, FILE_OVERWRITE_IF, 
5344                                    0x4044, 0, &fnum))) {
5345                 printf("open failed - %s\n", cli_errstr(cli));
5346                 talloc_destroy(mem_ctx);
5347                 return False;
5348         }
5349
5350         for (i = 0; i < 10; i++) {
5351                 fstring ea_name, ea_val;
5352
5353                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
5354                 memset(ea_val, (char)i+1, i+1);
5355                 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
5356                 if (!NT_STATUS_IS_OK(status)) {
5357                         printf("ea_set of name %s failed - %s\n", ea_name,
5358                                nt_errstr(status));
5359                         talloc_destroy(mem_ctx);
5360                         return False;
5361                 }
5362         }
5363
5364         cli_close(cli, fnum);
5365         for (i = 0; i < 10; i++) {
5366                 fstring ea_name, ea_val;
5367
5368                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
5369                 memset(ea_val, (char)i+1, i+1);
5370                 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
5371                 if (!NT_STATUS_IS_OK(status)) {
5372                         printf("ea_set of name %s failed - %s\n", ea_name,
5373                                nt_errstr(status));
5374                         talloc_destroy(mem_ctx);
5375                         return False;
5376                 }
5377         }
5378
5379         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
5380         if (!NT_STATUS_IS_OK(status)) {
5381                 printf("ea_get list failed - %s\n", nt_errstr(status));
5382                 correct = False;
5383         }
5384
5385         printf("num_eas = %d\n", (int)num_eas);
5386
5387         if (num_eas != 20) {
5388                 printf("Should be 20 EA's stored... failing.\n");
5389                 correct = False;
5390         }
5391
5392         for (i = 0; i < num_eas; i++) {
5393                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
5394                 dump_data(0, ea_list[i].value.data,
5395                           ea_list[i].value.length);
5396         }
5397
5398         /* Setting EA's to zero length deletes them. Test this */
5399         printf("Now deleting all EA's - case indepenent....\n");
5400
5401 #if 1
5402         cli_set_ea_path(cli, fname, "", "", 0);
5403 #else
5404         for (i = 0; i < 20; i++) {
5405                 fstring ea_name;
5406                 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
5407                 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
5408                 if (!NT_STATUS_IS_OK(status)) {
5409                         printf("ea_set of name %s failed - %s\n", ea_name,
5410                                nt_errstr(status));
5411                         talloc_destroy(mem_ctx);
5412                         return False;
5413                 }
5414         }
5415 #endif
5416
5417         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
5418         if (!NT_STATUS_IS_OK(status)) {
5419                 printf("ea_get list failed - %s\n", nt_errstr(status));
5420                 correct = False;
5421         }
5422
5423         printf("num_eas = %d\n", (int)num_eas);
5424         for (i = 0; i < num_eas; i++) {
5425                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
5426                 dump_data(0, ea_list[i].value.data,
5427                           ea_list[i].value.length);
5428         }
5429
5430         if (num_eas != 0) {
5431                 printf("deleting EA's failed.\n");
5432                 correct = False;
5433         }
5434
5435         /* Try and delete a non existant EA. */
5436         status = cli_set_ea_path(cli, fname, "foo", "", 0);
5437         if (!NT_STATUS_IS_OK(status)) {
5438                 printf("deleting non-existant EA 'foo' should succeed. %s\n",
5439                        nt_errstr(status));
5440                 correct = False;
5441         }
5442
5443         talloc_destroy(mem_ctx);
5444         if (!torture_close_connection(cli)) {
5445                 correct = False;
5446         }
5447
5448         return correct;
5449 }
5450
5451 static bool run_dirtest1(int dummy)
5452 {
5453         int i;
5454         static struct cli_state *cli;
5455         uint16_t fnum;
5456         int num_seen;
5457         bool correct = True;
5458
5459         printf("starting directory test\n");
5460
5461         if (!torture_open_connection(&cli, 0)) {
5462                 return False;
5463         }
5464
5465         cli_sockopt(cli, sockops);
5466
5467         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
5468         cli_list(cli, "\\LISTDIR\\*", aDIR, del_fn, cli);
5469         cli_rmdir(cli, "\\LISTDIR");
5470         cli_mkdir(cli, "\\LISTDIR");
5471
5472         /* Create 1000 files and 1000 directories. */
5473         for (i=0;i<1000;i++) {
5474                 fstring fname;
5475                 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
5476                 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
5477                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum))) {
5478                         fprintf(stderr,"Failed to open %s\n", fname);
5479                         return False;
5480                 }
5481                 cli_close(cli, fnum);
5482         }
5483         for (i=0;i<1000;i++) {
5484                 fstring fname;
5485                 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
5486                 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
5487                         fprintf(stderr,"Failed to open %s\n", fname);
5488                         return False;
5489                 }
5490         }
5491
5492         /* Now ensure that doing an old list sees both files and directories. */
5493         num_seen = 0;
5494         cli_list_old(cli, "\\LISTDIR\\*", aDIR, list_fn, &num_seen);
5495         printf("num_seen = %d\n", num_seen );
5496         /* We should see 100 files + 1000 directories + . and .. */
5497         if (num_seen != 2002)
5498                 correct = False;
5499
5500         /* Ensure if we have the "must have" bits we only see the
5501          * relevent entries.
5502          */
5503         num_seen = 0;
5504         cli_list_old(cli, "\\LISTDIR\\*", (aDIR<<8)|aDIR, list_fn, &num_seen);
5505         printf("num_seen = %d\n", num_seen );
5506         if (num_seen != 1002)
5507                 correct = False;
5508
5509         num_seen = 0;
5510         cli_list_old(cli, "\\LISTDIR\\*", (aARCH<<8)|aDIR, list_fn, &num_seen);
5511         printf("num_seen = %d\n", num_seen );
5512         if (num_seen != 1000)
5513                 correct = False;
5514
5515         /* Delete everything. */
5516         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
5517         cli_list(cli, "\\LISTDIR\\*", aDIR, del_fn, cli);
5518         cli_rmdir(cli, "\\LISTDIR");
5519
5520 #if 0
5521         printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
5522         printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
5523         printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
5524 #endif
5525
5526         if (!torture_close_connection(cli)) {
5527                 correct = False;
5528         }
5529
5530         printf("finished dirtest1\n");
5531
5532         return correct;
5533 }
5534
5535 static bool run_error_map_extract(int dummy) {
5536
5537         static struct cli_state *c_dos;
5538         static struct cli_state *c_nt;
5539         NTSTATUS status;
5540
5541         uint32 error;
5542
5543         uint32 flgs2, errnum;
5544         uint8 errclass;
5545
5546         NTSTATUS nt_status;
5547
5548         fstring user;
5549
5550         /* NT-Error connection */
5551
5552         if (!(c_nt = open_nbt_connection())) {
5553                 return False;
5554         }
5555
5556         c_nt->use_spnego = False;
5557
5558         status = cli_negprot(c_nt);
5559
5560         if (!NT_STATUS_IS_OK(status)) {
5561                 printf("%s rejected the NT-error negprot (%s)\n", host,
5562                        nt_errstr(status));
5563                 cli_shutdown(c_nt);
5564                 return False;
5565         }
5566
5567         if (!NT_STATUS_IS_OK(cli_session_setup(c_nt, "", "", 0, "", 0,
5568                                                workgroup))) {
5569                 printf("%s rejected the NT-error initial session setup (%s)\n",host, cli_errstr(c_nt));
5570                 return False;
5571         }
5572
5573         /* DOS-Error connection */
5574
5575         if (!(c_dos = open_nbt_connection())) {
5576                 return False;
5577         }
5578
5579         c_dos->use_spnego = False;
5580         c_dos->force_dos_errors = True;
5581
5582         status = cli_negprot(c_dos);
5583         if (!NT_STATUS_IS_OK(status)) {
5584                 printf("%s rejected the DOS-error negprot (%s)\n", host,
5585                        nt_errstr(status));
5586                 cli_shutdown(c_dos);
5587                 return False;
5588         }
5589
5590         if (!NT_STATUS_IS_OK(cli_session_setup(c_dos, "", "", 0, "", 0,
5591                                                workgroup))) {
5592                 printf("%s rejected the DOS-error initial session setup (%s)\n",host, cli_errstr(c_dos));
5593                 return False;
5594         }
5595
5596         for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
5597                 fstr_sprintf(user, "%X", error);
5598
5599                 if (NT_STATUS_IS_OK(cli_session_setup(c_nt, user, 
5600                                                       password, strlen(password),
5601                                                       password, strlen(password),
5602                                                       workgroup))) {
5603                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
5604                 }
5605
5606                 flgs2 = SVAL(c_nt->inbuf,smb_flg2);
5607
5608                 /* Case #1: 32-bit NT errors */
5609                 if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) {
5610                         nt_status = NT_STATUS(IVAL(c_nt->inbuf,smb_rcls));
5611                 } else {
5612                         printf("/** Dos error on NT connection! (%s) */\n", 
5613                                cli_errstr(c_nt));
5614                         nt_status = NT_STATUS(0xc0000000);
5615                 }
5616
5617                 if (NT_STATUS_IS_OK(cli_session_setup(c_dos, user, 
5618                                                       password, strlen(password),
5619                                                       password, strlen(password),
5620                                                       workgroup))) {
5621                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
5622                 }
5623                 flgs2 = SVAL(c_dos->inbuf,smb_flg2), errnum;
5624
5625                 /* Case #1: 32-bit NT errors */
5626                 if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) {
5627                         printf("/** NT error on DOS connection! (%s) */\n", 
5628                                cli_errstr(c_nt));
5629                         errnum = errclass = 0;
5630                 } else {
5631                         cli_dos_error(c_dos, &errclass, &errnum);
5632                 }
5633
5634                 if (NT_STATUS_V(nt_status) != error) { 
5635                         printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n", 
5636                                get_nt_error_c_code(NT_STATUS(error)), 
5637                                get_nt_error_c_code(nt_status));
5638                 }
5639
5640                 printf("\t{%s,\t%s,\t%s},\n", 
5641                        smb_dos_err_class(errclass), 
5642                        smb_dos_err_name(errclass, errnum), 
5643                        get_nt_error_c_code(NT_STATUS(error)));
5644         }
5645         return True;
5646 }
5647
5648 static bool run_sesssetup_bench(int dummy)
5649 {
5650         static struct cli_state *c;
5651         const char *fname = "\\file.dat";
5652         uint16_t fnum;
5653         NTSTATUS status;
5654         int i;
5655
5656         if (!torture_open_connection(&c, 0)) {
5657                 return false;
5658         }
5659
5660         if (!NT_STATUS_IS_OK(cli_ntcreate(
5661                         c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5662                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5663                         FILE_DELETE_ON_CLOSE, 0, &fnum))) {
5664                 d_printf("open %s failed: %s\n", fname, cli_errstr(c));
5665                 return false;
5666         }
5667
5668         for (i=0; i<torture_numops; i++) {
5669                 status = cli_session_setup(
5670                         c, username,
5671                         password, strlen(password),
5672                         password, strlen(password),
5673                         workgroup);
5674                 if (!NT_STATUS_IS_OK(status)) {
5675                         d_printf("(%s) cli_session_setup failed: %s\n",
5676                                  __location__, nt_errstr(status));
5677                         return false;
5678                 }
5679
5680                 d_printf("\r%d   ", (int)c->vuid);
5681
5682                 status = cli_ulogoff(c);
5683                 if (!NT_STATUS_IS_OK(status)) {
5684                         d_printf("(%s) cli_ulogoff failed: %s\n",
5685                                  __location__, nt_errstr(status));
5686                         return false;
5687                 }
5688                 c->vuid = 0;
5689         }
5690
5691         return true;
5692 }
5693
5694 static bool subst_test(const char *str, const char *user, const char *domain,
5695                        uid_t uid, gid_t gid, const char *expected)
5696 {
5697         char *subst;
5698         bool result = true;
5699
5700         subst = talloc_sub_specified(talloc_tos(), str, user, domain, uid, gid);
5701
5702         if (strcmp(subst, expected) != 0) {
5703                 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
5704                        "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
5705                        expected);
5706                 result = false;
5707         }
5708
5709         TALLOC_FREE(subst);
5710         return result;
5711 }
5712
5713 static void chain1_open_completion(struct tevent_req *req)
5714 {
5715         uint16_t fnum;
5716         NTSTATUS status;
5717         status = cli_open_recv(req, &fnum);
5718         TALLOC_FREE(req);
5719
5720         d_printf("cli_open_recv returned %s: %d\n",
5721                  nt_errstr(status),
5722                  NT_STATUS_IS_OK(status) ? fnum : -1);
5723 }
5724
5725 static void chain1_write_completion(struct tevent_req *req)
5726 {
5727         size_t written;
5728         NTSTATUS status;
5729         status = cli_write_andx_recv(req, &written);
5730         TALLOC_FREE(req);
5731
5732         d_printf("cli_write_andx_recv returned %s: %d\n",
5733                  nt_errstr(status),
5734                  NT_STATUS_IS_OK(status) ? (int)written : -1);
5735 }
5736
5737 static void chain1_close_completion(struct tevent_req *req)
5738 {
5739         NTSTATUS status;
5740         bool *done = (bool *)tevent_req_callback_data_void(req);
5741
5742         status = cli_close_recv(req);
5743         *done = true;
5744
5745         TALLOC_FREE(req);
5746
5747         d_printf("cli_close returned %s\n", nt_errstr(status));
5748 }
5749
5750 static bool run_chain1(int dummy)
5751 {
5752         struct cli_state *cli1;
5753         struct event_context *evt = event_context_init(NULL);
5754         struct tevent_req *reqs[3], *smbreqs[3];
5755         bool done = false;
5756         const char *str = "foobar";
5757         NTSTATUS status;
5758
5759         printf("starting chain1 test\n");
5760         if (!torture_open_connection(&cli1, 0)) {
5761                 return False;
5762         }
5763
5764         cli_sockopt(cli1, sockops);
5765
5766         reqs[0] = cli_open_create(talloc_tos(), evt, cli1, "\\test",
5767                                   O_CREAT|O_RDWR, 0, &smbreqs[0]);
5768         if (reqs[0] == NULL) return false;
5769         tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
5770
5771
5772         reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
5773                                         (uint8_t *)str, 0, strlen(str)+1,
5774                                         smbreqs, 1, &smbreqs[1]);
5775         if (reqs[1] == NULL) return false;
5776         tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
5777
5778         reqs[2] = cli_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
5779         if (reqs[2] == NULL) return false;
5780         tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
5781
5782         status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
5783         if (!NT_STATUS_IS_OK(status)) {
5784                 return false;
5785         }
5786
5787         while (!done) {
5788                 event_loop_once(evt);
5789         }
5790
5791         torture_close_connection(cli1);
5792         return True;
5793 }
5794
5795 static void chain2_sesssetup_completion(struct tevent_req *req)
5796 {
5797         NTSTATUS status;
5798         status = cli_session_setup_guest_recv(req);
5799         d_printf("sesssetup returned %s\n", nt_errstr(status));
5800 }
5801
5802 static void chain2_tcon_completion(struct tevent_req *req)
5803 {
5804         bool *done = (bool *)tevent_req_callback_data_void(req);
5805         NTSTATUS status;
5806         status = cli_tcon_andx_recv(req);
5807         d_printf("tcon_and_x returned %s\n", nt_errstr(status));
5808         *done = true;
5809 }
5810
5811 static bool run_chain2(int dummy)
5812 {
5813         struct cli_state *cli1;
5814         struct event_context *evt = event_context_init(NULL);
5815         struct tevent_req *reqs[2], *smbreqs[2];
5816         bool done = false;
5817         NTSTATUS status;
5818
5819         printf("starting chain2 test\n");
5820         status = cli_start_connection(&cli1, global_myname(), host, NULL,
5821                                       port_to_use, Undefined, 0);
5822         if (!NT_STATUS_IS_OK(status)) {
5823                 return False;
5824         }
5825
5826         cli_sockopt(cli1, sockops);
5827
5828         reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
5829                                                  &smbreqs[0]);
5830         if (reqs[0] == NULL) return false;
5831         tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
5832
5833         reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
5834                                        "?????", NULL, 0, &smbreqs[1]);
5835         if (reqs[1] == NULL) return false;
5836         tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
5837
5838         status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
5839         if (!NT_STATUS_IS_OK(status)) {
5840                 return false;
5841         }
5842
5843         while (!done) {
5844                 event_loop_once(evt);
5845         }
5846
5847         torture_close_connection(cli1);
5848         return True;
5849 }
5850
5851
5852 struct torture_createdel_state {
5853         struct tevent_context *ev;
5854         struct cli_state *cli;
5855 };
5856
5857 static void torture_createdel_created(struct tevent_req *subreq);
5858 static void torture_createdel_closed(struct tevent_req *subreq);
5859
5860 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
5861                                                  struct tevent_context *ev,
5862                                                  struct cli_state *cli,
5863                                                  const char *name)
5864 {
5865         struct tevent_req *req, *subreq;
5866         struct torture_createdel_state *state;
5867
5868         req = tevent_req_create(mem_ctx, &state,
5869                                 struct torture_createdel_state);
5870         if (req == NULL) {
5871                 return NULL;
5872         }
5873         state->ev = ev;
5874         state->cli = cli;
5875
5876         subreq = cli_ntcreate_send(
5877                 state, ev, cli, name, 0,
5878                 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5879                 FILE_ATTRIBUTE_NORMAL,
5880                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5881                 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
5882
5883         if (tevent_req_nomem(subreq, req)) {
5884                 return tevent_req_post(req, ev);
5885         }
5886         tevent_req_set_callback(subreq, torture_createdel_created, req);
5887         return req;
5888 }
5889
5890 static void torture_createdel_created(struct tevent_req *subreq)
5891 {
5892         struct tevent_req *req = tevent_req_callback_data(
5893                 subreq, struct tevent_req);
5894         struct torture_createdel_state *state = tevent_req_data(
5895                 req, struct torture_createdel_state);
5896         NTSTATUS status;
5897         uint16_t fnum;
5898
5899         status = cli_ntcreate_recv(subreq, &fnum);
5900         TALLOC_FREE(subreq);
5901         if (!NT_STATUS_IS_OK(status)) {
5902                 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
5903                            nt_errstr(status)));
5904                 tevent_req_nterror(req, status);
5905                 return;
5906         }
5907
5908         subreq = cli_close_send(state, state->ev, state->cli, fnum);
5909         if (tevent_req_nomem(subreq, req)) {
5910                 return;
5911         }
5912         tevent_req_set_callback(subreq, torture_createdel_closed, req);
5913 }
5914
5915 static void torture_createdel_closed(struct tevent_req *subreq)
5916 {
5917         struct tevent_req *req = tevent_req_callback_data(
5918                 subreq, struct tevent_req);
5919         NTSTATUS status;
5920
5921         status = cli_close_recv(subreq);
5922         if (!NT_STATUS_IS_OK(status)) {
5923                 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
5924                 tevent_req_nterror(req, status);
5925                 return;
5926         }
5927         tevent_req_done(req);
5928 }
5929
5930 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
5931 {
5932         return tevent_req_simple_recv_ntstatus(req);
5933 }
5934
5935 struct torture_createdels_state {
5936         struct tevent_context *ev;
5937         struct cli_state *cli;
5938         const char *base_name;
5939         int sent;
5940         int received;
5941         int num_files;
5942         struct tevent_req **reqs;
5943 };
5944
5945 static void torture_createdels_done(struct tevent_req *subreq);
5946
5947 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
5948                                                   struct tevent_context *ev,
5949                                                   struct cli_state *cli,
5950                                                   const char *base_name,
5951                                                   int num_parallel,
5952                                                   int num_files)
5953 {
5954         struct tevent_req *req;
5955         struct torture_createdels_state *state;
5956         int i;
5957
5958         req = tevent_req_create(mem_ctx, &state,
5959                                 struct torture_createdels_state);
5960         if (req == NULL) {
5961                 return NULL;
5962         }
5963         state->ev = ev;
5964         state->cli = cli;
5965         state->base_name = talloc_strdup(state, base_name);
5966         if (tevent_req_nomem(state->base_name, req)) {
5967                 return tevent_req_post(req, ev);
5968         }
5969         state->num_files = MAX(num_parallel, num_files);
5970         state->sent = 0;
5971         state->received = 0;
5972
5973         state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
5974         if (tevent_req_nomem(state->reqs, req)) {
5975                 return tevent_req_post(req, ev);
5976         }
5977
5978         for (i=0; i<num_parallel; i++) {
5979                 char *name;
5980
5981                 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
5982                                        state->sent);
5983                 if (tevent_req_nomem(name, req)) {
5984                         return tevent_req_post(req, ev);
5985                 }
5986                 state->reqs[i] = torture_createdel_send(
5987                         state->reqs, state->ev, state->cli, name);
5988                 if (tevent_req_nomem(state->reqs[i], req)) {
5989                         return tevent_req_post(req, ev);
5990                 }
5991                 name = talloc_move(state->reqs[i], &name);
5992                 tevent_req_set_callback(state->reqs[i],
5993                                         torture_createdels_done, req);
5994                 state->sent += 1;
5995         }
5996         return req;
5997 }
5998
5999 static void torture_createdels_done(struct tevent_req *subreq)
6000 {
6001         struct tevent_req *req = tevent_req_callback_data(
6002                 subreq, struct tevent_req);
6003         struct torture_createdels_state *state = tevent_req_data(
6004                 req, struct torture_createdels_state);
6005         size_t num_parallel = talloc_array_length(state->reqs);
6006         NTSTATUS status;
6007         char *name;
6008         int i;
6009
6010         status = torture_createdel_recv(subreq);
6011         if (!NT_STATUS_IS_OK(status)){
6012                 DEBUG(10, ("torture_createdel_recv returned %s\n",
6013                            nt_errstr(status)));
6014                 TALLOC_FREE(subreq);
6015                 tevent_req_nterror(req, status);
6016                 return;
6017         }
6018
6019         for (i=0; i<num_parallel; i++) {
6020                 if (subreq == state->reqs[i]) {
6021                         break;
6022                 }
6023         }
6024         if (i == num_parallel) {
6025                 DEBUG(10, ("received something we did not send\n"));
6026                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
6027                 return;
6028         }
6029         TALLOC_FREE(state->reqs[i]);
6030
6031         if (state->sent >= state->num_files) {
6032                 tevent_req_done(req);
6033                 return;
6034         }
6035
6036         name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6037                                state->sent);
6038         if (tevent_req_nomem(name, req)) {
6039                 return;
6040         }
6041         state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
6042                                                 state->cli, name);
6043         if (tevent_req_nomem(state->reqs[i], req)) {
6044                 return;
6045         }
6046         name = talloc_move(state->reqs[i], &name);
6047         tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
6048         state->sent += 1;
6049 }
6050
6051 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
6052 {
6053         return tevent_req_simple_recv_ntstatus(req);
6054 }
6055
6056 struct swallow_notify_state {
6057         struct tevent_context *ev;
6058         struct cli_state *cli;
6059         uint16_t fnum;
6060         uint32_t completion_filter;
6061         bool recursive;
6062         bool (*fn)(uint32_t action, const char *name, void *priv);
6063         void *priv;
6064 };
6065
6066 static void swallow_notify_done(struct tevent_req *subreq);
6067
6068 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
6069                                               struct tevent_context *ev,
6070                                               struct cli_state *cli,
6071                                               uint16_t fnum,
6072                                               uint32_t completion_filter,
6073                                               bool recursive,
6074                                               bool (*fn)(uint32_t action,
6075                                                          const char *name,
6076                                                          void *priv),
6077                                               void *priv)
6078 {
6079         struct tevent_req *req, *subreq;
6080         struct swallow_notify_state *state;
6081
6082         req = tevent_req_create(mem_ctx, &state,
6083                                 struct swallow_notify_state);
6084         if (req == NULL) {
6085                 return NULL;
6086         }
6087         state->ev = ev;
6088         state->cli = cli;
6089         state->fnum = fnum;
6090         state->completion_filter = completion_filter;
6091         state->recursive = recursive;
6092         state->fn = fn;
6093         state->priv = priv;
6094
6095         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6096                                  0xffff, state->completion_filter,
6097                                  state->recursive);
6098         if (tevent_req_nomem(subreq, req)) {
6099                 return tevent_req_post(req, ev);
6100         }
6101         tevent_req_set_callback(subreq, swallow_notify_done, req);
6102         return req;
6103 }
6104
6105 static void swallow_notify_done(struct tevent_req *subreq)
6106 {
6107         struct tevent_req *req = tevent_req_callback_data(
6108                 subreq, struct tevent_req);
6109         struct swallow_notify_state *state = tevent_req_data(
6110                 req, struct swallow_notify_state);
6111         NTSTATUS status;
6112         uint32_t i, num_changes;
6113         struct notify_change *changes;
6114
6115         status = cli_notify_recv(subreq, state, &num_changes, &changes);
6116         TALLOC_FREE(subreq);
6117         if (!NT_STATUS_IS_OK(status)) {
6118                 DEBUG(10, ("cli_notify_recv returned %s\n",
6119                            nt_errstr(status)));
6120                 tevent_req_nterror(req, status);
6121                 return;
6122         }
6123
6124         for (i=0; i<num_changes; i++) {
6125                 state->fn(changes[i].action, changes[i].name, state->priv);
6126         }
6127         TALLOC_FREE(changes);
6128
6129         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6130                                  0xffff, state->completion_filter,
6131                                  state->recursive);
6132         if (tevent_req_nomem(subreq, req)) {
6133                 return;
6134         }
6135         tevent_req_set_callback(subreq, swallow_notify_done, req);
6136 }
6137
6138 static bool print_notifies(uint32_t action, const char *name, void *priv)
6139 {
6140         if (DEBUGLEVEL > 5) {
6141                 d_printf("%d %s\n", (int)action, name);
6142         }
6143         return true;
6144 }
6145
6146 static void notify_bench_done(struct tevent_req *req)
6147 {
6148         int *num_finished = (int *)tevent_req_callback_data_void(req);
6149         *num_finished += 1;
6150 }
6151
6152 static bool run_notify_bench(int dummy)
6153 {
6154         const char *dname = "\\notify-bench";
6155         struct tevent_context *ev;
6156         NTSTATUS status;
6157         uint16_t dnum;
6158         struct tevent_req *req1;
6159         struct tevent_req *req2 = NULL;
6160         int i, num_unc_names;
6161         int num_finished = 0;
6162
6163         printf("starting notify-bench test\n");
6164
6165         if (use_multishare_conn) {
6166                 char **unc_list;
6167                 unc_list = file_lines_load(multishare_conn_fname,
6168                                            &num_unc_names, 0, NULL);
6169                 if (!unc_list || num_unc_names <= 0) {
6170                         d_printf("Failed to load unc names list from '%s'\n",
6171                                  multishare_conn_fname);
6172                         return false;
6173                 }
6174                 TALLOC_FREE(unc_list);
6175         } else {
6176                 num_unc_names = 1;
6177         }
6178
6179         ev = tevent_context_init(talloc_tos());
6180         if (ev == NULL) {
6181                 d_printf("tevent_context_init failed\n");
6182                 return false;
6183         }
6184
6185         for (i=0; i<num_unc_names; i++) {
6186                 struct cli_state *cli;
6187                 char *base_fname;
6188
6189                 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
6190                                              dname, i);
6191                 if (base_fname == NULL) {
6192                         return false;
6193                 }
6194
6195                 if (!torture_open_connection(&cli, i)) {
6196                         return false;
6197                 }
6198
6199                 status = cli_ntcreate(cli, dname, 0,
6200                                       MAXIMUM_ALLOWED_ACCESS,
6201                                       0, FILE_SHARE_READ|FILE_SHARE_WRITE|
6202                                       FILE_SHARE_DELETE,
6203                                       FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
6204                                       &dnum);
6205
6206                 if (!NT_STATUS_IS_OK(status)) {
6207                         d_printf("Could not create %s: %s\n", dname,
6208                                  nt_errstr(status));
6209                         return false;
6210                 }
6211
6212                 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
6213                                            FILE_NOTIFY_CHANGE_FILE_NAME |
6214                                            FILE_NOTIFY_CHANGE_DIR_NAME |
6215                                            FILE_NOTIFY_CHANGE_ATTRIBUTES |
6216                                            FILE_NOTIFY_CHANGE_LAST_WRITE,
6217                                            false, print_notifies, NULL);
6218                 if (req1 == NULL) {
6219                         d_printf("Could not create notify request\n");
6220                         return false;
6221                 }
6222
6223                 req2 = torture_createdels_send(talloc_tos(), ev, cli,
6224                                                base_fname, 10, torture_numops);
6225                 if (req2 == NULL) {
6226                         d_printf("Could not create createdels request\n");
6227                         return false;
6228                 }
6229                 TALLOC_FREE(base_fname);
6230
6231                 tevent_req_set_callback(req2, notify_bench_done,
6232                                         &num_finished);
6233         }
6234
6235         while (num_finished < num_unc_names) {
6236                 int ret;
6237                 ret = tevent_loop_once(ev);
6238                 if (ret != 0) {
6239                         d_printf("tevent_loop_once failed\n");
6240                         return false;
6241                 }
6242         }
6243
6244         if (!tevent_req_poll(req2, ev)) {
6245                 d_printf("tevent_req_poll failed\n");
6246         }
6247
6248         status = torture_createdels_recv(req2);
6249         d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
6250
6251         return true;
6252 }
6253
6254 static bool run_mangle1(int dummy)
6255 {
6256         struct cli_state *cli;
6257         const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
6258         uint16_t fnum;
6259         fstring alt_name;
6260         NTSTATUS status;
6261         time_t change_time, access_time, write_time;
6262         SMB_OFF_T size;
6263         uint16_t mode;
6264
6265         printf("starting mangle1 test\n");
6266         if (!torture_open_connection(&cli, 0)) {
6267                 return False;
6268         }
6269
6270         cli_sockopt(cli, sockops);
6271
6272         if (!NT_STATUS_IS_OK(cli_ntcreate(
6273                         cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6274                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF, 0, 0, &fnum))) {
6275                 d_printf("open %s failed: %s\n", fname, cli_errstr(cli));
6276                 return false;
6277         }
6278         cli_close(cli, fnum);
6279
6280         status = cli_qpathinfo_alt_name(cli, fname, alt_name);
6281         if (!NT_STATUS_IS_OK(status)) {
6282                 d_printf("cli_qpathinfo_alt_name failed: %s\n",
6283                          nt_errstr(status));
6284                 return false;
6285         }
6286         d_printf("alt_name: %s\n", alt_name);
6287
6288         if (!NT_STATUS_IS_OK(cli_open(cli, alt_name, O_RDONLY, DENY_NONE, &fnum))) {
6289                 d_printf("cli_open(%s) failed: %s\n", alt_name,
6290                          cli_errstr(cli));
6291                 return false;
6292         }
6293         cli_close(cli, fnum);
6294
6295         status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
6296                                 &write_time, &size, &mode);
6297         if (!NT_STATUS_IS_OK(status)) {
6298                 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
6299                          nt_errstr(status));
6300                 return false;
6301         }
6302
6303         return true;
6304 }
6305
6306 static size_t null_source(uint8_t *buf, size_t n, void *priv)
6307 {
6308         size_t *to_pull = (size_t *)priv;
6309         size_t thistime = *to_pull;
6310
6311         thistime = MIN(thistime, n);
6312         if (thistime == 0) {
6313                 return 0;
6314         }
6315
6316         memset(buf, 0, thistime);
6317         *to_pull -= thistime;
6318         return thistime;
6319 }
6320
6321 static bool run_windows_write(int dummy)
6322 {
6323         struct cli_state *cli1;
6324         uint16_t fnum;
6325         int i;
6326         bool ret = false;
6327         const char *fname = "\\writetest.txt";
6328         struct timeval start_time;
6329         double seconds;
6330         double kbytes;
6331
6332         printf("starting windows_write test\n");
6333         if (!torture_open_connection(&cli1, 0)) {
6334                 return False;
6335         }
6336
6337         if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum))) {
6338                 printf("open failed (%s)\n", cli_errstr(cli1));
6339                 return False;
6340         }
6341
6342         cli_sockopt(cli1, sockops);
6343
6344         start_time = timeval_current();
6345
6346         for (i=0; i<torture_numops; i++) {
6347                 char c = 0;
6348                 off_t start = i * torture_blocksize;
6349                 NTSTATUS status;
6350                 size_t to_pull = torture_blocksize - 1;
6351
6352                 if (cli_write(cli1, fnum, 0, &c,
6353                               start + torture_blocksize - 1, 1) != 1) {
6354                         printf("cli_write failed: %s\n", cli_errstr(cli1));
6355                         goto fail;
6356                 }
6357
6358                 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
6359                                   null_source, &to_pull);
6360                 if (!NT_STATUS_IS_OK(status)) {
6361                         printf("cli_push returned: %s\n", nt_errstr(status));
6362                         goto fail;
6363                 }
6364         }
6365
6366         seconds = timeval_elapsed(&start_time);
6367         kbytes = (double)torture_blocksize * torture_numops;
6368         kbytes /= 1024;
6369
6370         printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
6371                (double)seconds, (int)(kbytes/seconds));
6372
6373         ret = true;
6374  fail:
6375         cli_close(cli1, fnum);
6376         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
6377         torture_close_connection(cli1);
6378         return ret;
6379 }
6380
6381 static bool run_cli_echo(int dummy)
6382 {
6383         struct cli_state *cli;
6384         NTSTATUS status;
6385
6386         printf("starting cli_echo test\n");
6387         if (!torture_open_connection(&cli, 0)) {
6388                 return false;
6389         }
6390         cli_sockopt(cli, sockops);
6391
6392         status = cli_echo(cli, 5, data_blob_const("hello", 5));
6393
6394         d_printf("cli_echo returned %s\n", nt_errstr(status));
6395
6396         torture_close_connection(cli);
6397         return NT_STATUS_IS_OK(status);
6398 }
6399
6400 static bool run_uid_regression_test(int dummy)
6401 {
6402         static struct cli_state *cli;
6403         int16_t old_vuid;
6404         int16_t old_cnum;
6405         bool correct = True;
6406         NTSTATUS status;
6407
6408         printf("starting uid regression test\n");
6409
6410         if (!torture_open_connection(&cli, 0)) {
6411                 return False;
6412         }
6413
6414         cli_sockopt(cli, sockops);
6415
6416         /* Ok - now save then logoff our current user. */
6417         old_vuid = cli->vuid;
6418
6419         status = cli_ulogoff(cli);
6420         if (!NT_STATUS_IS_OK(status)) {
6421                 d_printf("(%s) cli_ulogoff failed: %s\n",
6422                          __location__, nt_errstr(status));
6423                 correct = false;
6424                 goto out;
6425         }
6426
6427         cli->vuid = old_vuid;
6428
6429         /* Try an operation. */
6430         status = cli_mkdir(cli, "\\uid_reg_test");
6431         if (NT_STATUS_IS_OK(status)) {
6432                 d_printf("(%s) cli_mkdir succeeded\n",
6433                          __location__);
6434                 correct = false;
6435                 goto out;
6436         } else {
6437                 /* Should be bad uid. */
6438                 if (!check_error(__LINE__, cli, ERRSRV, ERRbaduid,
6439                                 NT_STATUS_USER_SESSION_DELETED)) {
6440                         correct = false;
6441                         goto out;
6442                 }
6443         }
6444
6445         old_cnum = cli->cnum;
6446
6447         /* Now try a SMBtdis with the invald vuid set to zero. */
6448         cli->vuid = 0;
6449
6450         /* This should succeed. */
6451         status = cli_tdis(cli);
6452
6453         if (NT_STATUS_IS_OK(status)) {
6454                 d_printf("First tdis with invalid vuid should succeed.\n");
6455         } else {
6456                 d_printf("First tdis failed (%s)\n", nt_errstr(status));
6457                 correct = false;
6458                 goto out;
6459         }
6460
6461         cli->vuid = old_vuid;
6462         cli->cnum = old_cnum;
6463
6464         /* This should fail. */
6465         status = cli_tdis(cli);
6466         if (NT_STATUS_IS_OK(status)) {
6467                 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
6468                 correct = false;
6469                 goto out;
6470         } else {
6471                 /* Should be bad tid. */
6472                 if (!check_error(__LINE__, cli, ERRSRV, ERRinvnid,
6473                                 NT_STATUS_NETWORK_NAME_DELETED)) {
6474                         correct = false;
6475                         goto out;
6476                 }
6477         }
6478
6479         cli_rmdir(cli, "\\uid_reg_test");
6480
6481   out:
6482
6483         cli_shutdown(cli);
6484         return correct;
6485 }
6486
6487
6488 static const char *illegal_chars = "*\\/?<>|\":";
6489 static char force_shortname_chars[] = " +,.[];=\177";
6490
6491 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
6492                              const char *mask, void *state)
6493 {
6494         struct cli_state *pcli = (struct cli_state *)state;
6495         fstring fname;
6496         NTSTATUS status = NT_STATUS_OK;
6497
6498         slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
6499
6500         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
6501                 return NT_STATUS_OK;
6502
6503         if (finfo->mode & aDIR) {
6504                 status = cli_rmdir(pcli, fname);
6505                 if (!NT_STATUS_IS_OK(status)) {
6506                         printf("del_fn: failed to rmdir %s\n,", fname );
6507                 }
6508         } else {
6509                 status = cli_unlink(pcli, fname, aSYSTEM | aHIDDEN);
6510                 if (!NT_STATUS_IS_OK(status)) {
6511                         printf("del_fn: failed to unlink %s\n,", fname );
6512                 }
6513         }
6514         return status;
6515 }
6516
6517 struct sn_state {
6518         int matched;
6519         int i;
6520         bool val;
6521 };
6522
6523 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
6524                               const char *name, void *state)
6525 {
6526         struct sn_state *s = (struct sn_state  *)state;
6527         int i = s->i;
6528
6529 #if 0
6530         printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
6531                 i, finfo->name, finfo->short_name);
6532 #endif
6533
6534         if (strchr(force_shortname_chars, i)) {
6535                 if (!finfo->short_name[0]) {
6536                         /* Shortname not created when it should be. */
6537                         d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
6538                                 __location__, finfo->name, i);
6539                         s->val = true;
6540                 }
6541         } else if (finfo->short_name[0]){
6542                 /* Shortname created when it should not be. */
6543                 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
6544                         __location__, finfo->short_name, finfo->name);
6545                 s->val = true;
6546         }
6547         s->matched += 1;
6548         return NT_STATUS_OK;
6549 }
6550
6551 static bool run_shortname_test(int dummy)
6552 {
6553         static struct cli_state *cli;
6554         bool correct = True;
6555         int i;
6556         struct sn_state s;
6557         char fname[20];
6558
6559         printf("starting shortname test\n");
6560
6561         if (!torture_open_connection(&cli, 0)) {
6562                 return False;
6563         }
6564
6565         cli_sockopt(cli, sockops);
6566
6567         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
6568         cli_list(cli, "\\shortname\\*", aDIR, shortname_del_fn, cli);
6569         cli_rmdir(cli, "\\shortname");
6570
6571         if (!NT_STATUS_IS_OK(cli_mkdir(cli, "\\shortname"))) {
6572                 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
6573                         __location__, cli_errstr(cli));
6574                 correct = false;
6575                 goto out;
6576         }
6577
6578         strlcpy(fname, "\\shortname\\", sizeof(fname));
6579         strlcat(fname, "test .txt", sizeof(fname));
6580
6581         s.val = false;
6582
6583         for (i = 32; i < 128; i++) {
6584                 NTSTATUS status;
6585                 uint16_t fnum = (uint16_t)-1;
6586
6587                 s.i = i;
6588
6589                 if (strchr(illegal_chars, i)) {
6590                         continue;
6591                 }
6592                 fname[15] = i;
6593
6594                 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
6595                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum);
6596                 if (!NT_STATUS_IS_OK(status)) {
6597                         d_printf("(%s) cli_nt_create of %s failed: %s\n",
6598                                 __location__, fname, cli_errstr(cli));
6599                         correct = false;
6600                         goto out;
6601                 }
6602                 cli_close(cli, fnum);
6603
6604                 s.matched = 0;
6605                 cli_list(cli, "\\shortname\\test*.*", 0, shortname_list_fn,
6606                          &s);
6607                 if (s.matched != 1) {
6608                         d_printf("(%s) failed to list %s: %s\n",
6609                                 __location__, fname, cli_errstr(cli));
6610                         correct = false;
6611                         goto out;
6612                 }
6613                 if (!NT_STATUS_IS_OK(cli_unlink(cli, fname, aSYSTEM | aHIDDEN))) {
6614                         d_printf("(%s) failed to delete %s: %s\n",
6615                                 __location__, fname, cli_errstr(cli));
6616                         correct = false;
6617                         goto out;
6618                 }
6619
6620                 if (s.val) {
6621                         correct = false;
6622                         goto out;
6623                 }
6624         }
6625
6626   out:
6627
6628         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
6629         cli_list(cli, "\\shortname\\*", aDIR, shortname_del_fn, cli);
6630         cli_rmdir(cli, "\\shortname");
6631         torture_close_connection(cli);
6632         return correct;
6633 }
6634
6635 static void pagedsearch_cb(struct tevent_req *req)
6636 {
6637         int rc;
6638         struct tldap_message *msg;
6639         char *dn;
6640
6641         rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
6642         if (rc != TLDAP_SUCCESS) {
6643                 d_printf("tldap_search_paged_recv failed: %s\n",
6644                          tldap_err2string(rc));
6645                 return;
6646         }
6647         if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
6648                 TALLOC_FREE(msg);
6649                 return;
6650         }
6651         if (!tldap_entry_dn(msg, &dn)) {
6652                 d_printf("tldap_entry_dn failed\n");
6653                 return;
6654         }
6655         d_printf("%s\n", dn);
6656         TALLOC_FREE(msg);
6657 }
6658
6659 static bool run_tldap(int dummy)
6660 {
6661         struct tldap_context *ld;
6662         int fd, rc;
6663         NTSTATUS status;
6664         struct sockaddr_storage addr;
6665         struct tevent_context *ev;
6666         struct tevent_req *req;
6667         char *basedn;
6668         const char *filter;
6669
6670         if (!resolve_name(host, &addr, 0, false)) {
6671                 d_printf("could not find host %s\n", host);
6672                 return false;
6673         }
6674         status = open_socket_out(&addr, 389, 9999, &fd);
6675         if (!NT_STATUS_IS_OK(status)) {
6676                 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
6677                 return false;
6678         }
6679
6680         ld = tldap_context_create(talloc_tos(), fd);
6681         if (ld == NULL) {
6682                 close(fd);
6683                 d_printf("tldap_context_create failed\n");
6684                 return false;
6685         }
6686
6687         rc = tldap_fetch_rootdse(ld);
6688         if (rc != TLDAP_SUCCESS) {
6689                 d_printf("tldap_fetch_rootdse failed: %s\n",
6690                          tldap_errstr(talloc_tos(), ld, rc));
6691                 return false;
6692         }
6693
6694         basedn = tldap_talloc_single_attribute(
6695                 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
6696         if (basedn == NULL) {
6697                 d_printf("no defaultNamingContext\n");
6698                 return false;
6699         }
6700         d_printf("defaultNamingContext: %s\n", basedn);
6701
6702         ev = tevent_context_init(talloc_tos());
6703         if (ev == NULL) {
6704                 d_printf("tevent_context_init failed\n");
6705                 return false;
6706         }
6707
6708         req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
6709                                       TLDAP_SCOPE_SUB, "(objectclass=*)",
6710                                       NULL, 0, 0,
6711                                       NULL, 0, NULL, 0, 0, 0, 0, 5);
6712         if (req == NULL) {
6713                 d_printf("tldap_search_paged_send failed\n");
6714                 return false;
6715         }
6716         tevent_req_set_callback(req, pagedsearch_cb, NULL);
6717
6718         tevent_req_poll(req, ev);
6719
6720         TALLOC_FREE(req);
6721
6722         /* test search filters against rootDSE */
6723         filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
6724                    "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
6725
6726         rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
6727                           NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
6728                           talloc_tos(), NULL, NULL);
6729         if (rc != TLDAP_SUCCESS) {
6730                 d_printf("tldap_search with complex filter failed: %s\n",
6731                          tldap_errstr(talloc_tos(), ld, rc));
6732                 return false;
6733         }
6734
6735         TALLOC_FREE(ld);
6736         return true;
6737 }
6738
6739 /* Torture test to ensure no regression of :
6740 https://bugzilla.samba.org/show_bug.cgi?id=7084
6741 */
6742
6743 static bool run_dir_createtime(int dummy)
6744 {
6745         struct cli_state *cli;
6746         const char *dname = "\\testdir";
6747         const char *fname = "\\testdir\\testfile";
6748         NTSTATUS status;
6749         struct timespec create_time;
6750         struct timespec create_time1;
6751         uint16_t fnum;
6752         bool ret = false;
6753
6754         if (!torture_open_connection(&cli, 0)) {
6755                 return false;
6756         }
6757
6758         cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
6759         cli_rmdir(cli, dname);
6760
6761         status = cli_mkdir(cli, dname);
6762         if (!NT_STATUS_IS_OK(status)) {
6763                 printf("mkdir failed: %s\n", nt_errstr(status));
6764                 goto out;
6765         }
6766
6767         status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
6768                                 NULL, NULL, NULL);
6769         if (!NT_STATUS_IS_OK(status)) {
6770                 printf("cli_qpathinfo2 returned %s\n",
6771                        nt_errstr(status));
6772                 goto out;
6773         }
6774
6775         /* Sleep 3 seconds, then create a file. */
6776         sleep(3);
6777
6778         status = cli_open(cli, fname, O_RDWR | O_CREAT | O_EXCL,
6779                          DENY_NONE, &fnum);
6780         if (!NT_STATUS_IS_OK(status)) {
6781                 printf("cli_open failed: %s\n", nt_errstr(status));
6782                 goto out;
6783         }
6784
6785         status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
6786                                 NULL, NULL, NULL);
6787         if (!NT_STATUS_IS_OK(status)) {
6788                 printf("cli_qpathinfo2 (2) returned %s\n",
6789                        nt_errstr(status));
6790                 goto out;
6791         }
6792
6793         if (timespec_compare(&create_time1, &create_time)) {
6794                 printf("run_dir_createtime: create time was updated (error)\n");
6795         } else {
6796                 printf("run_dir_createtime: create time was not updated (correct)\n");
6797                 ret = true;
6798         }
6799
6800   out:
6801
6802         cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
6803         cli_rmdir(cli, dname);
6804         if (!torture_close_connection(cli)) {
6805                 ret = false;
6806         }
6807         return ret;
6808 }
6809
6810
6811 static bool run_streamerror(int dummy)
6812 {
6813         struct cli_state *cli;
6814         const char *dname = "\\testdir";
6815         const char *streamname =
6816                 "testdir:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
6817         NTSTATUS status;
6818         time_t change_time, access_time, write_time;
6819         SMB_OFF_T size;
6820         uint16_t mode, fnum;
6821         bool ret = true;
6822
6823         if (!torture_open_connection(&cli, 0)) {
6824                 return false;
6825         }
6826
6827         cli_unlink(cli, "\\testdir\\*", aSYSTEM | aHIDDEN);
6828         cli_rmdir(cli, dname);
6829
6830         status = cli_mkdir(cli, dname);
6831         if (!NT_STATUS_IS_OK(status)) {
6832                 printf("mkdir failed: %s\n", nt_errstr(status));
6833                 return false;
6834         }
6835
6836         cli_qpathinfo1(cli, streamname, &change_time, &access_time, &write_time,
6837                       &size, &mode);
6838         status = cli_nt_error(cli);
6839
6840         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6841                 printf("pathinfo returned %s, expected "
6842                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
6843                        nt_errstr(status));
6844                 ret = false;
6845         }
6846
6847         status = cli_ntcreate(cli, streamname, 0x16,
6848                               FILE_READ_DATA|FILE_READ_EA|
6849                               FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
6850                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6851                               FILE_OPEN, 0, 0, &fnum);
6852
6853         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6854                 printf("ntcreate returned %s, expected "
6855                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
6856                        nt_errstr(status));
6857                 ret = false;
6858         }
6859
6860
6861         cli_rmdir(cli, dname);
6862         return ret;
6863 }
6864
6865 static bool run_local_substitute(int dummy)
6866 {
6867         bool ok = true;
6868
6869         ok &= subst_test("%U", "bla", "", -1, -1, "bla");
6870         ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
6871         ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
6872         ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
6873         ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
6874         ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
6875         ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
6876         ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
6877
6878         /* Different captialization rules in sub_basic... */
6879
6880         ok &=  (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
6881                        "blaDOM") == 0);
6882
6883         return ok;
6884 }
6885
6886 static bool run_local_base64(int dummy)
6887 {
6888         int i;
6889         bool ret = true;
6890
6891         for (i=1; i<2000; i++) {
6892                 DATA_BLOB blob1, blob2;
6893                 char *b64;
6894
6895                 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
6896                 blob1.length = i;
6897                 generate_random_buffer(blob1.data, blob1.length);
6898
6899                 b64 = base64_encode_data_blob(talloc_tos(), blob1);
6900                 if (b64 == NULL) {
6901                         d_fprintf(stderr, "base64_encode_data_blob failed "
6902                                   "for %d bytes\n", i);
6903                         ret = false;
6904                 }
6905                 blob2 = base64_decode_data_blob(b64);
6906                 TALLOC_FREE(b64);
6907
6908                 if (data_blob_cmp(&blob1, &blob2)) {
6909                         d_fprintf(stderr, "data_blob_cmp failed for %d "
6910                                   "bytes\n", i);
6911                         ret = false;
6912                 }
6913                 TALLOC_FREE(blob1.data);
6914                 data_blob_free(&blob2);
6915         }
6916         return ret;
6917 }
6918
6919 static bool run_local_gencache(int dummy)
6920 {
6921         char *val;
6922         time_t tm;
6923         DATA_BLOB blob;
6924
6925         if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
6926                 d_printf("%s: gencache_set() failed\n", __location__);
6927                 return False;
6928         }
6929
6930         if (!gencache_get("foo", NULL, NULL)) {
6931                 d_printf("%s: gencache_get() failed\n", __location__);
6932                 return False;
6933         }
6934
6935         if (!gencache_get("foo", &val, &tm)) {
6936                 d_printf("%s: gencache_get() failed\n", __location__);
6937                 return False;
6938         }
6939
6940         if (strcmp(val, "bar") != 0) {
6941                 d_printf("%s: gencache_get() returned %s, expected %s\n",
6942                          __location__, val, "bar");
6943                 SAFE_FREE(val);
6944                 return False;
6945         }
6946
6947         SAFE_FREE(val);
6948
6949         if (!gencache_del("foo")) {
6950                 d_printf("%s: gencache_del() failed\n", __location__);
6951                 return False;
6952         }
6953         if (gencache_del("foo")) {
6954                 d_printf("%s: second gencache_del() succeeded\n",
6955                          __location__);
6956                 return False;
6957         }
6958
6959         if (gencache_get("foo", &val, &tm)) {
6960                 d_printf("%s: gencache_get() on deleted entry "
6961                          "succeeded\n", __location__);
6962                 return False;
6963         }
6964
6965         blob = data_blob_string_const_null("bar");
6966         tm = time(NULL) + 60;
6967
6968         if (!gencache_set_data_blob("foo", &blob, tm)) {
6969                 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
6970                 return False;
6971         }
6972
6973         if (!gencache_get_data_blob("foo", &blob, NULL, NULL)) {
6974                 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
6975                 return False;
6976         }
6977
6978         if (strcmp((const char *)blob.data, "bar") != 0) {
6979                 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
6980                          __location__, (const char *)blob.data, "bar");
6981                 data_blob_free(&blob);
6982                 return False;
6983         }
6984
6985         data_blob_free(&blob);
6986
6987         if (!gencache_del("foo")) {
6988                 d_printf("%s: gencache_del() failed\n", __location__);
6989                 return False;
6990         }
6991         if (gencache_del("foo")) {
6992                 d_printf("%s: second gencache_del() succeeded\n",
6993                          __location__);
6994                 return False;
6995         }
6996
6997         if (gencache_get_data_blob("foo", &blob, NULL, NULL)) {
6998                 d_printf("%s: gencache_get_data_blob() on deleted entry "
6999                          "succeeded\n", __location__);
7000                 return False;
7001         }
7002
7003         return True;
7004 }
7005
7006 static bool rbt_testval(struct db_context *db, const char *key,
7007                         const char *value)
7008 {
7009         struct db_record *rec;
7010         TDB_DATA data = string_tdb_data(value);
7011         bool ret = false;
7012         NTSTATUS status;
7013
7014         rec = db->fetch_locked(db, db, string_tdb_data(key));
7015         if (rec == NULL) {
7016                 d_fprintf(stderr, "fetch_locked failed\n");
7017                 goto done;
7018         }
7019         status = rec->store(rec, data, 0);
7020         if (!NT_STATUS_IS_OK(status)) {
7021                 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
7022                 goto done;
7023         }
7024         TALLOC_FREE(rec);
7025
7026         rec = db->fetch_locked(db, db, string_tdb_data(key));
7027         if (rec == NULL) {
7028                 d_fprintf(stderr, "second fetch_locked failed\n");
7029                 goto done;
7030         }
7031         if ((rec->value.dsize != data.dsize)
7032             || (memcmp(rec->value.dptr, data.dptr, data.dsize) != 0)) {
7033                 d_fprintf(stderr, "Got wrong data back\n");
7034                 goto done;
7035         }
7036
7037         ret = true;
7038  done:
7039         TALLOC_FREE(rec);
7040         return ret;
7041 }
7042
7043 static bool run_local_rbtree(int dummy)
7044 {
7045         struct db_context *db;
7046         bool ret = false;
7047         int i;
7048
7049         db = db_open_rbt(NULL);
7050
7051         if (db == NULL) {
7052                 d_fprintf(stderr, "db_open_rbt failed\n");
7053                 return false;
7054         }
7055
7056         for (i=0; i<1000; i++) {
7057                 char *key, *value;
7058
7059                 if (asprintf(&key, "key%ld", random()) == -1) {
7060                         goto done;
7061                 }
7062                 if (asprintf(&value, "value%ld", random()) == -1) {
7063                         SAFE_FREE(key);
7064                         goto done;
7065                 }
7066
7067                 if (!rbt_testval(db, key, value)) {
7068                         SAFE_FREE(key);
7069                         SAFE_FREE(value);
7070                         goto done;
7071                 }
7072
7073                 SAFE_FREE(value);
7074                 if (asprintf(&value, "value%ld", random()) == -1) {
7075                         SAFE_FREE(key);
7076                         goto done;
7077                 }
7078
7079                 if (!rbt_testval(db, key, value)) {
7080                         SAFE_FREE(key);
7081                         SAFE_FREE(value);
7082                         goto done;
7083                 }
7084
7085                 SAFE_FREE(key);
7086                 SAFE_FREE(value);
7087         }
7088
7089         ret = true;
7090
7091  done:
7092         TALLOC_FREE(db);
7093         return ret;
7094 }
7095
7096 struct talloc_dict_test {
7097         int content;
7098 };
7099
7100 static int talloc_dict_traverse_fn(DATA_BLOB key, void *data, void *priv)
7101 {
7102         int *count = (int *)priv;
7103         *count += 1;
7104         return 0;
7105 }
7106
7107 static bool run_local_talloc_dict(int dummy)
7108 {
7109         struct talloc_dict *dict;
7110         struct talloc_dict_test *t;
7111         int key, count;
7112
7113         dict = talloc_dict_init(talloc_tos());
7114         if (dict == NULL) {
7115                 return false;
7116         }
7117
7118         t = talloc(talloc_tos(), struct talloc_dict_test);
7119         if (t == NULL) {
7120                 return false;
7121         }
7122
7123         key = 1;
7124         t->content = 1;
7125         if (!talloc_dict_set(dict, data_blob_const(&key, sizeof(key)), t)) {
7126                 return false;
7127         }
7128
7129         count = 0;
7130         if (talloc_dict_traverse(dict, talloc_dict_traverse_fn, &count) != 0) {
7131                 return false;
7132         }
7133
7134         if (count != 1) {
7135                 return false;
7136         }
7137
7138         TALLOC_FREE(dict);
7139
7140         return true;
7141 }
7142
7143 static bool run_local_string_to_sid(int dummy) {
7144         struct dom_sid sid;
7145
7146         if (string_to_sid(&sid, "S--1-5-32-545")) {
7147                 printf("allowing S--1-5-32-545\n");
7148                 return false;
7149         }
7150         if (string_to_sid(&sid, "S-1-5-32-+545")) {
7151                 printf("allowing S-1-5-32-+545\n");
7152                 return false;
7153         }
7154         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")) {
7155                 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
7156                 return false;
7157         }
7158         if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
7159                 printf("allowing S-1-5-32-545-abc\n");
7160                 return false;
7161         }
7162         if (!string_to_sid(&sid, "S-1-5-32-545")) {
7163                 printf("could not parse S-1-5-32-545\n");
7164                 return false;
7165         }
7166         if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
7167                 printf("mis-parsed S-1-5-32-545 as %s\n",
7168                        sid_string_tos(&sid));
7169                 return false;
7170         }
7171         return true;
7172 }
7173
7174 static bool run_local_binary_to_sid(int dummy) {
7175         struct dom_sid *sid = talloc(NULL, struct dom_sid);
7176         static const char good_binary_sid[] = {
7177                 0x1, /* revision number */
7178                 15, /* num auths */
7179                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
7180                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
7181                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
7182                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
7183                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
7184                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
7185                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
7186                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
7187                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
7188                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
7189                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
7190                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
7191                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
7192                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
7193                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
7194                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
7195         };
7196
7197         static const char long_binary_sid[] = {
7198                 0x1, /* revision number */
7199                 15, /* num auths */
7200                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
7201                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
7202                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
7203                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
7204                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
7205                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
7206                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
7207                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
7208                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
7209                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
7210                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
7211                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
7212                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
7213                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
7214                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
7215                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
7216                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
7217                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
7218                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
7219         };
7220
7221         static const char long_binary_sid2[] = {
7222                 0x1, /* revision number */
7223                 32, /* num auths */
7224                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
7225                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
7226                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
7227                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
7228                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
7229                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
7230                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
7231                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
7232                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
7233                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
7234                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
7235                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
7236                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
7237                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
7238                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
7239                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
7240                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
7241                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
7242                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
7243                 0x1, 0x1, 0x1, 0x1, /* auth[18] */
7244                 0x1, 0x1, 0x1, 0x1, /* auth[19] */
7245                 0x1, 0x1, 0x1, 0x1, /* auth[20] */
7246                 0x1, 0x1, 0x1, 0x1, /* auth[21] */
7247                 0x1, 0x1, 0x1, 0x1, /* auth[22] */
7248                 0x1, 0x1, 0x1, 0x1, /* auth[23] */
7249                 0x1, 0x1, 0x1, 0x1, /* auth[24] */
7250                 0x1, 0x1, 0x1, 0x1, /* auth[25] */
7251                 0x1, 0x1, 0x1, 0x1, /* auth[26] */
7252                 0x1, 0x1, 0x1, 0x1, /* auth[27] */
7253                 0x1, 0x1, 0x1, 0x1, /* auth[28] */
7254                 0x1, 0x1, 0x1, 0x1, /* auth[29] */
7255                 0x1, 0x1, 0x1, 0x1, /* auth[30] */
7256                 0x1, 0x1, 0x1, 0x1, /* auth[31] */
7257         };
7258
7259         if (!sid_parse(good_binary_sid, sizeof(good_binary_sid), sid)) {
7260                 return false;
7261         }
7262         if (sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid)) {
7263                 return false;
7264         }
7265         if (sid_parse(long_binary_sid, sizeof(long_binary_sid), sid)) {
7266                 return false;
7267         }
7268         return true;
7269 }
7270
7271 /* Split a path name into filename and stream name components. Canonicalise
7272  * such that an implicit $DATA token is always explicit.
7273  *
7274  * The "specification" of this function can be found in the
7275  * run_local_stream_name() function in torture.c, I've tried those
7276  * combinations against a W2k3 server.
7277  */
7278
7279 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
7280                                        char **pbase, char **pstream)
7281 {
7282         char *base = NULL;
7283         char *stream = NULL;
7284         char *sname; /* stream name */
7285         const char *stype; /* stream type */
7286
7287         DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
7288
7289         sname = strchr_m(fname, ':');
7290
7291         if (lp_posix_pathnames() || (sname == NULL)) {
7292                 if (pbase != NULL) {
7293                         base = talloc_strdup(mem_ctx, fname);
7294                         NT_STATUS_HAVE_NO_MEMORY(base);
7295                 }
7296                 goto done;
7297         }
7298
7299         if (pbase != NULL) {
7300                 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
7301                 NT_STATUS_HAVE_NO_MEMORY(base);
7302         }
7303
7304         sname += 1;
7305
7306         stype = strchr_m(sname, ':');
7307
7308         if (stype == NULL) {
7309                 sname = talloc_strdup(mem_ctx, sname);
7310                 stype = "$DATA";
7311         }
7312         else {
7313                 if (StrCaseCmp(stype, ":$DATA") != 0) {
7314                         /*
7315                          * If there is an explicit stream type, so far we only
7316                          * allow $DATA. Is there anything else allowed? -- vl
7317                          */
7318                         DEBUG(10, ("[%s] is an invalid stream type\n", stype));
7319                         TALLOC_FREE(base);
7320                         return NT_STATUS_OBJECT_NAME_INVALID;
7321                 }
7322                 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
7323                 stype += 1;
7324         }
7325
7326         if (sname == NULL) {
7327                 TALLOC_FREE(base);
7328                 return NT_STATUS_NO_MEMORY;
7329         }
7330
7331         if (sname[0] == '\0') {
7332                 /*
7333                  * no stream name, so no stream
7334                  */
7335                 goto done;
7336         }
7337
7338         if (pstream != NULL) {
7339                 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
7340                 if (stream == NULL) {
7341                         TALLOC_FREE(sname);
7342                         TALLOC_FREE(base);
7343                         return NT_STATUS_NO_MEMORY;
7344                 }
7345                 /*
7346                  * upper-case the type field
7347                  */
7348                 strupper_m(strchr_m(stream, ':')+1);
7349         }
7350
7351  done:
7352         if (pbase != NULL) {
7353                 *pbase = base;
7354         }
7355         if (pstream != NULL) {
7356                 *pstream = stream;
7357         }
7358         return NT_STATUS_OK;
7359 }
7360
7361 static bool test_stream_name(const char *fname, const char *expected_base,
7362                              const char *expected_stream,
7363                              NTSTATUS expected_status)
7364 {
7365         NTSTATUS status;
7366         char *base = NULL;
7367         char *stream = NULL;
7368
7369         status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
7370         if (!NT_STATUS_EQUAL(status, expected_status)) {
7371                 goto error;
7372         }
7373
7374         if (!NT_STATUS_IS_OK(status)) {
7375                 return true;
7376         }
7377
7378         if (base == NULL) goto error;
7379
7380         if (strcmp(expected_base, base) != 0) goto error;
7381
7382         if ((expected_stream != NULL) && (stream == NULL)) goto error;
7383         if ((expected_stream == NULL) && (stream != NULL)) goto error;
7384
7385         if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
7386                 goto error;
7387
7388         TALLOC_FREE(base);
7389         TALLOC_FREE(stream);
7390         return true;
7391
7392  error:
7393         d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
7394                   fname, expected_base ? expected_base : "<NULL>",
7395                   expected_stream ? expected_stream : "<NULL>",
7396                   nt_errstr(expected_status));
7397         d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
7398                   base ? base : "<NULL>", stream ? stream : "<NULL>",
7399                   nt_errstr(status));
7400         TALLOC_FREE(base);
7401         TALLOC_FREE(stream);
7402         return false;
7403 }
7404
7405 static bool run_local_stream_name(int dummy)
7406 {
7407         bool ret = true;
7408
7409         ret &= test_stream_name(
7410                 "bla", "bla", NULL, NT_STATUS_OK);
7411         ret &= test_stream_name(
7412                 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
7413         ret &= test_stream_name(
7414                 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
7415         ret &= test_stream_name(
7416                 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
7417         ret &= test_stream_name(
7418                 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
7419         ret &= test_stream_name(
7420                 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
7421         ret &= test_stream_name(
7422                 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
7423         ret &= test_stream_name(
7424                 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
7425
7426         return ret;
7427 }
7428
7429 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
7430 {
7431         if (a.length != b.length) {
7432                 printf("a.length=%d != b.length=%d\n",
7433                        (int)a.length, (int)b.length);
7434                 return false;
7435         }
7436         if (memcmp(a.data, b.data, a.length) != 0) {
7437                 printf("a.data and b.data differ\n");
7438                 return false;
7439         }
7440         return true;
7441 }
7442
7443 static bool run_local_memcache(int dummy)
7444 {
7445         struct memcache *cache;
7446         DATA_BLOB k1, k2;
7447         DATA_BLOB d1, d2, d3;
7448         DATA_BLOB v1, v2, v3;
7449
7450         TALLOC_CTX *mem_ctx;
7451         char *str1, *str2;
7452         size_t size1, size2;
7453         bool ret = false;
7454
7455         cache = memcache_init(NULL, 100);
7456
7457         if (cache == NULL) {
7458                 printf("memcache_init failed\n");
7459                 return false;
7460         }
7461
7462         d1 = data_blob_const("d1", 2);
7463         d2 = data_blob_const("d2", 2);
7464         d3 = data_blob_const("d3", 2);
7465
7466         k1 = data_blob_const("d1", 2);
7467         k2 = data_blob_const("d2", 2);
7468
7469         memcache_add(cache, STAT_CACHE, k1, d1);
7470         memcache_add(cache, GETWD_CACHE, k2, d2);
7471
7472         if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
7473                 printf("could not find k1\n");
7474                 return false;
7475         }
7476         if (!data_blob_equal(d1, v1)) {
7477                 return false;
7478         }
7479
7480         if (!memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
7481                 printf("could not find k2\n");
7482                 return false;
7483         }
7484         if (!data_blob_equal(d2, v2)) {
7485                 return false;
7486         }
7487
7488         memcache_add(cache, STAT_CACHE, k1, d3);
7489
7490         if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
7491                 printf("could not find replaced k1\n");
7492                 return false;
7493         }
7494         if (!data_blob_equal(d3, v3)) {
7495                 return false;
7496         }
7497
7498         memcache_add(cache, GETWD_CACHE, k1, d1);
7499
7500         if (memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
7501                 printf("Did find k2, should have been purged\n");
7502                 return false;
7503         }
7504
7505         TALLOC_FREE(cache);
7506
7507         cache = memcache_init(NULL, 0);
7508
7509         mem_ctx = talloc_init("foo");
7510
7511         str1 = talloc_strdup(mem_ctx, "string1");
7512         str2 = talloc_strdup(mem_ctx, "string2");
7513
7514         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
7515                             data_blob_string_const("torture"), &str1);
7516         size1 = talloc_total_size(cache);
7517
7518         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
7519                             data_blob_string_const("torture"), &str2);
7520         size2 = talloc_total_size(cache);
7521
7522         printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
7523
7524         if (size2 > size1) {
7525                 printf("memcache leaks memory!\n");
7526                 goto fail;
7527         }
7528
7529         ret = true;
7530  fail:
7531         TALLOC_FREE(cache);
7532         return ret;
7533 }
7534
7535 static void wbclient_done(struct tevent_req *req)
7536 {
7537         wbcErr wbc_err;
7538         struct winbindd_response *wb_resp;
7539         int *i = (int *)tevent_req_callback_data_void(req);
7540
7541         wbc_err = wb_trans_recv(req, req, &wb_resp);
7542         TALLOC_FREE(req);
7543         *i += 1;
7544         d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
7545 }
7546
7547 static bool run_local_wbclient(int dummy)
7548 {
7549         struct event_context *ev;
7550         struct wb_context **wb_ctx;
7551         struct winbindd_request wb_req;
7552         bool result = false;
7553         int i, j;
7554
7555         BlockSignals(True, SIGPIPE);
7556
7557         ev = tevent_context_init_byname(talloc_tos(), "epoll");
7558         if (ev == NULL) {
7559                 goto fail;
7560         }
7561
7562         wb_ctx = TALLOC_ARRAY(ev, struct wb_context *, nprocs);
7563         if (wb_ctx == NULL) {
7564                 goto fail;
7565         }
7566
7567         ZERO_STRUCT(wb_req);
7568         wb_req.cmd = WINBINDD_PING;
7569
7570         d_printf("nprocs=%d, numops=%d\n", (int)nprocs, (int)torture_numops);
7571
7572         for (i=0; i<nprocs; i++) {
7573                 wb_ctx[i] = wb_context_init(ev, NULL);
7574                 if (wb_ctx[i] == NULL) {
7575                         goto fail;
7576                 }
7577                 for (j=0; j<torture_numops; j++) {
7578                         struct tevent_req *req;
7579                         req = wb_trans_send(ev, ev, wb_ctx[i],
7580                                             (j % 2) == 0, &wb_req);
7581                         if (req == NULL) {
7582                                 goto fail;
7583                         }
7584                         tevent_req_set_callback(req, wbclient_done, &i);
7585                 }
7586         }
7587
7588         i = 0;
7589
7590         while (i < nprocs * torture_numops) {
7591                 event_loop_once(ev);
7592         }
7593
7594         result = true;
7595  fail:
7596         TALLOC_FREE(ev);
7597         return result;
7598 }
7599
7600 static void getaddrinfo_finished(struct tevent_req *req)
7601 {
7602         char *name = (char *)tevent_req_callback_data_void(req);
7603         struct addrinfo *ainfo;
7604         int res;
7605
7606         res = getaddrinfo_recv(req, &ainfo);
7607         if (res != 0) {
7608                 d_printf("gai(%s) returned %s\n", name, gai_strerror(res));
7609                 return;
7610         }
7611         d_printf("gai(%s) succeeded\n", name);
7612         freeaddrinfo(ainfo);
7613 }
7614
7615 static bool run_getaddrinfo_send(int dummy)
7616 {
7617         TALLOC_CTX *frame = talloc_stackframe();
7618         struct fncall_context *ctx;
7619         struct tevent_context *ev;
7620         bool result = false;
7621         const char *names[4] = { "www.samba.org", "notfound.samba.org",
7622                                  "www.slashdot.org", "heise.de" };
7623         struct tevent_req *reqs[4];
7624         int i;
7625
7626         ev = event_context_init(frame);
7627         if (ev == NULL) {
7628                 goto fail;
7629         }
7630
7631         ctx = fncall_context_init(frame, 4);
7632
7633         for (i=0; i<ARRAY_SIZE(names); i++) {
7634                 reqs[i] = getaddrinfo_send(frame, ev, ctx, names[i], NULL,
7635                                            NULL);
7636                 if (reqs[i] == NULL) {
7637                         goto fail;
7638                 }
7639                 tevent_req_set_callback(reqs[i], getaddrinfo_finished,
7640                                         (void *)names[i]);
7641         }
7642
7643         for (i=0; i<ARRAY_SIZE(reqs); i++) {
7644                 tevent_loop_once(ev);
7645         }
7646
7647         result = true;
7648 fail:
7649         TALLOC_FREE(frame);
7650         return result;
7651 }
7652
7653 static bool dbtrans_inc(struct db_context *db)
7654 {
7655         struct db_record *rec;
7656         uint32_t *val;
7657         bool ret = false;
7658         NTSTATUS status;
7659
7660         rec = db->fetch_locked(db, db, string_term_tdb_data("transtest"));
7661         if (rec == NULL) {
7662                 printf(__location__ "fetch_lock failed\n");
7663                 return false;
7664         }
7665
7666         if (rec->value.dsize != sizeof(uint32_t)) {
7667                 printf(__location__ "value.dsize = %d\n",
7668                        (int)rec->value.dsize);
7669                 goto fail;
7670         }
7671
7672         val = (uint32_t *)rec->value.dptr;
7673         *val += 1;
7674
7675         status = rec->store(rec, make_tdb_data((uint8_t *)val,
7676                                                sizeof(uint32_t)),
7677                             0);
7678         if (!NT_STATUS_IS_OK(status)) {
7679                 printf(__location__ "store failed: %s\n",
7680                        nt_errstr(status));
7681                 goto fail;
7682         }
7683
7684         ret = true;
7685 fail:
7686         TALLOC_FREE(rec);
7687         return ret;
7688 }
7689
7690 static bool run_local_dbtrans(int dummy)
7691 {
7692         struct db_context *db;
7693         struct db_record *rec;
7694         NTSTATUS status;
7695         uint32_t initial;
7696         int res;
7697
7698         db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
7699                      O_RDWR|O_CREAT, 0600);
7700         if (db == NULL) {
7701                 printf("Could not open transtest.db\n");
7702                 return false;
7703         }
7704
7705         res = db->transaction_start(db);
7706         if (res == -1) {
7707                 printf(__location__ "transaction_start failed\n");
7708                 return false;
7709         }
7710
7711         rec = db->fetch_locked(db, db, string_term_tdb_data("transtest"));
7712         if (rec == NULL) {
7713                 printf(__location__ "fetch_lock failed\n");
7714                 return false;
7715         }
7716
7717         if (rec->value.dptr == NULL) {
7718                 initial = 0;
7719                 status = rec->store(
7720                         rec, make_tdb_data((uint8_t *)&initial,
7721                                            sizeof(initial)),
7722                         0);
7723                 if (!NT_STATUS_IS_OK(status)) {
7724                         printf(__location__ "store returned %s\n",
7725                                nt_errstr(status));
7726                         return false;
7727                 }
7728         }
7729
7730         TALLOC_FREE(rec);
7731
7732         res = db->transaction_commit(db);
7733         if (res == -1) {
7734                 printf(__location__ "transaction_commit failed\n");
7735                 return false;
7736         }
7737
7738         while (true) {
7739                 uint32_t val, val2;
7740                 int i;
7741
7742                 res = db->transaction_start(db);
7743                 if (res == -1) {
7744                         printf(__location__ "transaction_start failed\n");
7745                         break;
7746                 }
7747
7748                 if (!dbwrap_fetch_uint32(db, "transtest", &val)) {
7749                         printf(__location__ "dbwrap_fetch_uint32 failed\n");
7750                         break;
7751                 }
7752
7753                 for (i=0; i<10; i++) {
7754                         if (!dbtrans_inc(db)) {
7755                                 return false;
7756                         }
7757                 }
7758
7759                 if (!dbwrap_fetch_uint32(db, "transtest", &val2)) {
7760                         printf(__location__ "dbwrap_fetch_uint32 failed\n");
7761                         break;
7762                 }
7763
7764                 if (val2 != val + 10) {
7765                         printf(__location__ "val=%d, val2=%d\n",
7766                                (int)val, (int)val2);
7767                         break;
7768                 }
7769
7770                 printf("val2=%d\r", val2);
7771
7772                 res = db->transaction_commit(db);
7773                 if (res == -1) {
7774                         printf(__location__ "transaction_commit failed\n");
7775                         break;
7776                 }
7777         }
7778
7779         TALLOC_FREE(db);
7780         return true;
7781 }
7782
7783 /*
7784  * Just a dummy test to be run under a debugger. There's no real way
7785  * to inspect the tevent_select specific function from outside of
7786  * tevent_select.c.
7787  */
7788
7789 static bool run_local_tevent_select(int dummy)
7790 {
7791         struct tevent_context *ev;
7792         struct tevent_fd *fd1, *fd2;
7793         bool result = false;
7794
7795         ev = tevent_context_init_byname(NULL, "select");
7796         if (ev == NULL) {
7797                 d_fprintf(stderr, "tevent_context_init_byname failed\n");
7798                 goto fail;
7799         }
7800
7801         fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
7802         if (fd1 == NULL) {
7803                 d_fprintf(stderr, "tevent_add_fd failed\n");
7804                 goto fail;
7805         }
7806         fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
7807         if (fd2 == NULL) {
7808                 d_fprintf(stderr, "tevent_add_fd failed\n");
7809                 goto fail;
7810         }
7811         TALLOC_FREE(fd2);
7812
7813         fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
7814         if (fd2 == NULL) {
7815                 d_fprintf(stderr, "tevent_add_fd failed\n");
7816                 goto fail;
7817         }
7818
7819         result = true;
7820 fail:
7821         TALLOC_FREE(ev);
7822         return result;
7823 }
7824
7825 static double create_procs(bool (*fn)(int), bool *result)
7826 {
7827         int i, status;
7828         volatile pid_t *child_status;
7829         volatile bool *child_status_out;
7830         int synccount;
7831         int tries = 8;
7832         struct timeval start;
7833
7834         synccount = 0;
7835
7836         child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*nprocs);
7837         if (!child_status) {
7838                 printf("Failed to setup shared memory\n");
7839                 return -1;
7840         }
7841
7842         child_status_out = (volatile bool *)shm_setup(sizeof(bool)*nprocs);
7843         if (!child_status_out) {
7844                 printf("Failed to setup result status shared memory\n");
7845                 return -1;
7846         }
7847
7848         for (i = 0; i < nprocs; i++) {
7849                 child_status[i] = 0;
7850                 child_status_out[i] = True;
7851         }
7852
7853         start = timeval_current();
7854
7855         for (i=0;i<nprocs;i++) {
7856                 procnum = i;
7857                 if (fork() == 0) {
7858                         pid_t mypid = getpid();
7859                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
7860
7861                         slprintf(myname,sizeof(myname),"CLIENT%d", i);
7862
7863                         while (1) {
7864                                 if (torture_open_connection(&current_cli, i)) break;
7865                                 if (tries-- == 0) {
7866                                         printf("pid %d failed to start\n", (int)getpid());
7867                                         _exit(1);
7868                                 }
7869                                 smb_msleep(10); 
7870                         }
7871
7872                         child_status[i] = getpid();
7873
7874                         while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
7875
7876                         child_status_out[i] = fn(i);
7877                         _exit(0);
7878                 }
7879         }
7880
7881         do {
7882                 synccount = 0;
7883                 for (i=0;i<nprocs;i++) {
7884                         if (child_status[i]) synccount++;
7885                 }
7886                 if (synccount == nprocs) break;
7887                 smb_msleep(10);
7888         } while (timeval_elapsed(&start) < 30);
7889
7890         if (synccount != nprocs) {
7891                 printf("FAILED TO START %d CLIENTS (started %d)\n", nprocs, synccount);
7892                 *result = False;
7893                 return timeval_elapsed(&start);
7894         }
7895
7896         /* start the client load */
7897         start = timeval_current();
7898
7899         for (i=0;i<nprocs;i++) {
7900                 child_status[i] = 0;
7901         }
7902
7903         printf("%d clients started\n", nprocs);
7904
7905         for (i=0;i<nprocs;i++) {
7906                 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
7907         }
7908
7909         printf("\n");
7910
7911         for (i=0;i<nprocs;i++) {
7912                 if (!child_status_out[i]) {
7913                         *result = False;
7914                 }
7915         }
7916         return timeval_elapsed(&start);
7917 }
7918
7919 #define FLAG_MULTIPROC 1
7920
7921 static struct {
7922         const char *name;
7923         bool (*fn)(int);
7924         unsigned flags;
7925 } torture_ops[] = {
7926         {"FDPASS", run_fdpasstest, 0},
7927         {"LOCK1",  run_locktest1,  0},
7928         {"LOCK2",  run_locktest2,  0},
7929         {"LOCK3",  run_locktest3,  0},
7930         {"LOCK4",  run_locktest4,  0},
7931         {"LOCK5",  run_locktest5,  0},
7932         {"LOCK6",  run_locktest6,  0},
7933         {"LOCK7",  run_locktest7,  0},
7934         {"LOCK8",  run_locktest8,  0},
7935         {"LOCK9",  run_locktest9,  0},
7936         {"UNLINK", run_unlinktest, 0},
7937         {"BROWSE", run_browsetest, 0},
7938         {"ATTR",   run_attrtest,   0},
7939         {"TRANS2", run_trans2test, 0},
7940         {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
7941         {"TORTURE",run_torture,    FLAG_MULTIPROC},
7942         {"RANDOMIPC", run_randomipc, 0},
7943         {"NEGNOWAIT", run_negprot_nowait, 0},
7944         {"NBENCH",  run_nbench, 0},
7945         {"NBENCH2", run_nbench2, 0},
7946         {"OPLOCK1",  run_oplock1, 0},
7947         {"OPLOCK2",  run_oplock2, 0},
7948         {"OPLOCK3",  run_oplock3, 0},
7949         {"OPLOCK4",  run_oplock4, 0},
7950         {"DIR",  run_dirtest, 0},
7951         {"DIR1",  run_dirtest1, 0},
7952         {"DIR-CREATETIME",  run_dir_createtime, 0},
7953         {"DENY1",  torture_denytest1, 0},
7954         {"DENY2",  torture_denytest2, 0},
7955         {"TCON",  run_tcon_test, 0},
7956         {"TCONDEV",  run_tcon_devtype_test, 0},
7957         {"RW1",  run_readwritetest, 0},
7958         {"RW2",  run_readwritemulti, FLAG_MULTIPROC},
7959         {"RW3",  run_readwritelarge, 0},
7960         {"RW-SIGNING",  run_readwritelarge_signtest, 0},
7961         {"OPEN", run_opentest, 0},
7962         {"POSIX", run_simple_posix_open_test, 0},
7963         {"POSIX-APPEND", run_posix_append, 0},
7964         {"ASYNC-ECHO", run_async_echo, 0},
7965         { "UID-REGRESSION-TEST", run_uid_regression_test, 0},
7966         { "SHORTNAME-TEST", run_shortname_test, 0},
7967 #if 1
7968         {"OPENATTR", run_openattrtest, 0},
7969 #endif
7970         {"XCOPY", run_xcopy, 0},
7971         {"RENAME", run_rename, 0},
7972         {"DELETE", run_deletetest, 0},
7973         {"PROPERTIES", run_properties, 0},
7974         {"MANGLE", torture_mangle, 0},
7975         {"MANGLE1", run_mangle1, 0},
7976         {"W2K", run_w2ktest, 0},
7977         {"TRANS2SCAN", torture_trans2_scan, 0},
7978         {"NTTRANSSCAN", torture_nttrans_scan, 0},
7979         {"UTABLE", torture_utable, 0},
7980         {"CASETABLE", torture_casetable, 0},
7981         {"ERRMAPEXTRACT", run_error_map_extract, 0},
7982         {"PIPE_NUMBER", run_pipe_number, 0},
7983         {"TCON2",  run_tcon2_test, 0},
7984         {"IOCTL",  torture_ioctl_test, 0},
7985         {"CHKPATH",  torture_chkpath_test, 0},
7986         {"FDSESS", run_fdsesstest, 0},
7987         { "EATEST", run_eatest, 0},
7988         { "SESSSETUP_BENCH", run_sesssetup_bench, 0},
7989         { "CHAIN1", run_chain1, 0},
7990         { "CHAIN2", run_chain2, 0},
7991         { "WINDOWS-WRITE", run_windows_write, 0},
7992         { "CLI_ECHO", run_cli_echo, 0},
7993         { "GETADDRINFO", run_getaddrinfo_send, 0},
7994         { "TLDAP", run_tldap },
7995         { "STREAMERROR", run_streamerror },
7996         { "NOTIFY-BENCH", run_notify_bench },
7997         { "BAD-NBT-SESSION", run_bad_nbt_session },
7998         { "SMB-ANY-CONNECT", run_smb_any_connect },
7999         { "LOCAL-SUBSTITUTE", run_local_substitute, 0},
8000         { "LOCAL-GENCACHE", run_local_gencache, 0},
8001         { "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0},
8002         { "LOCAL-BASE64", run_local_base64, 0},
8003         { "LOCAL-RBTREE", run_local_rbtree, 0},
8004         { "LOCAL-MEMCACHE", run_local_memcache, 0},
8005         { "LOCAL-STREAM-NAME", run_local_stream_name, 0},
8006         { "LOCAL-WBCLIENT", run_local_wbclient, 0},
8007         { "LOCAL-string_to_sid", run_local_string_to_sid, 0},
8008         { "LOCAL-binary_to_sid", run_local_binary_to_sid, 0},
8009         { "LOCAL-DBTRANS", run_local_dbtrans, 0},
8010         { "LOCAL-TEVENT-SELECT", run_local_tevent_select, 0},
8011         {NULL, NULL, 0}};
8012
8013
8014
8015 /****************************************************************************
8016 run a specified test or "ALL"
8017 ****************************************************************************/
8018 static bool run_test(const char *name)
8019 {
8020         bool ret = True;
8021         bool result = True;
8022         bool found = False;
8023         int i;
8024         double t;
8025         if (strequal(name,"ALL")) {
8026                 for (i=0;torture_ops[i].name;i++) {
8027                         run_test(torture_ops[i].name);
8028                 }
8029                 found = True;
8030         }
8031
8032         for (i=0;torture_ops[i].name;i++) {
8033                 fstr_sprintf(randomfname, "\\XX%x", 
8034                          (unsigned)random());
8035
8036                 if (strequal(name, torture_ops[i].name)) {
8037                         found = True;
8038                         printf("Running %s\n", name);
8039                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
8040                                 t = create_procs(torture_ops[i].fn, &result);
8041                                 if (!result) { 
8042                                         ret = False;
8043                                         printf("TEST %s FAILED!\n", name);
8044                                 }
8045                         } else {
8046                                 struct timeval start;
8047                                 start = timeval_current();
8048                                 if (!torture_ops[i].fn(0)) {
8049                                         ret = False;
8050                                         printf("TEST %s FAILED!\n", name);
8051                                 }
8052                                 t = timeval_elapsed(&start);
8053                         }
8054                         printf("%s took %g secs\n\n", name, t);
8055                 }
8056         }
8057
8058         if (!found) {
8059                 printf("Did not find a test named %s\n", name);
8060                 ret = False;
8061         }
8062
8063         return ret;
8064 }
8065
8066
8067 static void usage(void)
8068 {
8069         int i;
8070
8071         printf("WARNING samba4 test suite is much more complete nowadays.\n");
8072         printf("Please use samba4 torture.\n\n");
8073
8074         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
8075
8076         printf("\t-d debuglevel\n");
8077         printf("\t-U user%%pass\n");
8078         printf("\t-k               use kerberos\n");
8079         printf("\t-N numprocs\n");
8080         printf("\t-n my_netbios_name\n");
8081         printf("\t-W workgroup\n");
8082         printf("\t-o num_operations\n");
8083         printf("\t-O socket_options\n");
8084         printf("\t-m maximum protocol\n");
8085         printf("\t-L use oplocks\n");
8086         printf("\t-c CLIENT.TXT   specify client load file for NBENCH\n");
8087         printf("\t-A showall\n");
8088         printf("\t-p port\n");
8089         printf("\t-s seed\n");
8090         printf("\t-b unclist_filename   specify multiple shares for multiple connections\n");
8091         printf("\n\n");
8092
8093         printf("tests are:");
8094         for (i=0;torture_ops[i].name;i++) {
8095                 printf(" %s", torture_ops[i].name);
8096         }
8097         printf("\n");
8098
8099         printf("default test is ALL\n");
8100
8101         exit(1);
8102 }
8103
8104 /****************************************************************************
8105   main program
8106 ****************************************************************************/
8107  int main(int argc,char *argv[])
8108 {
8109         int opt, i;
8110         char *p;
8111         int gotuser = 0;
8112         int gotpass = 0;
8113         bool correct = True;
8114         TALLOC_CTX *frame = talloc_stackframe();
8115         int seed = time(NULL);
8116
8117 #ifdef HAVE_SETBUFFER
8118         setbuffer(stdout, NULL, 0);
8119 #endif
8120
8121         setup_logging("smbtorture", DEBUG_STDOUT);
8122
8123         load_case_tables();
8124
8125         if (is_default_dyn_CONFIGFILE()) {
8126                 if(getenv("SMB_CONF_PATH")) {
8127                         set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
8128                 }
8129         }
8130         lp_load(get_dyn_CONFIGFILE(),True,False,False,True);
8131         load_interfaces();
8132
8133         if (argc < 2) {
8134                 usage();
8135         }
8136
8137         for(p = argv[1]; *p; p++)
8138           if(*p == '\\')
8139             *p = '/';
8140
8141         if (strncmp(argv[1], "//", 2)) {
8142                 usage();
8143         }
8144
8145         fstrcpy(host, &argv[1][2]);
8146         p = strchr_m(&host[2],'/');
8147         if (!p) {
8148                 usage();
8149         }
8150         *p = 0;
8151         fstrcpy(share, p+1);
8152
8153         fstrcpy(myname, get_myname(talloc_tos()));
8154         if (!*myname) {
8155                 fprintf(stderr, "Failed to get my hostname.\n");
8156                 return 1;
8157         }
8158
8159         if (*username == 0 && getenv("LOGNAME")) {
8160           fstrcpy(username,getenv("LOGNAME"));
8161         }
8162
8163         argc--;
8164         argv++;
8165
8166         fstrcpy(workgroup, lp_workgroup());
8167
8168         while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:")) != EOF) {
8169                 switch (opt) {
8170                 case 'p':
8171                         port_to_use = atoi(optarg);
8172                         break;
8173                 case 's':
8174                         seed = atoi(optarg);
8175                         break;
8176                 case 'W':
8177                         fstrcpy(workgroup,optarg);
8178                         break;
8179                 case 'm':
8180                         max_protocol = interpret_protocol(optarg, max_protocol);
8181                         break;
8182                 case 'N':
8183                         nprocs = atoi(optarg);
8184                         break;
8185                 case 'o':
8186                         torture_numops = atoi(optarg);
8187                         break;
8188                 case 'd':
8189                         lp_set_cmdline("log level", optarg);
8190                         break;
8191                 case 'O':
8192                         sockops = optarg;
8193                         break;
8194                 case 'L':
8195                         use_oplocks = True;
8196                         break;
8197                 case 'l':
8198                         local_path = optarg;
8199                         break;
8200                 case 'A':
8201                         torture_showall = True;
8202                         break;
8203                 case 'n':
8204                         fstrcpy(myname, optarg);
8205                         break;
8206                 case 'c':
8207                         client_txt = optarg;
8208                         break;
8209                 case 'e':
8210                         do_encrypt = true;
8211                         break;
8212                 case 'k':
8213 #ifdef HAVE_KRB5
8214                         use_kerberos = True;
8215 #else
8216                         d_printf("No kerberos support compiled in\n");
8217                         exit(1);
8218 #endif
8219                         break;
8220                 case 'U':
8221                         gotuser = 1;
8222                         fstrcpy(username,optarg);
8223                         p = strchr_m(username,'%');
8224                         if (p) {
8225                                 *p = 0;
8226                                 fstrcpy(password, p+1);
8227                                 gotpass = 1;
8228                         }
8229                         break;
8230                 case 'b':
8231                         fstrcpy(multishare_conn_fname, optarg);
8232                         use_multishare_conn = True;
8233                         break;
8234                 case 'B':
8235                         torture_blocksize = atoi(optarg);
8236                         break;
8237                 default:
8238                         printf("Unknown option %c (%d)\n", (char)opt, opt);
8239                         usage();
8240                 }
8241         }
8242
8243         d_printf("using seed %d\n", seed);
8244
8245         srandom(seed);
8246
8247         if(use_kerberos && !gotuser) gotpass = True;
8248
8249         while (!gotpass) {
8250                 p = getpass("Password:");
8251                 if (p) {
8252                         fstrcpy(password, p);
8253                         gotpass = 1;
8254                 }
8255         }
8256
8257         printf("host=%s share=%s user=%s myname=%s\n", 
8258                host, share, username, myname);
8259
8260         if (argc == optind) {
8261                 correct = run_test("ALL");
8262         } else {
8263                 for (i=optind;i<argc;i++) {
8264                         if (!run_test(argv[i])) {
8265                                 correct = False;
8266                         }
8267                 }
8268         }
8269
8270         TALLOC_FREE(frame);
8271
8272         if (correct) {
8273                 return(0);
8274         } else {
8275                 return(1);
8276         }
8277 }