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