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