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