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