s3-torture: let wait_lock() use cli_lock32() instead of cli_lock()
[Samba/gebeck_regimport.git] / source3 / torture / torture.c
blob41ea8c1ad89132428460dc324323190661ee55a4
1 /*
2 Unix SMB/CIFS implementation.
3 SMB torture tester
4 Copyright (C) Andrew Tridgell 1997-1998
5 Copyright (C) Jeremy Allison 2009
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.
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.
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/>.
21 #include "includes.h"
22 #include "system/shmem.h"
23 #include "wbc_async.h"
24 #include "torture/proto.h"
25 #include "libcli/security/security.h"
26 #include "tldap.h"
27 #include "tldap_util.h"
28 #include "../librpc/gen_ndr/svcctl.h"
29 #include "memcache.h"
30 #include "nsswitch/winbind_client.h"
31 #include "dbwrap.h"
32 #include "talloc_dict.h"
33 #include "async_smb.h"
34 #include "libsmb/libsmb.h"
35 #include "libsmb/clirap.h"
36 #include "trans2.h"
37 #include "libsmb/nmblib.h"
38 #include "../lib/util/tevent_ntstatus.h"
39 #include "util_tdb.h"
40 #include "libsmb/read_smb.h"
42 extern char *optarg;
43 extern int optind;
45 fstring host, workgroup, share, password, username, myname;
46 static int max_protocol = PROTOCOL_NT1;
47 static const char *sockops="TCP_NODELAY";
48 static int nprocs=1;
49 static int port_to_use=0;
50 int torture_numops=100;
51 int torture_blocksize=1024*1024;
52 static int procnum; /* records process count number when forking */
53 static struct cli_state *current_cli;
54 static fstring randomfname;
55 static bool use_oplocks;
56 static bool use_level_II_oplocks;
57 static const char *client_txt = "client_oplocks.txt";
58 static bool use_kerberos;
59 static fstring multishare_conn_fname;
60 static bool use_multishare_conn = False;
61 static bool do_encrypt;
62 static const char *local_path = NULL;
63 static int signing_state = Undefined;
64 char *test_filename;
66 bool torture_showall = False;
68 static double create_procs(bool (*fn)(int), bool *result);
71 /* return a pointer to a anonymous shared memory segment of size "size"
72 which will persist across fork() but will disappear when all processes
73 exit
75 The memory is not zeroed
77 This function uses system5 shared memory. It takes advantage of a property
78 that the memory is not destroyed if it is attached when the id is removed
80 void *shm_setup(int size)
82 int shmid;
83 void *ret;
85 #ifdef __QNXNTO__
86 shmid = shm_open("private", O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
87 if (shmid == -1) {
88 printf("can't get shared memory\n");
89 exit(1);
91 shm_unlink("private");
92 if (ftruncate(shmid, size) == -1) {
93 printf("can't set shared memory size\n");
94 exit(1);
96 ret = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, shmid, 0);
97 if (ret == MAP_FAILED) {
98 printf("can't map shared memory\n");
99 exit(1);
101 #else
102 shmid = shmget(IPC_PRIVATE, size, S_IRUSR | S_IWUSR);
103 if (shmid == -1) {
104 printf("can't get shared memory\n");
105 exit(1);
107 ret = (void *)shmat(shmid, 0, 0);
108 if (!ret || ret == (void *)-1) {
109 printf("can't attach to shared memory\n");
110 return NULL;
112 /* the following releases the ipc, but note that this process
113 and all its children will still have access to the memory, its
114 just that the shmid is no longer valid for other shm calls. This
115 means we don't leave behind lots of shm segments after we exit
117 See Stevens "advanced programming in unix env" for details
119 shmctl(shmid, IPC_RMID, 0);
120 #endif
122 return ret;
125 /********************************************************************
126 Ensure a connection is encrypted.
127 ********************************************************************/
129 static bool force_cli_encryption(struct cli_state *c,
130 const char *sharename)
132 uint16 major, minor;
133 uint32 caplow, caphigh;
134 NTSTATUS status;
136 if (!SERVER_HAS_UNIX_CIFS(c)) {
137 d_printf("Encryption required and "
138 "server that doesn't support "
139 "UNIX extensions - failing connect\n");
140 return false;
143 status = cli_unix_extensions_version(c, &major, &minor, &caplow,
144 &caphigh);
145 if (!NT_STATUS_IS_OK(status)) {
146 d_printf("Encryption required and "
147 "can't get UNIX CIFS extensions "
148 "version from server: %s\n", nt_errstr(status));
149 return false;
152 if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
153 d_printf("Encryption required and "
154 "share %s doesn't support "
155 "encryption.\n", sharename);
156 return false;
159 if (c->use_kerberos) {
160 status = cli_gss_smb_encryption_start(c);
161 } else {
162 status = cli_raw_ntlm_smb_encryption_start(c,
163 username,
164 password,
165 workgroup);
168 if (!NT_STATUS_IS_OK(status)) {
169 d_printf("Encryption required and "
170 "setup failed with error %s.\n",
171 nt_errstr(status));
172 return false;
175 return true;
179 static struct cli_state *open_nbt_connection(void)
181 struct cli_state *c;
182 NTSTATUS status;
184 status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
185 signing_state, &c);
186 if (!NT_STATUS_IS_OK(status)) {
187 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
188 return NULL;
191 c->use_kerberos = use_kerberos;
193 c->timeout = 120000; /* set a really long timeout (2 minutes) */
194 if (use_oplocks) c->use_oplocks = True;
195 if (use_level_II_oplocks) c->use_level_II_oplocks = True;
197 return c;
200 /****************************************************************************
201 Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
202 ****************************************************************************/
204 static bool cli_bad_session_request(int fd,
205 struct nmb_name *calling, struct nmb_name *called)
207 TALLOC_CTX *frame;
208 uint8_t len_buf[4];
209 struct iovec iov[3];
210 ssize_t len;
211 uint8_t *inbuf;
212 int err;
213 bool ret = false;
214 uint8_t message_type;
215 uint8_t error;
217 frame = talloc_stackframe();
219 iov[0].iov_base = len_buf;
220 iov[0].iov_len = sizeof(len_buf);
222 /* put in the destination name */
224 iov[1].iov_base = name_mangle(talloc_tos(), called->name,
225 called->name_type);
226 if (iov[1].iov_base == NULL) {
227 goto fail;
229 iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
230 talloc_get_size(iov[1].iov_base));
232 /* and my name */
234 iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
235 calling->name_type);
236 if (iov[2].iov_base == NULL) {
237 goto fail;
239 iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
240 talloc_get_size(iov[2].iov_base));
242 /* Deliberately corrupt the name len (first byte) */
243 *((uint8_t *)iov[2].iov_base) = 100;
245 /* send a session request (RFC 1002) */
246 /* setup the packet length
247 * Remove four bytes from the length count, since the length
248 * field in the NBT Session Service header counts the number
249 * of bytes which follow. The cli_send_smb() function knows
250 * about this and accounts for those four bytes.
251 * CRH.
254 _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
255 SCVAL(len_buf,0,0x81);
257 len = write_data_iov(fd, iov, 3);
258 if (len == -1) {
259 goto fail;
261 len = read_smb(fd, talloc_tos(), &inbuf, &err);
262 if (len == -1) {
263 errno = err;
264 goto fail;
267 message_type = CVAL(inbuf, 0);
268 if (message_type != 0x83) {
269 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
270 message_type);
271 goto fail;
274 if (smb_len(inbuf) != 1) {
275 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
276 (int)smb_len(inbuf));
277 goto fail;
280 error = CVAL(inbuf, 4);
281 if (error != 0x82) {
282 d_fprintf(stderr, "Expected error 0x82, got %d\n",
283 (int)error);
284 goto fail;
287 ret = true;
288 fail:
289 TALLOC_FREE(frame);
290 return ret;
293 /* Insert a NULL at the first separator of the given path and return a pointer
294 * to the remainder of the string.
296 static char *
297 terminate_path_at_separator(char * path)
299 char * p;
301 if (!path) {
302 return NULL;
305 if ((p = strchr_m(path, '/'))) {
306 *p = '\0';
307 return p + 1;
310 if ((p = strchr_m(path, '\\'))) {
311 *p = '\0';
312 return p + 1;
315 /* No separator. */
316 return NULL;
320 parse a //server/share type UNC name
322 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
323 char **hostname, char **sharename)
325 char *p;
327 *hostname = *sharename = NULL;
329 if (strncmp(unc_name, "\\\\", 2) &&
330 strncmp(unc_name, "//", 2)) {
331 return False;
334 *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
335 p = terminate_path_at_separator(*hostname);
337 if (p && *p) {
338 *sharename = talloc_strdup(mem_ctx, p);
339 terminate_path_at_separator(*sharename);
342 if (*hostname && *sharename) {
343 return True;
346 TALLOC_FREE(*hostname);
347 TALLOC_FREE(*sharename);
348 return False;
351 static bool torture_open_connection_share(struct cli_state **c,
352 const char *hostname,
353 const char *sharename)
355 int flags = 0;
356 NTSTATUS status;
358 if (use_kerberos)
359 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
360 if (use_oplocks)
361 flags |= CLI_FULL_CONNECTION_OPLOCKS;
362 if (use_level_II_oplocks)
363 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
365 status = cli_full_connection(c, myname,
366 hostname, NULL, port_to_use,
367 sharename, "?????",
368 username, workgroup,
369 password, flags, signing_state);
370 if (!NT_STATUS_IS_OK(status)) {
371 printf("failed to open share connection: //%s/%s port:%d - %s\n",
372 hostname, sharename, port_to_use, nt_errstr(status));
373 return False;
376 (*c)->timeout = 120000; /* set a really long timeout (2 minutes) */
378 if (do_encrypt) {
379 return force_cli_encryption(*c,
380 sharename);
382 return True;
385 bool torture_open_connection(struct cli_state **c, int conn_index)
387 char **unc_list = NULL;
388 int num_unc_names = 0;
389 bool result;
391 if (use_multishare_conn==True) {
392 char *h, *s;
393 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
394 if (!unc_list || num_unc_names <= 0) {
395 printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
396 exit(1);
399 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
400 NULL, &h, &s)) {
401 printf("Failed to parse UNC name %s\n",
402 unc_list[conn_index % num_unc_names]);
403 TALLOC_FREE(unc_list);
404 exit(1);
407 result = torture_open_connection_share(c, h, s);
409 /* h, s were copied earlier */
410 TALLOC_FREE(unc_list);
411 return result;
414 return torture_open_connection_share(c, host, share);
417 bool torture_init_connection(struct cli_state **pcli)
419 struct cli_state *cli;
421 cli = open_nbt_connection();
422 if (cli == NULL) {
423 return false;
426 *pcli = cli;
427 return true;
430 bool torture_cli_session_setup2(struct cli_state *cli, uint16 *new_vuid)
432 uint16 old_vuid = cli->vuid;
433 fstring old_user_name;
434 size_t passlen = strlen(password);
435 NTSTATUS status;
436 bool ret;
438 fstrcpy(old_user_name, cli->user_name);
439 cli->vuid = 0;
440 ret = NT_STATUS_IS_OK(cli_session_setup(cli, username,
441 password, passlen,
442 password, passlen,
443 workgroup));
444 *new_vuid = cli->vuid;
445 cli->vuid = old_vuid;
446 status = cli_set_username(cli, old_user_name);
447 if (!NT_STATUS_IS_OK(status)) {
448 return false;
450 return ret;
454 bool torture_close_connection(struct cli_state *c)
456 bool ret = True;
457 NTSTATUS status;
459 status = cli_tdis(c);
460 if (!NT_STATUS_IS_OK(status)) {
461 printf("tdis failed (%s)\n", nt_errstr(status));
462 ret = False;
465 cli_shutdown(c);
467 return ret;
471 /* check if the server produced the expected dos or nt error code */
472 static bool check_both_error(int line, NTSTATUS status,
473 uint8 eclass, uint32 ecode, NTSTATUS nterr)
475 if (NT_STATUS_IS_DOS(status)) {
476 uint8 cclass;
477 uint32 num;
479 /* Check DOS error */
480 cclass = NT_STATUS_DOS_CLASS(status);
481 num = NT_STATUS_DOS_CODE(status);
483 if (eclass != cclass || ecode != num) {
484 printf("unexpected error code class=%d code=%d\n",
485 (int)cclass, (int)num);
486 printf(" expected %d/%d %s (line=%d)\n",
487 (int)eclass, (int)ecode, nt_errstr(nterr), line);
488 return false;
490 } else {
491 /* Check NT error */
492 if (!NT_STATUS_EQUAL(nterr, status)) {
493 printf("unexpected error code %s\n",
494 nt_errstr(status));
495 printf(" expected %s (line=%d)\n",
496 nt_errstr(nterr), line);
497 return false;
501 return true;
505 /* check if the server produced the expected error code */
506 static bool check_error(int line, struct cli_state *c,
507 uint8 eclass, uint32 ecode, NTSTATUS nterr)
509 if (cli_is_dos_error(c)) {
510 uint8 cclass;
511 uint32 num;
513 /* Check DOS error */
515 cli_dos_error(c, &cclass, &num);
517 if (eclass != cclass || ecode != num) {
518 printf("unexpected error code class=%d code=%d\n",
519 (int)cclass, (int)num);
520 printf(" expected %d/%d %s (line=%d)\n",
521 (int)eclass, (int)ecode, nt_errstr(nterr), line);
522 return False;
525 } else {
526 NTSTATUS status;
528 /* Check NT error */
530 status = cli_nt_error(c);
532 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
533 printf("unexpected error code %s\n", nt_errstr(status));
534 printf(" expected %s (line=%d)\n", nt_errstr(nterr), line);
535 return False;
539 return True;
543 static bool wait_lock(struct cli_state *c, int fnum, uint32 offset, uint32 len)
545 NTSTATUS status;
547 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
549 while (!NT_STATUS_IS_OK(status)) {
550 if (!check_both_error(__LINE__, status, ERRDOS,
551 ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
552 return false;
555 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
558 return true;
562 static bool rw_torture(struct cli_state *c)
564 const char *lockfname = "\\torture.lck";
565 fstring fname;
566 uint16_t fnum;
567 uint16_t fnum2;
568 pid_t pid2, pid = getpid();
569 int i, j;
570 char buf[1024];
571 bool correct = True;
572 NTSTATUS status;
574 memset(buf, '\0', sizeof(buf));
576 status = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
577 DENY_NONE, &fnum2);
578 if (!NT_STATUS_IS_OK(status)) {
579 status = cli_open(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
581 if (!NT_STATUS_IS_OK(status)) {
582 printf("open of %s failed (%s)\n",
583 lockfname, nt_errstr(status));
584 return False;
587 for (i=0;i<torture_numops;i++) {
588 unsigned n = (unsigned)sys_random()%10;
590 if (i % 10 == 0) {
591 printf("%d\r", i); fflush(stdout);
593 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
595 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
596 return False;
599 status = cli_open(c, fname, O_RDWR | O_CREAT | O_TRUNC,
600 DENY_ALL, &fnum);
601 if (!NT_STATUS_IS_OK(status)) {
602 printf("open failed (%s)\n", nt_errstr(status));
603 correct = False;
604 break;
607 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
608 sizeof(pid), NULL);
609 if (!NT_STATUS_IS_OK(status)) {
610 printf("write failed (%s)\n", nt_errstr(status));
611 correct = False;
614 for (j=0;j<50;j++) {
615 status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
616 sizeof(pid)+(j*sizeof(buf)),
617 sizeof(buf), NULL);
618 if (!NT_STATUS_IS_OK(status)) {
619 printf("write failed (%s)\n",
620 nt_errstr(status));
621 correct = False;
625 pid2 = 0;
627 if (cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid)) != sizeof(pid)) {
628 printf("read failed (%s)\n", cli_errstr(c));
629 correct = False;
632 if (pid2 != pid) {
633 printf("data corruption!\n");
634 correct = False;
637 status = cli_close(c, fnum);
638 if (!NT_STATUS_IS_OK(status)) {
639 printf("close failed (%s)\n", nt_errstr(status));
640 correct = False;
643 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
644 if (!NT_STATUS_IS_OK(status)) {
645 printf("unlink failed (%s)\n", nt_errstr(status));
646 correct = False;
649 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
650 if (!NT_STATUS_IS_OK(status)) {
651 printf("unlock failed (%s)\n", nt_errstr(status));
652 correct = False;
656 cli_close(c, fnum2);
657 cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
659 printf("%d\n", i);
661 return correct;
664 static bool run_torture(int dummy)
666 struct cli_state *cli;
667 bool ret;
669 cli = current_cli;
671 cli_sockopt(cli, sockops);
673 ret = rw_torture(cli);
675 if (!torture_close_connection(cli)) {
676 ret = False;
679 return ret;
682 static bool rw_torture3(struct cli_state *c, char *lockfname)
684 uint16_t fnum = (uint16_t)-1;
685 unsigned int i = 0;
686 char buf[131072];
687 char buf_rd[131072];
688 unsigned count;
689 unsigned countprev = 0;
690 ssize_t sent = 0;
691 bool correct = True;
692 NTSTATUS status = NT_STATUS_OK;
694 srandom(1);
695 for (i = 0; i < sizeof(buf); i += sizeof(uint32))
697 SIVAL(buf, i, sys_random());
700 if (procnum == 0)
702 status = cli_unlink(
703 c, lockfname,
704 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
705 if (!NT_STATUS_IS_OK(status)) {
706 printf("unlink failed (%s) (normal, this file should "
707 "not exist)\n", nt_errstr(status));
710 status = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
711 DENY_NONE, &fnum);
712 if (!NT_STATUS_IS_OK(status)) {
713 printf("first open read/write of %s failed (%s)\n",
714 lockfname, nt_errstr(status));
715 return False;
718 else
720 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
722 status = cli_open(c, lockfname, O_RDONLY,
723 DENY_NONE, &fnum);
724 if (!NT_STATUS_IS_OK(status)) {
725 break;
727 smb_msleep(10);
729 if (!NT_STATUS_IS_OK(status)) {
730 printf("second open read-only of %s failed (%s)\n",
731 lockfname, nt_errstr(status));
732 return False;
736 i = 0;
737 for (count = 0; count < sizeof(buf); count += sent)
739 if (count >= countprev) {
740 printf("%d %8d\r", i, count);
741 fflush(stdout);
742 i++;
743 countprev += (sizeof(buf) / 20);
746 if (procnum == 0)
748 sent = ((unsigned)sys_random()%(20))+ 1;
749 if (sent > sizeof(buf) - count)
751 sent = sizeof(buf) - count;
754 status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
755 count, (size_t)sent, NULL);
756 if (!NT_STATUS_IS_OK(status)) {
757 printf("write failed (%s)\n",
758 nt_errstr(status));
759 correct = False;
762 else
764 sent = cli_read(c, fnum, buf_rd+count, count,
765 sizeof(buf)-count);
766 if (sent < 0)
768 printf("read failed offset:%d size:%ld (%s)\n",
769 count, (unsigned long)sizeof(buf)-count,
770 cli_errstr(c));
771 correct = False;
772 sent = 0;
774 if (sent > 0)
776 if (memcmp(buf_rd+count, buf+count, sent) != 0)
778 printf("read/write compare failed\n");
779 printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
780 correct = False;
781 break;
788 status = cli_close(c, fnum);
789 if (!NT_STATUS_IS_OK(status)) {
790 printf("close failed (%s)\n", nt_errstr(status));
791 correct = False;
794 return correct;
797 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
799 const char *lockfname = "\\torture2.lck";
800 uint16_t fnum1;
801 uint16_t fnum2;
802 int i;
803 char buf[131072];
804 char buf_rd[131072];
805 bool correct = True;
806 ssize_t bytes_read;
807 NTSTATUS status;
809 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
810 if (!NT_STATUS_IS_OK(status)) {
811 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
814 status = cli_open(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
815 DENY_NONE, &fnum1);
816 if (!NT_STATUS_IS_OK(status)) {
817 printf("first open read/write of %s failed (%s)\n",
818 lockfname, nt_errstr(status));
819 return False;
822 status = cli_open(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
823 if (!NT_STATUS_IS_OK(status)) {
824 printf("second open read-only of %s failed (%s)\n",
825 lockfname, nt_errstr(status));
826 cli_close(c1, fnum1);
827 return False;
830 for (i = 0; i < torture_numops; i++)
832 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
833 if (i % 10 == 0) {
834 printf("%d\r", i); fflush(stdout);
837 generate_random_buffer((unsigned char *)buf, buf_size);
839 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
840 buf_size, NULL);
841 if (!NT_STATUS_IS_OK(status)) {
842 printf("write failed (%s)\n", nt_errstr(status));
843 correct = False;
844 break;
847 if ((bytes_read = cli_read(c2, fnum2, buf_rd, 0, buf_size)) != buf_size) {
848 printf("read failed (%s)\n", cli_errstr(c2));
849 printf("read %d, expected %ld\n", (int)bytes_read,
850 (unsigned long)buf_size);
851 correct = False;
852 break;
855 if (memcmp(buf_rd, buf, buf_size) != 0)
857 printf("read/write compare failed\n");
858 correct = False;
859 break;
863 status = cli_close(c2, fnum2);
864 if (!NT_STATUS_IS_OK(status)) {
865 printf("close failed (%s)\n", nt_errstr(status));
866 correct = False;
869 status = cli_close(c1, fnum1);
870 if (!NT_STATUS_IS_OK(status)) {
871 printf("close failed (%s)\n", nt_errstr(status));
872 correct = False;
875 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
876 if (!NT_STATUS_IS_OK(status)) {
877 printf("unlink failed (%s)\n", nt_errstr(status));
878 correct = False;
881 return correct;
884 static bool run_readwritetest(int dummy)
886 struct cli_state *cli1, *cli2;
887 bool test1, test2 = False;
889 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
890 return False;
892 cli_sockopt(cli1, sockops);
893 cli_sockopt(cli2, sockops);
895 printf("starting readwritetest\n");
897 test1 = rw_torture2(cli1, cli2);
898 printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
900 if (test1) {
901 test2 = rw_torture2(cli1, cli1);
902 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
905 if (!torture_close_connection(cli1)) {
906 test1 = False;
909 if (!torture_close_connection(cli2)) {
910 test2 = False;
913 return (test1 && test2);
916 static bool run_readwritemulti(int dummy)
918 struct cli_state *cli;
919 bool test;
921 cli = current_cli;
923 cli_sockopt(cli, sockops);
925 printf("run_readwritemulti: fname %s\n", randomfname);
926 test = rw_torture3(cli, randomfname);
928 if (!torture_close_connection(cli)) {
929 test = False;
932 return test;
935 static bool run_readwritelarge_internal(int max_xmit_k)
937 static struct cli_state *cli1;
938 uint16_t fnum1;
939 const char *lockfname = "\\large.dat";
940 SMB_OFF_T fsize;
941 char buf[126*1024];
942 bool correct = True;
943 NTSTATUS status;
945 if (!torture_open_connection(&cli1, 0)) {
946 return False;
948 cli_sockopt(cli1, sockops);
949 memset(buf,'\0',sizeof(buf));
951 cli1->max_xmit = max_xmit_k*1024;
953 if (signing_state == Required) {
954 /* Horrible cheat to force
955 multiple signed outstanding
956 packets against a Samba server.
958 cli1->is_samba = false;
961 printf("starting readwritelarge_internal\n");
963 cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
965 status = cli_open(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
966 DENY_NONE, &fnum1);
967 if (!NT_STATUS_IS_OK(status)) {
968 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
969 return False;
972 cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
974 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
975 NULL, NULL, NULL);
976 if (!NT_STATUS_IS_OK(status)) {
977 printf("qfileinfo failed (%s)\n", nt_errstr(status));
978 correct = False;
981 if (fsize == sizeof(buf))
982 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
983 (unsigned long)fsize);
984 else {
985 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
986 (unsigned long)fsize);
987 correct = False;
990 status = cli_close(cli1, fnum1);
991 if (!NT_STATUS_IS_OK(status)) {
992 printf("close failed (%s)\n", nt_errstr(status));
993 correct = False;
996 status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
997 if (!NT_STATUS_IS_OK(status)) {
998 printf("unlink failed (%s)\n", nt_errstr(status));
999 correct = False;
1002 status = cli_open(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1003 DENY_NONE, &fnum1);
1004 if (!NT_STATUS_IS_OK(status)) {
1005 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1006 return False;
1009 cli1->max_xmit = 4*1024;
1011 cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1013 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1014 NULL, NULL, NULL);
1015 if (!NT_STATUS_IS_OK(status)) {
1016 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1017 correct = False;
1020 if (fsize == sizeof(buf))
1021 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1022 (unsigned long)fsize);
1023 else {
1024 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1025 (unsigned long)fsize);
1026 correct = False;
1029 #if 0
1030 /* ToDo - set allocation. JRA */
1031 if(!cli_set_allocation_size(cli1, fnum1, 0)) {
1032 printf("set allocation size to zero failed (%s)\n", cli_errstr(&cli1));
1033 return False;
1035 if (!cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL, NULL,
1036 NULL, NULL)) {
1037 printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
1038 correct = False;
1040 if (fsize != 0)
1041 printf("readwritelarge test 3 (truncate test) succeeded (size = %x)\n", fsize);
1042 #endif
1044 status = cli_close(cli1, fnum1);
1045 if (!NT_STATUS_IS_OK(status)) {
1046 printf("close failed (%s)\n", nt_errstr(status));
1047 correct = False;
1050 if (!torture_close_connection(cli1)) {
1051 correct = False;
1053 return correct;
1056 static bool run_readwritelarge(int dummy)
1058 return run_readwritelarge_internal(128);
1061 static bool run_readwritelarge_signtest(int dummy)
1063 bool ret;
1064 signing_state = Required;
1065 ret = run_readwritelarge_internal(2);
1066 signing_state = Undefined;
1067 return ret;
1070 int line_count = 0;
1071 int nbio_id;
1073 #define ival(s) strtol(s, NULL, 0)
1075 /* run a test that simulates an approximate netbench client load */
1076 static bool run_netbench(int client)
1078 struct cli_state *cli;
1079 int i;
1080 char line[1024];
1081 char cname[20];
1082 FILE *f;
1083 const char *params[20];
1084 bool correct = True;
1086 cli = current_cli;
1088 nbio_id = client;
1090 cli_sockopt(cli, sockops);
1092 nb_setup(cli);
1094 slprintf(cname,sizeof(cname)-1, "client%d", client);
1096 f = fopen(client_txt, "r");
1098 if (!f) {
1099 perror(client_txt);
1100 return False;
1103 while (fgets(line, sizeof(line)-1, f)) {
1104 char *saveptr;
1105 line_count++;
1107 line[strlen(line)-1] = 0;
1109 /* printf("[%d] %s\n", line_count, line); */
1111 all_string_sub(line,"client1", cname, sizeof(line));
1113 /* parse the command parameters */
1114 params[0] = strtok_r(line, " ", &saveptr);
1115 i = 0;
1116 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1118 params[i] = "";
1120 if (i < 2) continue;
1122 if (!strncmp(params[0],"SMB", 3)) {
1123 printf("ERROR: You are using a dbench 1 load file\n");
1124 exit(1);
1127 if (!strcmp(params[0],"NTCreateX")) {
1128 nb_createx(params[1], ival(params[2]), ival(params[3]),
1129 ival(params[4]));
1130 } else if (!strcmp(params[0],"Close")) {
1131 nb_close(ival(params[1]));
1132 } else if (!strcmp(params[0],"Rename")) {
1133 nb_rename(params[1], params[2]);
1134 } else if (!strcmp(params[0],"Unlink")) {
1135 nb_unlink(params[1]);
1136 } else if (!strcmp(params[0],"Deltree")) {
1137 nb_deltree(params[1]);
1138 } else if (!strcmp(params[0],"Rmdir")) {
1139 nb_rmdir(params[1]);
1140 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1141 nb_qpathinfo(params[1]);
1142 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1143 nb_qfileinfo(ival(params[1]));
1144 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1145 nb_qfsinfo(ival(params[1]));
1146 } else if (!strcmp(params[0],"FIND_FIRST")) {
1147 nb_findfirst(params[1]);
1148 } else if (!strcmp(params[0],"WriteX")) {
1149 nb_writex(ival(params[1]),
1150 ival(params[2]), ival(params[3]), ival(params[4]));
1151 } else if (!strcmp(params[0],"ReadX")) {
1152 nb_readx(ival(params[1]),
1153 ival(params[2]), ival(params[3]), ival(params[4]));
1154 } else if (!strcmp(params[0],"Flush")) {
1155 nb_flush(ival(params[1]));
1156 } else {
1157 printf("Unknown operation %s\n", params[0]);
1158 exit(1);
1161 fclose(f);
1163 nb_cleanup();
1165 if (!torture_close_connection(cli)) {
1166 correct = False;
1169 return correct;
1173 /* run a test that simulates an approximate netbench client load */
1174 static bool run_nbench(int dummy)
1176 double t;
1177 bool correct = True;
1179 nbio_shmem(nprocs);
1181 nbio_id = -1;
1183 signal(SIGALRM, nb_alarm);
1184 alarm(1);
1185 t = create_procs(run_netbench, &correct);
1186 alarm(0);
1188 printf("\nThroughput %g MB/sec\n",
1189 1.0e-6 * nbio_total() / t);
1190 return correct;
1195 This test checks for two things:
1197 1) correct support for retaining locks over a close (ie. the server
1198 must not use posix semantics)
1199 2) support for lock timeouts
1201 static bool run_locktest1(int dummy)
1203 struct cli_state *cli1, *cli2;
1204 const char *fname = "\\lockt1.lck";
1205 uint16_t fnum1, fnum2, fnum3;
1206 time_t t1, t2;
1207 unsigned lock_timeout;
1208 NTSTATUS status;
1210 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1211 return False;
1213 cli_sockopt(cli1, sockops);
1214 cli_sockopt(cli2, sockops);
1216 printf("starting locktest1\n");
1218 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1220 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1221 &fnum1);
1222 if (!NT_STATUS_IS_OK(status)) {
1223 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1224 return False;
1227 status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1228 if (!NT_STATUS_IS_OK(status)) {
1229 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1230 return False;
1233 status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1234 if (!NT_STATUS_IS_OK(status)) {
1235 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1236 return False;
1239 if (!cli_lock(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) {
1240 printf("lock1 failed (%s)\n", cli_errstr(cli1));
1241 return False;
1245 if (cli_lock(cli2, fnum3, 0, 4, 0, WRITE_LOCK)) {
1246 printf("lock2 succeeded! This is a locking bug\n");
1247 return False;
1248 } else {
1249 if (!check_error(__LINE__, cli2, ERRDOS, ERRlock,
1250 NT_STATUS_LOCK_NOT_GRANTED)) return False;
1254 lock_timeout = (1 + (random() % 20));
1255 printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1256 t1 = time(NULL);
1257 if (cli_lock(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK)) {
1258 printf("lock3 succeeded! This is a locking bug\n");
1259 return False;
1260 } else {
1261 if (!check_error(__LINE__, cli2, ERRDOS, ERRlock,
1262 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
1264 t2 = time(NULL);
1266 if (ABS(t2 - t1) < lock_timeout-1) {
1267 printf("error: This server appears not to support timed lock requests\n");
1270 printf("server slept for %u seconds for a %u second timeout\n",
1271 (unsigned int)(t2-t1), lock_timeout);
1273 status = cli_close(cli1, fnum2);
1274 if (!NT_STATUS_IS_OK(status)) {
1275 printf("close1 failed (%s)\n", nt_errstr(status));
1276 return False;
1279 if (cli_lock(cli2, fnum3, 0, 4, 0, WRITE_LOCK)) {
1280 printf("lock4 succeeded! This is a locking bug\n");
1281 return False;
1282 } else {
1283 if (!check_error(__LINE__, cli2, ERRDOS, ERRlock,
1284 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
1287 status = cli_close(cli1, fnum1);
1288 if (!NT_STATUS_IS_OK(status)) {
1289 printf("close2 failed (%s)\n", nt_errstr(status));
1290 return False;
1293 status = cli_close(cli2, fnum3);
1294 if (!NT_STATUS_IS_OK(status)) {
1295 printf("close3 failed (%s)\n", nt_errstr(status));
1296 return False;
1299 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1300 if (!NT_STATUS_IS_OK(status)) {
1301 printf("unlink failed (%s)\n", nt_errstr(status));
1302 return False;
1306 if (!torture_close_connection(cli1)) {
1307 return False;
1310 if (!torture_close_connection(cli2)) {
1311 return False;
1314 printf("Passed locktest1\n");
1315 return True;
1319 this checks to see if a secondary tconx can use open files from an
1320 earlier tconx
1322 static bool run_tcon_test(int dummy)
1324 static struct cli_state *cli;
1325 const char *fname = "\\tcontest.tmp";
1326 uint16 fnum1;
1327 uint16 cnum1, cnum2, cnum3;
1328 uint16 vuid1, vuid2;
1329 char buf[4];
1330 bool ret = True;
1331 NTSTATUS status;
1333 memset(buf, '\0', sizeof(buf));
1335 if (!torture_open_connection(&cli, 0)) {
1336 return False;
1338 cli_sockopt(cli, sockops);
1340 printf("starting tcontest\n");
1342 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1344 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1345 if (!NT_STATUS_IS_OK(status)) {
1346 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1347 return False;
1350 cnum1 = cli->cnum;
1351 vuid1 = cli->vuid;
1353 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1354 if (!NT_STATUS_IS_OK(status)) {
1355 printf("initial write failed (%s)", nt_errstr(status));
1356 return False;
1359 status = cli_tcon_andx(cli, share, "?????",
1360 password, strlen(password)+1);
1361 if (!NT_STATUS_IS_OK(status)) {
1362 printf("%s refused 2nd tree connect (%s)\n", host,
1363 nt_errstr(status));
1364 cli_shutdown(cli);
1365 return False;
1368 cnum2 = cli->cnum;
1369 cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1370 vuid2 = cli->vuid + 1;
1372 /* try a write with the wrong tid */
1373 cli->cnum = cnum2;
1375 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1376 if (NT_STATUS_IS_OK(status)) {
1377 printf("* server allows write with wrong TID\n");
1378 ret = False;
1379 } else {
1380 printf("server fails write with wrong TID : %s\n",
1381 nt_errstr(status));
1385 /* try a write with an invalid tid */
1386 cli->cnum = cnum3;
1388 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1389 if (NT_STATUS_IS_OK(status)) {
1390 printf("* server allows write with invalid TID\n");
1391 ret = False;
1392 } else {
1393 printf("server fails write with invalid TID : %s\n",
1394 nt_errstr(status));
1397 /* try a write with an invalid vuid */
1398 cli->vuid = vuid2;
1399 cli->cnum = cnum1;
1401 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1402 if (NT_STATUS_IS_OK(status)) {
1403 printf("* server allows write with invalid VUID\n");
1404 ret = False;
1405 } else {
1406 printf("server fails write with invalid VUID : %s\n",
1407 nt_errstr(status));
1410 cli->cnum = cnum1;
1411 cli->vuid = vuid1;
1413 status = cli_close(cli, fnum1);
1414 if (!NT_STATUS_IS_OK(status)) {
1415 printf("close failed (%s)\n", nt_errstr(status));
1416 return False;
1419 cli->cnum = cnum2;
1421 status = cli_tdis(cli);
1422 if (!NT_STATUS_IS_OK(status)) {
1423 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1424 return False;
1427 cli->cnum = cnum1;
1429 if (!torture_close_connection(cli)) {
1430 return False;
1433 return ret;
1438 checks for old style tcon support
1440 static bool run_tcon2_test(int dummy)
1442 static struct cli_state *cli;
1443 uint16 cnum, max_xmit;
1444 char *service;
1445 NTSTATUS status;
1447 if (!torture_open_connection(&cli, 0)) {
1448 return False;
1450 cli_sockopt(cli, sockops);
1452 printf("starting tcon2 test\n");
1454 if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1455 return false;
1458 status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1460 SAFE_FREE(service);
1462 if (!NT_STATUS_IS_OK(status)) {
1463 printf("tcon2 failed : %s\n", nt_errstr(status));
1464 } else {
1465 printf("tcon OK : max_xmit=%d cnum=%d\n",
1466 (int)max_xmit, (int)cnum);
1469 if (!torture_close_connection(cli)) {
1470 return False;
1473 printf("Passed tcon2 test\n");
1474 return True;
1477 static bool tcon_devtest(struct cli_state *cli,
1478 const char *myshare, const char *devtype,
1479 const char *return_devtype,
1480 NTSTATUS expected_error)
1482 NTSTATUS status;
1483 bool ret;
1485 status = cli_tcon_andx(cli, myshare, devtype,
1486 password, strlen(password)+1);
1488 if (NT_STATUS_IS_OK(expected_error)) {
1489 if (NT_STATUS_IS_OK(status)) {
1490 if (strcmp(cli->dev, return_devtype) == 0) {
1491 ret = True;
1492 } else {
1493 printf("tconX to share %s with type %s "
1494 "succeeded but returned the wrong "
1495 "device type (got [%s] but should have got [%s])\n",
1496 myshare, devtype, cli->dev, return_devtype);
1497 ret = False;
1499 } else {
1500 printf("tconX to share %s with type %s "
1501 "should have succeeded but failed\n",
1502 myshare, devtype);
1503 ret = False;
1505 cli_tdis(cli);
1506 } else {
1507 if (NT_STATUS_IS_OK(status)) {
1508 printf("tconx to share %s with type %s "
1509 "should have failed but succeeded\n",
1510 myshare, devtype);
1511 ret = False;
1512 } else {
1513 if (NT_STATUS_EQUAL(cli_nt_error(cli),
1514 expected_error)) {
1515 ret = True;
1516 } else {
1517 printf("Returned unexpected error\n");
1518 ret = False;
1522 return ret;
1526 checks for correct tconX support
1528 static bool run_tcon_devtype_test(int dummy)
1530 static struct cli_state *cli1 = NULL;
1531 int flags = 0;
1532 NTSTATUS status;
1533 bool ret = True;
1535 status = cli_full_connection(&cli1, myname,
1536 host, NULL, port_to_use,
1537 NULL, NULL,
1538 username, workgroup,
1539 password, flags, signing_state);
1541 if (!NT_STATUS_IS_OK(status)) {
1542 printf("could not open connection\n");
1543 return False;
1546 if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1547 ret = False;
1549 if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1550 ret = False;
1552 if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1553 ret = False;
1555 if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1556 ret = False;
1558 if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1559 ret = False;
1561 if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1562 ret = False;
1564 if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1565 ret = False;
1567 if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1568 ret = False;
1570 if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1571 ret = False;
1573 if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1574 ret = False;
1576 cli_shutdown(cli1);
1578 if (ret)
1579 printf("Passed tcondevtest\n");
1581 return ret;
1586 This test checks that
1588 1) the server supports multiple locking contexts on the one SMB
1589 connection, distinguished by PID.
1591 2) the server correctly fails overlapping locks made by the same PID (this
1592 goes against POSIX behaviour, which is why it is tricky to implement)
1594 3) the server denies unlock requests by an incorrect client PID
1596 static bool run_locktest2(int dummy)
1598 static struct cli_state *cli;
1599 const char *fname = "\\lockt2.lck";
1600 uint16_t fnum1, fnum2, fnum3;
1601 bool correct = True;
1602 NTSTATUS status;
1604 if (!torture_open_connection(&cli, 0)) {
1605 return False;
1608 cli_sockopt(cli, sockops);
1610 printf("starting locktest2\n");
1612 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1614 cli_setpid(cli, 1);
1616 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1617 if (!NT_STATUS_IS_OK(status)) {
1618 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1619 return False;
1622 status = cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1623 if (!NT_STATUS_IS_OK(status)) {
1624 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1625 return False;
1628 cli_setpid(cli, 2);
1630 status = cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1631 if (!NT_STATUS_IS_OK(status)) {
1632 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1633 return False;
1636 cli_setpid(cli, 1);
1638 if (!cli_lock(cli, fnum1, 0, 4, 0, WRITE_LOCK)) {
1639 printf("lock1 failed (%s)\n", cli_errstr(cli));
1640 return False;
1643 if (cli_lock(cli, fnum1, 0, 4, 0, WRITE_LOCK)) {
1644 printf("WRITE lock1 succeeded! This is a locking bug\n");
1645 correct = False;
1646 } else {
1647 if (!check_error(__LINE__, cli, ERRDOS, ERRlock,
1648 NT_STATUS_LOCK_NOT_GRANTED)) return False;
1651 if (cli_lock(cli, fnum2, 0, 4, 0, WRITE_LOCK)) {
1652 printf("WRITE lock2 succeeded! This is a locking bug\n");
1653 correct = False;
1654 } else {
1655 if (!check_error(__LINE__, cli, ERRDOS, ERRlock,
1656 NT_STATUS_LOCK_NOT_GRANTED)) return False;
1659 if (cli_lock(cli, fnum2, 0, 4, 0, READ_LOCK)) {
1660 printf("READ lock2 succeeded! This is a locking bug\n");
1661 correct = False;
1662 } else {
1663 if (!check_error(__LINE__, cli, ERRDOS, ERRlock,
1664 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
1667 if (!cli_lock(cli, fnum1, 100, 4, 0, WRITE_LOCK)) {
1668 printf("lock at 100 failed (%s)\n", cli_errstr(cli));
1670 cli_setpid(cli, 2);
1671 if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1672 printf("unlock at 100 succeeded! This is a locking bug\n");
1673 correct = False;
1676 if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 0, 4))) {
1677 printf("unlock1 succeeded! This is a locking bug\n");
1678 correct = False;
1679 } else {
1680 if (!check_error(__LINE__, cli,
1681 ERRDOS, ERRlock,
1682 NT_STATUS_RANGE_NOT_LOCKED)) return False;
1685 if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 0, 8))) {
1686 printf("unlock2 succeeded! This is a locking bug\n");
1687 correct = False;
1688 } else {
1689 if (!check_error(__LINE__, cli,
1690 ERRDOS, ERRlock,
1691 NT_STATUS_RANGE_NOT_LOCKED)) return False;
1694 if (cli_lock(cli, fnum3, 0, 4, 0, WRITE_LOCK)) {
1695 printf("lock3 succeeded! This is a locking bug\n");
1696 correct = False;
1697 } else {
1698 if (!check_error(__LINE__, cli, ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) return False;
1701 cli_setpid(cli, 1);
1703 status = cli_close(cli, fnum1);
1704 if (!NT_STATUS_IS_OK(status)) {
1705 printf("close1 failed (%s)\n", nt_errstr(status));
1706 return False;
1709 status = cli_close(cli, fnum2);
1710 if (!NT_STATUS_IS_OK(status)) {
1711 printf("close2 failed (%s)\n", nt_errstr(status));
1712 return False;
1715 status = cli_close(cli, fnum3);
1716 if (!NT_STATUS_IS_OK(status)) {
1717 printf("close3 failed (%s)\n", nt_errstr(status));
1718 return False;
1721 if (!torture_close_connection(cli)) {
1722 correct = False;
1725 printf("locktest2 finished\n");
1727 return correct;
1732 This test checks that
1734 1) the server supports the full offset range in lock requests
1736 static bool run_locktest3(int dummy)
1738 static struct cli_state *cli1, *cli2;
1739 const char *fname = "\\lockt3.lck";
1740 uint16_t fnum1, fnum2;
1741 int i;
1742 uint32 offset;
1743 bool correct = True;
1744 NTSTATUS status;
1746 #define NEXT_OFFSET offset += (~(uint32)0) / torture_numops
1748 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1749 return False;
1751 cli_sockopt(cli1, sockops);
1752 cli_sockopt(cli2, sockops);
1754 printf("starting locktest3\n");
1756 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1758 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1759 &fnum1);
1760 if (!NT_STATUS_IS_OK(status)) {
1761 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1762 return False;
1765 status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1766 if (!NT_STATUS_IS_OK(status)) {
1767 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1768 return False;
1771 for (offset=i=0;i<torture_numops;i++) {
1772 NEXT_OFFSET;
1773 if (!cli_lock(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
1774 printf("lock1 %d failed (%s)\n",
1776 cli_errstr(cli1));
1777 return False;
1780 if (!cli_lock(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK)) {
1781 printf("lock2 %d failed (%s)\n",
1783 cli_errstr(cli1));
1784 return False;
1788 for (offset=i=0;i<torture_numops;i++) {
1789 NEXT_OFFSET;
1791 if (cli_lock(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK)) {
1792 printf("error: lock1 %d succeeded!\n", i);
1793 return False;
1796 if (cli_lock(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK)) {
1797 printf("error: lock2 %d succeeded!\n", i);
1798 return False;
1801 if (cli_lock(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
1802 printf("error: lock3 %d succeeded!\n", i);
1803 return False;
1806 if (cli_lock(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK)) {
1807 printf("error: lock4 %d succeeded!\n", i);
1808 return False;
1812 for (offset=i=0;i<torture_numops;i++) {
1813 NEXT_OFFSET;
1815 status = cli_unlock(cli1, fnum1, offset-1, 1);
1816 if (!NT_STATUS_IS_OK(status)) {
1817 printf("unlock1 %d failed (%s)\n",
1819 nt_errstr(status));
1820 return False;
1823 status = cli_unlock(cli2, fnum2, offset-2, 1);
1824 if (!NT_STATUS_IS_OK(status)) {
1825 printf("unlock2 %d failed (%s)\n",
1827 nt_errstr(status));
1828 return False;
1832 status = cli_close(cli1, fnum1);
1833 if (!NT_STATUS_IS_OK(status)) {
1834 printf("close1 failed (%s)\n", nt_errstr(status));
1835 return False;
1838 status = cli_close(cli2, fnum2);
1839 if (!NT_STATUS_IS_OK(status)) {
1840 printf("close2 failed (%s)\n", nt_errstr(status));
1841 return False;
1844 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1845 if (!NT_STATUS_IS_OK(status)) {
1846 printf("unlink failed (%s)\n", nt_errstr(status));
1847 return False;
1850 if (!torture_close_connection(cli1)) {
1851 correct = False;
1854 if (!torture_close_connection(cli2)) {
1855 correct = False;
1858 printf("finished locktest3\n");
1860 return correct;
1863 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1864 printf("** "); correct = False; \
1868 looks at overlapping locks
1870 static bool run_locktest4(int dummy)
1872 static struct cli_state *cli1, *cli2;
1873 const char *fname = "\\lockt4.lck";
1874 uint16_t fnum1, fnum2, f;
1875 bool ret;
1876 char buf[1000];
1877 bool correct = True;
1878 NTSTATUS status;
1880 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1881 return False;
1884 cli_sockopt(cli1, sockops);
1885 cli_sockopt(cli2, sockops);
1887 printf("starting locktest4\n");
1889 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1891 cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1892 cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1894 memset(buf, 0, sizeof(buf));
1896 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
1897 NULL);
1898 if (!NT_STATUS_IS_OK(status)) {
1899 printf("Failed to create file: %s\n", nt_errstr(status));
1900 correct = False;
1901 goto fail;
1904 ret = cli_lock(cli1, fnum1, 0, 4, 0, WRITE_LOCK) &&
1905 cli_lock(cli1, fnum1, 2, 4, 0, WRITE_LOCK);
1906 EXPECTED(ret, False);
1907 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1909 ret = cli_lock(cli1, fnum1, 10, 4, 0, READ_LOCK) &&
1910 cli_lock(cli1, fnum1, 12, 4, 0, READ_LOCK);
1911 EXPECTED(ret, True);
1912 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1914 ret = cli_lock(cli1, fnum1, 20, 4, 0, WRITE_LOCK) &&
1915 cli_lock(cli2, fnum2, 22, 4, 0, WRITE_LOCK);
1916 EXPECTED(ret, False);
1917 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1919 ret = cli_lock(cli1, fnum1, 30, 4, 0, READ_LOCK) &&
1920 cli_lock(cli2, fnum2, 32, 4, 0, READ_LOCK);
1921 EXPECTED(ret, True);
1922 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1924 ret = (cli_setpid(cli1, 1), cli_lock(cli1, fnum1, 40, 4, 0, WRITE_LOCK)) &&
1925 (cli_setpid(cli1, 2), cli_lock(cli1, fnum1, 42, 4, 0, WRITE_LOCK));
1926 EXPECTED(ret, False);
1927 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1929 ret = (cli_setpid(cli1, 1), cli_lock(cli1, fnum1, 50, 4, 0, READ_LOCK)) &&
1930 (cli_setpid(cli1, 2), cli_lock(cli1, fnum1, 52, 4, 0, READ_LOCK));
1931 EXPECTED(ret, True);
1932 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1934 ret = cli_lock(cli1, fnum1, 60, 4, 0, READ_LOCK) &&
1935 cli_lock(cli1, fnum1, 60, 4, 0, READ_LOCK);
1936 EXPECTED(ret, True);
1937 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1939 ret = cli_lock(cli1, fnum1, 70, 4, 0, WRITE_LOCK) &&
1940 cli_lock(cli1, fnum1, 70, 4, 0, WRITE_LOCK);
1941 EXPECTED(ret, False);
1942 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1944 ret = cli_lock(cli1, fnum1, 80, 4, 0, READ_LOCK) &&
1945 cli_lock(cli1, fnum1, 80, 4, 0, WRITE_LOCK);
1946 EXPECTED(ret, False);
1947 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
1949 ret = cli_lock(cli1, fnum1, 90, 4, 0, WRITE_LOCK) &&
1950 cli_lock(cli1, fnum1, 90, 4, 0, READ_LOCK);
1951 EXPECTED(ret, True);
1952 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1954 ret = (cli_setpid(cli1, 1), cli_lock(cli1, fnum1, 100, 4, 0, WRITE_LOCK)) &&
1955 (cli_setpid(cli1, 2), cli_lock(cli1, fnum1, 100, 4, 0, READ_LOCK));
1956 EXPECTED(ret, False);
1957 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1959 ret = cli_lock(cli1, fnum1, 110, 4, 0, READ_LOCK) &&
1960 cli_lock(cli1, fnum1, 112, 4, 0, READ_LOCK) &&
1961 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
1962 EXPECTED(ret, False);
1963 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
1966 ret = cli_lock(cli1, fnum1, 120, 4, 0, WRITE_LOCK) &&
1967 (cli_read(cli2, fnum2, buf, 120, 4) == 4);
1968 EXPECTED(ret, False);
1969 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
1971 ret = cli_lock(cli1, fnum1, 130, 4, 0, READ_LOCK);
1972 if (ret) {
1973 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
1974 NULL);
1975 ret = NT_STATUS_IS_OK(status);
1977 EXPECTED(ret, False);
1978 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
1981 ret = cli_lock(cli1, fnum1, 140, 4, 0, READ_LOCK) &&
1982 cli_lock(cli1, fnum1, 140, 4, 0, READ_LOCK) &&
1983 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
1984 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
1985 EXPECTED(ret, True);
1986 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
1989 ret = cli_lock(cli1, fnum1, 150, 4, 0, WRITE_LOCK) &&
1990 cli_lock(cli1, fnum1, 150, 4, 0, READ_LOCK) &&
1991 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
1992 (cli_read(cli2, fnum2, buf, 150, 4) == 4) &&
1993 !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
1994 150, 4, NULL))) &&
1995 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
1996 EXPECTED(ret, True);
1997 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
1999 ret = cli_lock(cli1, fnum1, 160, 4, 0, READ_LOCK) &&
2000 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2001 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2002 160, 4, NULL)) &&
2003 (cli_read(cli2, fnum2, buf, 160, 4) == 4);
2004 EXPECTED(ret, True);
2005 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2007 ret = cli_lock(cli1, fnum1, 170, 4, 0, WRITE_LOCK) &&
2008 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2009 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2010 170, 4, NULL)) &&
2011 (cli_read(cli2, fnum2, buf, 170, 4) == 4);
2012 EXPECTED(ret, True);
2013 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2015 ret = cli_lock(cli1, fnum1, 190, 4, 0, WRITE_LOCK) &&
2016 cli_lock(cli1, fnum1, 190, 4, 0, READ_LOCK) &&
2017 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2018 !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2019 190, 4, NULL)) &&
2020 (cli_read(cli2, fnum2, buf, 190, 4) == 4);
2021 EXPECTED(ret, True);
2022 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2024 cli_close(cli1, fnum1);
2025 cli_close(cli2, fnum2);
2026 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2027 cli_open(cli1, fname, O_RDWR, DENY_NONE, &f);
2028 ret = cli_lock(cli1, fnum1, 0, 8, 0, READ_LOCK) &&
2029 cli_lock(cli1, f, 0, 1, 0, READ_LOCK) &&
2030 NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2031 NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2032 cli_lock(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2033 cli_close(cli1, f);
2034 cli_close(cli1, fnum1);
2035 EXPECTED(ret, True);
2036 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2038 fail:
2039 cli_close(cli1, fnum1);
2040 cli_close(cli2, fnum2);
2041 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2042 torture_close_connection(cli1);
2043 torture_close_connection(cli2);
2045 printf("finished locktest4\n");
2046 return correct;
2050 looks at lock upgrade/downgrade.
2052 static bool run_locktest5(int dummy)
2054 static struct cli_state *cli1, *cli2;
2055 const char *fname = "\\lockt5.lck";
2056 uint16_t fnum1, fnum2, fnum3;
2057 bool ret;
2058 char buf[1000];
2059 bool correct = True;
2060 NTSTATUS status;
2062 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2063 return False;
2066 cli_sockopt(cli1, sockops);
2067 cli_sockopt(cli2, sockops);
2069 printf("starting locktest5\n");
2071 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2073 cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2074 cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2075 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2077 memset(buf, 0, sizeof(buf));
2079 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2080 NULL);
2081 if (!NT_STATUS_IS_OK(status)) {
2082 printf("Failed to create file: %s\n", nt_errstr(status));
2083 correct = False;
2084 goto fail;
2087 /* Check for NT bug... */
2088 ret = cli_lock(cli1, fnum1, 0, 8, 0, READ_LOCK) &&
2089 cli_lock(cli1, fnum3, 0, 1, 0, READ_LOCK);
2090 cli_close(cli1, fnum1);
2091 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2092 ret = cli_lock(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2093 EXPECTED(ret, True);
2094 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2095 cli_close(cli1, fnum1);
2096 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2097 cli_unlock(cli1, fnum3, 0, 1);
2099 ret = cli_lock(cli1, fnum1, 0, 4, 0, WRITE_LOCK) &&
2100 cli_lock(cli1, fnum1, 1, 1, 0, READ_LOCK);
2101 EXPECTED(ret, True);
2102 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2104 ret = cli_lock(cli2, fnum2, 0, 4, 0, READ_LOCK);
2105 EXPECTED(ret, False);
2107 printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2109 /* Unlock the process 2 lock. */
2110 cli_unlock(cli2, fnum2, 0, 4);
2112 ret = cli_lock(cli1, fnum3, 0, 4, 0, READ_LOCK);
2113 EXPECTED(ret, False);
2115 printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
2117 /* Unlock the process 1 fnum3 lock. */
2118 cli_unlock(cli1, fnum3, 0, 4);
2120 /* Stack 2 more locks here. */
2121 ret = cli_lock(cli1, fnum1, 0, 4, 0, READ_LOCK) &&
2122 cli_lock(cli1, fnum1, 0, 4, 0, READ_LOCK);
2124 EXPECTED(ret, True);
2125 printf("the same process %s stack read locks\n", ret?"can":"cannot");
2127 /* Unlock the first process lock, then check this was the WRITE lock that was
2128 removed. */
2130 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2131 cli_lock(cli2, fnum2, 0, 4, 0, READ_LOCK);
2133 EXPECTED(ret, True);
2134 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2136 /* Unlock the process 2 lock. */
2137 cli_unlock(cli2, fnum2, 0, 4);
2139 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2141 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2142 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2143 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2145 EXPECTED(ret, True);
2146 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2148 /* Ensure the next unlock fails. */
2149 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2150 EXPECTED(ret, False);
2151 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2153 /* Ensure connection 2 can get a write lock. */
2154 ret = cli_lock(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2155 EXPECTED(ret, True);
2157 printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2160 fail:
2161 cli_close(cli1, fnum1);
2162 cli_close(cli2, fnum2);
2163 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2164 if (!torture_close_connection(cli1)) {
2165 correct = False;
2167 if (!torture_close_connection(cli2)) {
2168 correct = False;
2171 printf("finished locktest5\n");
2173 return correct;
2177 tries the unusual lockingX locktype bits
2179 static bool run_locktest6(int dummy)
2181 static struct cli_state *cli;
2182 const char *fname[1] = { "\\lock6.txt" };
2183 int i;
2184 uint16_t fnum;
2185 NTSTATUS status;
2187 if (!torture_open_connection(&cli, 0)) {
2188 return False;
2191 cli_sockopt(cli, sockops);
2193 printf("starting locktest6\n");
2195 for (i=0;i<1;i++) {
2196 printf("Testing %s\n", fname[i]);
2198 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2200 cli_open(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2201 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2202 cli_close(cli, fnum);
2203 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2205 cli_open(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2206 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2207 cli_close(cli, fnum);
2208 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2210 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2213 torture_close_connection(cli);
2215 printf("finished locktest6\n");
2216 return True;
2219 static bool run_locktest7(int dummy)
2221 struct cli_state *cli1;
2222 const char *fname = "\\lockt7.lck";
2223 uint16_t fnum1;
2224 char buf[200];
2225 bool correct = False;
2226 NTSTATUS status;
2228 if (!torture_open_connection(&cli1, 0)) {
2229 return False;
2232 cli_sockopt(cli1, sockops);
2234 printf("starting locktest7\n");
2236 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2238 cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2240 memset(buf, 0, sizeof(buf));
2242 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2243 NULL);
2244 if (!NT_STATUS_IS_OK(status)) {
2245 printf("Failed to create file: %s\n", nt_errstr(status));
2246 goto fail;
2249 cli_setpid(cli1, 1);
2251 if (!cli_lock(cli1, fnum1, 130, 4, 0, READ_LOCK)) {
2252 printf("Unable to apply read lock on range 130:4, error was %s\n", cli_errstr(cli1));
2253 goto fail;
2254 } else {
2255 printf("pid1 successfully locked range 130:4 for READ\n");
2258 if (cli_read(cli1, fnum1, buf, 130, 4) != 4) {
2259 printf("pid1 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2260 goto fail;
2261 } else {
2262 printf("pid1 successfully read the range 130:4\n");
2265 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2266 if (!NT_STATUS_IS_OK(status)) {
2267 printf("pid1 unable to write to the range 130:4, error was "
2268 "%s\n", nt_errstr(status));
2269 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2270 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2271 goto fail;
2273 } else {
2274 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2275 goto fail;
2278 cli_setpid(cli1, 2);
2280 if (cli_read(cli1, fnum1, buf, 130, 4) != 4) {
2281 printf("pid2 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2282 } else {
2283 printf("pid2 successfully read the range 130:4\n");
2286 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2287 if (!NT_STATUS_IS_OK(status)) {
2288 printf("pid2 unable to write to the range 130:4, error was "
2289 "%s\n", nt_errstr(status));
2290 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2291 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2292 goto fail;
2294 } else {
2295 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2296 goto fail;
2299 cli_setpid(cli1, 1);
2300 cli_unlock(cli1, fnum1, 130, 4);
2302 if (!cli_lock(cli1, fnum1, 130, 4, 0, WRITE_LOCK)) {
2303 printf("Unable to apply write lock on range 130:4, error was %s\n", cli_errstr(cli1));
2304 goto fail;
2305 } else {
2306 printf("pid1 successfully locked range 130:4 for WRITE\n");
2309 if (cli_read(cli1, fnum1, buf, 130, 4) != 4) {
2310 printf("pid1 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2311 goto fail;
2312 } else {
2313 printf("pid1 successfully read the range 130:4\n");
2316 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2317 if (!NT_STATUS_IS_OK(status)) {
2318 printf("pid1 unable to write to the range 130:4, error was "
2319 "%s\n", nt_errstr(status));
2320 goto fail;
2321 } else {
2322 printf("pid1 successfully wrote to the range 130:4\n");
2325 cli_setpid(cli1, 2);
2327 if (cli_read(cli1, fnum1, buf, 130, 4) != 4) {
2328 printf("pid2 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2329 if (NT_STATUS_V(cli_nt_error(cli1)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
2330 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2331 goto fail;
2333 } else {
2334 printf("pid2 successfully read the range 130:4 (should be denied)\n");
2335 goto fail;
2338 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2339 if (!NT_STATUS_IS_OK(status)) {
2340 printf("pid2 unable to write to the range 130:4, error was "
2341 "%s\n", nt_errstr(status));
2342 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2343 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2344 goto fail;
2346 } else {
2347 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2348 goto fail;
2351 cli_unlock(cli1, fnum1, 130, 0);
2352 correct = True;
2354 fail:
2355 cli_close(cli1, fnum1);
2356 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2357 torture_close_connection(cli1);
2359 printf("finished locktest7\n");
2360 return correct;
2364 * This demonstrates a problem with our use of GPFS share modes: A file
2365 * descriptor sitting in the pending close queue holding a GPFS share mode
2366 * blocks opening a file another time. Happens with Word 2007 temp files.
2367 * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2368 * open is denied with NT_STATUS_SHARING_VIOLATION.
2371 static bool run_locktest8(int dummy)
2373 struct cli_state *cli1;
2374 const char *fname = "\\lockt8.lck";
2375 uint16_t fnum1, fnum2;
2376 char buf[200];
2377 bool correct = False;
2378 NTSTATUS status;
2380 if (!torture_open_connection(&cli1, 0)) {
2381 return False;
2384 cli_sockopt(cli1, sockops);
2386 printf("starting locktest8\n");
2388 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2390 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2391 &fnum1);
2392 if (!NT_STATUS_IS_OK(status)) {
2393 d_fprintf(stderr, "cli_open returned %s\n", nt_errstr(status));
2394 return false;
2397 memset(buf, 0, sizeof(buf));
2399 status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2400 if (!NT_STATUS_IS_OK(status)) {
2401 d_fprintf(stderr, "cli_open second time returned %s\n",
2402 nt_errstr(status));
2403 goto fail;
2406 if (!cli_lock(cli1, fnum2, 1, 1, 0, READ_LOCK)) {
2407 printf("Unable to apply read lock on range 1:1, error was "
2408 "%s\n", cli_errstr(cli1));
2409 goto fail;
2412 status = cli_close(cli1, fnum1);
2413 if (!NT_STATUS_IS_OK(status)) {
2414 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2415 goto fail;
2418 status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2419 if (!NT_STATUS_IS_OK(status)) {
2420 d_fprintf(stderr, "cli_open third time returned %s\n",
2421 nt_errstr(status));
2422 goto fail;
2425 correct = true;
2427 fail:
2428 cli_close(cli1, fnum1);
2429 cli_close(cli1, fnum2);
2430 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2431 torture_close_connection(cli1);
2433 printf("finished locktest8\n");
2434 return correct;
2438 * This test is designed to be run in conjunction with
2439 * external NFS or POSIX locks taken in the filesystem.
2440 * It checks that the smbd server will block until the
2441 * lock is released and then acquire it. JRA.
2444 static bool got_alarm;
2445 static int alarm_fd;
2447 static void alarm_handler(int dummy)
2449 got_alarm = True;
2452 static void alarm_handler_parent(int dummy)
2454 close(alarm_fd);
2457 static void do_local_lock(int read_fd, int write_fd)
2459 int fd;
2460 char c = '\0';
2461 struct flock lock;
2462 const char *local_pathname = NULL;
2463 int ret;
2465 local_pathname = talloc_asprintf(talloc_tos(),
2466 "%s/lockt9.lck", local_path);
2467 if (!local_pathname) {
2468 printf("child: alloc fail\n");
2469 exit(1);
2472 unlink(local_pathname);
2473 fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2474 if (fd == -1) {
2475 printf("child: open of %s failed %s.\n",
2476 local_pathname, strerror(errno));
2477 exit(1);
2480 /* Now take a fcntl lock. */
2481 lock.l_type = F_WRLCK;
2482 lock.l_whence = SEEK_SET;
2483 lock.l_start = 0;
2484 lock.l_len = 4;
2485 lock.l_pid = getpid();
2487 ret = fcntl(fd,F_SETLK,&lock);
2488 if (ret == -1) {
2489 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2490 local_pathname, strerror(errno));
2491 exit(1);
2492 } else {
2493 printf("child: got lock 0:4 on file %s.\n",
2494 local_pathname );
2495 fflush(stdout);
2498 CatchSignal(SIGALRM, alarm_handler);
2499 alarm(5);
2500 /* Signal the parent. */
2501 if (write(write_fd, &c, 1) != 1) {
2502 printf("child: start signal fail %s.\n",
2503 strerror(errno));
2504 exit(1);
2506 alarm(0);
2508 alarm(10);
2509 /* Wait for the parent to be ready. */
2510 if (read(read_fd, &c, 1) != 1) {
2511 printf("child: reply signal fail %s.\n",
2512 strerror(errno));
2513 exit(1);
2515 alarm(0);
2517 sleep(5);
2518 close(fd);
2519 printf("child: released lock 0:4 on file %s.\n",
2520 local_pathname );
2521 fflush(stdout);
2522 exit(0);
2525 static bool run_locktest9(int dummy)
2527 struct cli_state *cli1;
2528 const char *fname = "\\lockt9.lck";
2529 uint16_t fnum;
2530 bool correct = False;
2531 int pipe_in[2], pipe_out[2];
2532 pid_t child_pid;
2533 char c = '\0';
2534 int ret;
2535 struct timeval start;
2536 double seconds;
2537 NTSTATUS status;
2539 printf("starting locktest9\n");
2541 if (local_path == NULL) {
2542 d_fprintf(stderr, "locktest9 must be given a local path via -l <localpath>\n");
2543 return false;
2546 if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2547 return false;
2550 child_pid = fork();
2551 if (child_pid == -1) {
2552 return false;
2555 if (child_pid == 0) {
2556 /* Child. */
2557 do_local_lock(pipe_out[0], pipe_in[1]);
2558 exit(0);
2561 close(pipe_out[0]);
2562 close(pipe_in[1]);
2563 pipe_out[0] = -1;
2564 pipe_in[1] = -1;
2566 /* Parent. */
2567 ret = read(pipe_in[0], &c, 1);
2568 if (ret != 1) {
2569 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2570 strerror(errno));
2571 return false;
2574 if (!torture_open_connection(&cli1, 0)) {
2575 return false;
2578 cli_sockopt(cli1, sockops);
2580 status = cli_open(cli1, fname, O_RDWR, DENY_NONE,
2581 &fnum);
2582 if (!NT_STATUS_IS_OK(status)) {
2583 d_fprintf(stderr, "cli_open returned %s\n", nt_errstr(status));
2584 return false;
2587 /* Ensure the child has the lock. */
2588 if (cli_lock(cli1, fnum, 0, 4, 0, WRITE_LOCK)) {
2589 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2590 goto fail;
2591 } else {
2592 d_printf("Child has the lock.\n");
2595 /* Tell the child to wait 5 seconds then exit. */
2596 ret = write(pipe_out[1], &c, 1);
2597 if (ret != 1) {
2598 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2599 strerror(errno));
2600 goto fail;
2603 /* Wait 20 seconds for the lock. */
2604 alarm_fd = cli1->fd;
2605 CatchSignal(SIGALRM, alarm_handler_parent);
2606 alarm(20);
2608 start = timeval_current();
2610 if (!cli_lock(cli1, fnum, 0, 4, -1, WRITE_LOCK)) {
2611 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2612 "%s\n", cli_errstr(cli1));
2613 goto fail_nofd;
2615 alarm(0);
2617 seconds = timeval_elapsed(&start);
2619 printf("Parent got the lock after %.2f seconds.\n",
2620 seconds);
2622 status = cli_close(cli1, fnum);
2623 if (!NT_STATUS_IS_OK(status)) {
2624 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2625 goto fail;
2628 correct = true;
2630 fail:
2631 cli_close(cli1, fnum);
2632 torture_close_connection(cli1);
2634 fail_nofd:
2636 printf("finished locktest9\n");
2637 return correct;
2641 test whether fnums and tids open on one VC are available on another (a major
2642 security hole)
2644 static bool run_fdpasstest(int dummy)
2646 struct cli_state *cli1, *cli2;
2647 const char *fname = "\\fdpass.tst";
2648 uint16_t fnum1;
2649 char buf[1024];
2650 NTSTATUS status;
2652 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2653 return False;
2655 cli_sockopt(cli1, sockops);
2656 cli_sockopt(cli2, sockops);
2658 printf("starting fdpasstest\n");
2660 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2662 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
2663 &fnum1);
2664 if (!NT_STATUS_IS_OK(status)) {
2665 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2666 return False;
2669 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
2670 13, NULL);
2671 if (!NT_STATUS_IS_OK(status)) {
2672 printf("write failed (%s)\n", nt_errstr(status));
2673 return False;
2676 cli2->vuid = cli1->vuid;
2677 cli2->cnum = cli1->cnum;
2678 cli2->pid = cli1->pid;
2680 if (cli_read(cli2, fnum1, buf, 0, 13) == 13) {
2681 printf("read succeeded! nasty security hole [%s]\n",
2682 buf);
2683 return False;
2686 cli_close(cli1, fnum1);
2687 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2689 torture_close_connection(cli1);
2690 torture_close_connection(cli2);
2692 printf("finished fdpasstest\n");
2693 return True;
2696 static bool run_fdsesstest(int dummy)
2698 struct cli_state *cli;
2699 uint16 new_vuid;
2700 uint16 saved_vuid;
2701 uint16 new_cnum;
2702 uint16 saved_cnum;
2703 const char *fname = "\\fdsess.tst";
2704 const char *fname1 = "\\fdsess1.tst";
2705 uint16_t fnum1;
2706 uint16_t fnum2;
2707 char buf[1024];
2708 bool ret = True;
2709 NTSTATUS status;
2711 if (!torture_open_connection(&cli, 0))
2712 return False;
2713 cli_sockopt(cli, sockops);
2715 if (!torture_cli_session_setup2(cli, &new_vuid))
2716 return False;
2718 saved_cnum = cli->cnum;
2719 if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, share, "?????", "", 1)))
2720 return False;
2721 new_cnum = cli->cnum;
2722 cli->cnum = saved_cnum;
2724 printf("starting fdsesstest\n");
2726 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2727 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2729 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2730 if (!NT_STATUS_IS_OK(status)) {
2731 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2732 return False;
2735 status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
2736 NULL);
2737 if (!NT_STATUS_IS_OK(status)) {
2738 printf("write failed (%s)\n", nt_errstr(status));
2739 return False;
2742 saved_vuid = cli->vuid;
2743 cli->vuid = new_vuid;
2745 if (cli_read(cli, fnum1, buf, 0, 13) == 13) {
2746 printf("read succeeded with different vuid! nasty security hole [%s]\n",
2747 buf);
2748 ret = False;
2750 /* Try to open a file with different vuid, samba cnum. */
2751 if (NT_STATUS_IS_OK(cli_open(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
2752 printf("create with different vuid, same cnum succeeded.\n");
2753 cli_close(cli, fnum2);
2754 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2755 } else {
2756 printf("create with different vuid, same cnum failed.\n");
2757 printf("This will cause problems with service clients.\n");
2758 ret = False;
2761 cli->vuid = saved_vuid;
2763 /* Try with same vuid, different cnum. */
2764 cli->cnum = new_cnum;
2766 if (cli_read(cli, fnum1, buf, 0, 13) == 13) {
2767 printf("read succeeded with different cnum![%s]\n",
2768 buf);
2769 ret = False;
2772 cli->cnum = saved_cnum;
2773 cli_close(cli, fnum1);
2774 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2776 torture_close_connection(cli);
2778 printf("finished fdsesstest\n");
2779 return ret;
2783 This test checks that
2785 1) the server does not allow an unlink on a file that is open
2787 static bool run_unlinktest(int dummy)
2789 struct cli_state *cli;
2790 const char *fname = "\\unlink.tst";
2791 uint16_t fnum;
2792 bool correct = True;
2793 NTSTATUS status;
2795 if (!torture_open_connection(&cli, 0)) {
2796 return False;
2799 cli_sockopt(cli, sockops);
2801 printf("starting unlink test\n");
2803 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2805 cli_setpid(cli, 1);
2807 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2808 if (!NT_STATUS_IS_OK(status)) {
2809 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2810 return False;
2813 status = cli_unlink(cli, fname,
2814 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2815 if (NT_STATUS_IS_OK(status)) {
2816 printf("error: server allowed unlink on an open file\n");
2817 correct = False;
2818 } else {
2819 correct = check_error(__LINE__, cli, ERRDOS, ERRbadshare,
2820 NT_STATUS_SHARING_VIOLATION);
2823 cli_close(cli, fnum);
2824 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2826 if (!torture_close_connection(cli)) {
2827 correct = False;
2830 printf("unlink test finished\n");
2832 return correct;
2837 test how many open files this server supports on the one socket
2839 static bool run_maxfidtest(int dummy)
2841 struct cli_state *cli;
2842 fstring fname;
2843 uint16_t fnums[0x11000];
2844 int i;
2845 int retries=4;
2846 bool correct = True;
2847 NTSTATUS status;
2849 cli = current_cli;
2851 if (retries <= 0) {
2852 printf("failed to connect\n");
2853 return False;
2856 cli_sockopt(cli, sockops);
2858 for (i=0; i<0x11000; i++) {
2859 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2860 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
2861 &fnums[i]);
2862 if (!NT_STATUS_IS_OK(status)) {
2863 printf("open of %s failed (%s)\n",
2864 fname, nt_errstr(status));
2865 printf("maximum fnum is %d\n", i);
2866 break;
2868 printf("%6d\r", i);
2870 printf("%6d\n", i);
2871 i--;
2873 printf("cleaning up\n");
2874 for (;i>=0;i--) {
2875 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2876 cli_close(cli, fnums[i]);
2878 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2879 if (!NT_STATUS_IS_OK(status)) {
2880 printf("unlink of %s failed (%s)\n",
2881 fname, nt_errstr(status));
2882 correct = False;
2884 printf("%6d\r", i);
2886 printf("%6d\n", 0);
2888 printf("maxfid test finished\n");
2889 if (!torture_close_connection(cli)) {
2890 correct = False;
2892 return correct;
2895 /* generate a random buffer */
2896 static void rand_buf(char *buf, int len)
2898 while (len--) {
2899 *buf = (char)sys_random();
2900 buf++;
2904 /* send smb negprot commands, not reading the response */
2905 static bool run_negprot_nowait(int dummy)
2907 struct tevent_context *ev;
2908 int i;
2909 struct cli_state *cli;
2910 bool correct = True;
2912 printf("starting negprot nowait test\n");
2914 ev = tevent_context_init(talloc_tos());
2915 if (ev == NULL) {
2916 return false;
2919 if (!(cli = open_nbt_connection())) {
2920 TALLOC_FREE(ev);
2921 return False;
2924 for (i=0;i<50000;i++) {
2925 struct tevent_req *req;
2927 req = cli_negprot_send(ev, ev, cli);
2928 if (req == NULL) {
2929 TALLOC_FREE(ev);
2930 return false;
2932 if (!tevent_req_poll(req, ev)) {
2933 d_fprintf(stderr, "tevent_req_poll failed: %s\n",
2934 strerror(errno));
2935 TALLOC_FREE(ev);
2936 return false;
2938 TALLOC_FREE(req);
2941 if (torture_close_connection(cli)) {
2942 correct = False;
2945 printf("finished negprot nowait test\n");
2947 return correct;
2950 /* send smb negprot commands, not reading the response */
2951 static bool run_bad_nbt_session(int dummy)
2953 struct nmb_name called, calling;
2954 struct sockaddr_storage ss;
2955 NTSTATUS status;
2956 int fd;
2957 bool ret;
2959 printf("starting bad nbt session test\n");
2961 make_nmb_name(&calling, myname, 0x0);
2962 make_nmb_name(&called , host, 0x20);
2964 if (!resolve_name(host, &ss, 0x20, true)) {
2965 d_fprintf(stderr, "Could not resolve name %s\n", host);
2966 return false;
2969 status = open_socket_out(&ss, 139, 10000, &fd);
2970 if (!NT_STATUS_IS_OK(status)) {
2971 d_fprintf(stderr, "open_socket_out failed: %s\n",
2972 nt_errstr(status));
2973 return false;
2976 ret = cli_bad_session_request(fd, &calling, &called);
2977 close(fd);
2978 if (!ret) {
2979 d_fprintf(stderr, "open_socket_out failed: %s\n",
2980 nt_errstr(status));
2981 return false;
2984 printf("finished bad nbt session test\n");
2985 return true;
2988 /* send random IPC commands */
2989 static bool run_randomipc(int dummy)
2991 char *rparam = NULL;
2992 char *rdata = NULL;
2993 unsigned int rdrcnt,rprcnt;
2994 char param[1024];
2995 int api, param_len, i;
2996 struct cli_state *cli;
2997 bool correct = True;
2998 int count = 50000;
3000 printf("starting random ipc test\n");
3002 if (!torture_open_connection(&cli, 0)) {
3003 return False;
3006 for (i=0;i<count;i++) {
3007 api = sys_random() % 500;
3008 param_len = (sys_random() % 64);
3010 rand_buf(param, param_len);
3012 SSVAL(param,0,api);
3014 cli_api(cli,
3015 param, param_len, 8,
3016 NULL, 0, BUFFER_SIZE,
3017 &rparam, &rprcnt,
3018 &rdata, &rdrcnt);
3019 if (i % 100 == 0) {
3020 printf("%d/%d\r", i,count);
3023 printf("%d/%d\n", i, count);
3025 if (!torture_close_connection(cli)) {
3026 correct = False;
3029 printf("finished random ipc test\n");
3031 return correct;
3036 static void browse_callback(const char *sname, uint32 stype,
3037 const char *comment, void *state)
3039 printf("\t%20.20s %08x %s\n", sname, stype, comment);
3045 This test checks the browse list code
3048 static bool run_browsetest(int dummy)
3050 static struct cli_state *cli;
3051 bool correct = True;
3053 printf("starting browse test\n");
3055 if (!torture_open_connection(&cli, 0)) {
3056 return False;
3059 printf("domain list:\n");
3060 cli_NetServerEnum(cli, cli->server_domain,
3061 SV_TYPE_DOMAIN_ENUM,
3062 browse_callback, NULL);
3064 printf("machine list:\n");
3065 cli_NetServerEnum(cli, cli->server_domain,
3066 SV_TYPE_ALL,
3067 browse_callback, NULL);
3069 if (!torture_close_connection(cli)) {
3070 correct = False;
3073 printf("browse test finished\n");
3075 return correct;
3081 This checks how the getatr calls works
3083 static bool run_attrtest(int dummy)
3085 struct cli_state *cli;
3086 uint16_t fnum;
3087 time_t t, t2;
3088 const char *fname = "\\attrib123456789.tst";
3089 bool correct = True;
3090 NTSTATUS status;
3092 printf("starting attrib test\n");
3094 if (!torture_open_connection(&cli, 0)) {
3095 return False;
3098 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3099 cli_open(cli, fname,
3100 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3101 cli_close(cli, fnum);
3103 status = cli_getatr(cli, fname, NULL, NULL, &t);
3104 if (!NT_STATUS_IS_OK(status)) {
3105 printf("getatr failed (%s)\n", nt_errstr(status));
3106 correct = False;
3109 if (abs(t - time(NULL)) > 60*60*24*10) {
3110 printf("ERROR: SMBgetatr bug. time is %s",
3111 ctime(&t));
3112 t = time(NULL);
3113 correct = True;
3116 t2 = t-60*60*24; /* 1 day ago */
3118 status = cli_setatr(cli, fname, 0, t2);
3119 if (!NT_STATUS_IS_OK(status)) {
3120 printf("setatr failed (%s)\n", nt_errstr(status));
3121 correct = True;
3124 status = cli_getatr(cli, fname, NULL, NULL, &t);
3125 if (!NT_STATUS_IS_OK(status)) {
3126 printf("getatr failed (%s)\n", nt_errstr(status));
3127 correct = True;
3130 if (t != t2) {
3131 printf("ERROR: getatr/setatr bug. times are\n%s",
3132 ctime(&t));
3133 printf("%s", ctime(&t2));
3134 correct = True;
3137 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3139 if (!torture_close_connection(cli)) {
3140 correct = False;
3143 printf("attrib test finished\n");
3145 return correct;
3150 This checks a couple of trans2 calls
3152 static bool run_trans2test(int dummy)
3154 struct cli_state *cli;
3155 uint16_t fnum;
3156 SMB_OFF_T size;
3157 time_t c_time, a_time, m_time;
3158 struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
3159 const char *fname = "\\trans2.tst";
3160 const char *dname = "\\trans2";
3161 const char *fname2 = "\\trans2\\trans2.tst";
3162 char *pname;
3163 bool correct = True;
3164 NTSTATUS status;
3165 uint32_t fs_attr;
3167 printf("starting trans2 test\n");
3169 if (!torture_open_connection(&cli, 0)) {
3170 return False;
3173 status = cli_get_fs_attr_info(cli, &fs_attr);
3174 if (!NT_STATUS_IS_OK(status)) {
3175 printf("ERROR: cli_get_fs_attr_info returned %s\n",
3176 nt_errstr(status));
3177 correct = false;
3180 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3181 cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3182 status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
3183 &a_time_ts, &w_time_ts, &m_time_ts, NULL);
3184 if (!NT_STATUS_IS_OK(status)) {
3185 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
3186 correct = False;
3189 status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
3190 if (!NT_STATUS_IS_OK(status)) {
3191 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
3192 correct = False;
3195 if (strcmp(pname, fname)) {
3196 printf("qfilename gave different name? [%s] [%s]\n",
3197 fname, pname);
3198 correct = False;
3201 cli_close(cli, fnum);
3203 sleep(2);
3205 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3206 status = cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
3207 &fnum);
3208 if (!NT_STATUS_IS_OK(status)) {
3209 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3210 return False;
3212 cli_close(cli, fnum);
3214 status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
3215 NULL);
3216 if (!NT_STATUS_IS_OK(status)) {
3217 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
3218 correct = False;
3219 } else {
3220 if (c_time != m_time) {
3221 printf("create time=%s", ctime(&c_time));
3222 printf("modify time=%s", ctime(&m_time));
3223 printf("This system appears to have sticky create times\n");
3225 if (a_time % (60*60) == 0) {
3226 printf("access time=%s", ctime(&a_time));
3227 printf("This system appears to set a midnight access time\n");
3228 correct = False;
3231 if (abs(m_time - time(NULL)) > 60*60*24*7) {
3232 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
3233 correct = False;
3238 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3239 cli_open(cli, fname,
3240 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3241 cli_close(cli, fnum);
3242 status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
3243 &m_time_ts, &size, NULL, NULL);
3244 if (!NT_STATUS_IS_OK(status)) {
3245 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3246 correct = False;
3247 } else {
3248 if (w_time_ts.tv_sec < 60*60*24*2) {
3249 printf("write time=%s", ctime(&w_time_ts.tv_sec));
3250 printf("This system appears to set a initial 0 write time\n");
3251 correct = False;
3255 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3258 /* check if the server updates the directory modification time
3259 when creating a new file */
3260 status = cli_mkdir(cli, dname);
3261 if (!NT_STATUS_IS_OK(status)) {
3262 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
3263 correct = False;
3265 sleep(3);
3266 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3267 &w_time_ts, &m_time_ts, &size, NULL, NULL);
3268 if (!NT_STATUS_IS_OK(status)) {
3269 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3270 correct = False;
3273 cli_open(cli, fname2,
3274 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3275 cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
3276 cli_close(cli, fnum);
3277 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3278 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
3279 if (!NT_STATUS_IS_OK(status)) {
3280 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3281 correct = False;
3282 } else {
3283 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
3284 == 0) {
3285 printf("This system does not update directory modification times\n");
3286 correct = False;
3289 cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3290 cli_rmdir(cli, dname);
3292 if (!torture_close_connection(cli)) {
3293 correct = False;
3296 printf("trans2 test finished\n");
3298 return correct;
3302 This checks new W2K calls.
3305 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
3307 uint8_t *buf = NULL;
3308 uint32 len;
3309 NTSTATUS status;
3311 status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
3312 pcli->max_xmit, NULL, &buf, &len);
3313 if (!NT_STATUS_IS_OK(status)) {
3314 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
3315 nt_errstr(status));
3316 } else {
3317 printf("qfileinfo: level %d, len = %u\n", level, len);
3318 dump_data(0, (uint8 *)buf, len);
3319 printf("\n");
3321 TALLOC_FREE(buf);
3322 return status;
3325 static bool run_w2ktest(int dummy)
3327 struct cli_state *cli;
3328 uint16_t fnum;
3329 const char *fname = "\\w2ktest\\w2k.tst";
3330 int level;
3331 bool correct = True;
3333 printf("starting w2k test\n");
3335 if (!torture_open_connection(&cli, 0)) {
3336 return False;
3339 cli_open(cli, fname,
3340 O_RDWR | O_CREAT , DENY_NONE, &fnum);
3342 for (level = 1004; level < 1040; level++) {
3343 new_trans(cli, fnum, level);
3346 cli_close(cli, fnum);
3348 if (!torture_close_connection(cli)) {
3349 correct = False;
3352 printf("w2k test finished\n");
3354 return correct;
3359 this is a harness for some oplock tests
3361 static bool run_oplock1(int dummy)
3363 struct cli_state *cli1;
3364 const char *fname = "\\lockt1.lck";
3365 uint16_t fnum1;
3366 bool correct = True;
3367 NTSTATUS status;
3369 printf("starting oplock test 1\n");
3371 if (!torture_open_connection(&cli1, 0)) {
3372 return False;
3375 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3377 cli_sockopt(cli1, sockops);
3379 cli1->use_oplocks = True;
3381 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3382 &fnum1);
3383 if (!NT_STATUS_IS_OK(status)) {
3384 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3385 return False;
3388 cli1->use_oplocks = False;
3390 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3391 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3393 status = cli_close(cli1, fnum1);
3394 if (!NT_STATUS_IS_OK(status)) {
3395 printf("close2 failed (%s)\n", nt_errstr(status));
3396 return False;
3399 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3400 if (!NT_STATUS_IS_OK(status)) {
3401 printf("unlink failed (%s)\n", nt_errstr(status));
3402 return False;
3405 if (!torture_close_connection(cli1)) {
3406 correct = False;
3409 printf("finished oplock test 1\n");
3411 return correct;
3414 static bool run_oplock2(int dummy)
3416 struct cli_state *cli1, *cli2;
3417 const char *fname = "\\lockt2.lck";
3418 uint16_t fnum1, fnum2;
3419 int saved_use_oplocks = use_oplocks;
3420 char buf[4];
3421 bool correct = True;
3422 volatile bool *shared_correct;
3423 NTSTATUS status;
3425 shared_correct = (volatile bool *)shm_setup(sizeof(bool));
3426 *shared_correct = True;
3428 use_level_II_oplocks = True;
3429 use_oplocks = True;
3431 printf("starting oplock test 2\n");
3433 if (!torture_open_connection(&cli1, 0)) {
3434 use_level_II_oplocks = False;
3435 use_oplocks = saved_use_oplocks;
3436 return False;
3439 cli1->use_oplocks = True;
3440 cli1->use_level_II_oplocks = True;
3442 if (!torture_open_connection(&cli2, 1)) {
3443 use_level_II_oplocks = False;
3444 use_oplocks = saved_use_oplocks;
3445 return False;
3448 cli2->use_oplocks = True;
3449 cli2->use_level_II_oplocks = True;
3451 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3453 cli_sockopt(cli1, sockops);
3454 cli_sockopt(cli2, sockops);
3456 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3457 &fnum1);
3458 if (!NT_STATUS_IS_OK(status)) {
3459 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3460 return False;
3463 /* Don't need the globals any more. */
3464 use_level_II_oplocks = False;
3465 use_oplocks = saved_use_oplocks;
3467 if (fork() == 0) {
3468 /* Child code */
3469 status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
3470 if (!NT_STATUS_IS_OK(status)) {
3471 printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
3472 *shared_correct = False;
3473 exit(0);
3476 sleep(2);
3478 status = cli_close(cli2, fnum2);
3479 if (!NT_STATUS_IS_OK(status)) {
3480 printf("close2 failed (%s)\n", nt_errstr(status));
3481 *shared_correct = False;
3484 exit(0);
3487 sleep(2);
3489 /* Ensure cli1 processes the break. Empty file should always return 0
3490 * bytes. */
3492 if (cli_read(cli1, fnum1, buf, 0, 4) != 0) {
3493 printf("read on fnum1 failed (%s)\n", cli_errstr(cli1));
3494 correct = False;
3497 /* Should now be at level II. */
3498 /* Test if sending a write locks causes a break to none. */
3500 if (!cli_lock(cli1, fnum1, 0, 4, 0, READ_LOCK)) {
3501 printf("lock failed (%s)\n", cli_errstr(cli1));
3502 correct = False;
3505 cli_unlock(cli1, fnum1, 0, 4);
3507 sleep(2);
3509 if (!cli_lock(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) {
3510 printf("lock failed (%s)\n", cli_errstr(cli1));
3511 correct = False;
3514 cli_unlock(cli1, fnum1, 0, 4);
3516 sleep(2);
3518 cli_read(cli1, fnum1, buf, 0, 4);
3520 status = cli_close(cli1, fnum1);
3521 if (!NT_STATUS_IS_OK(status)) {
3522 printf("close1 failed (%s)\n", nt_errstr(status));
3523 correct = False;
3526 sleep(4);
3528 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3529 if (!NT_STATUS_IS_OK(status)) {
3530 printf("unlink failed (%s)\n", nt_errstr(status));
3531 correct = False;
3534 if (!torture_close_connection(cli1)) {
3535 correct = False;
3538 if (!*shared_correct) {
3539 correct = False;
3542 printf("finished oplock test 2\n");
3544 return correct;
3547 struct oplock4_state {
3548 struct tevent_context *ev;
3549 struct cli_state *cli;
3550 bool *got_break;
3551 uint16_t *fnum2;
3554 static void oplock4_got_break(struct tevent_req *req);
3555 static void oplock4_got_open(struct tevent_req *req);
3557 static bool run_oplock4(int dummy)
3559 struct tevent_context *ev;
3560 struct cli_state *cli1, *cli2;
3561 struct tevent_req *oplock_req, *open_req;
3562 const char *fname = "\\lockt4.lck";
3563 const char *fname_ln = "\\lockt4_ln.lck";
3564 uint16_t fnum1, fnum2;
3565 int saved_use_oplocks = use_oplocks;
3566 NTSTATUS status;
3567 bool correct = true;
3569 bool got_break;
3571 struct oplock4_state *state;
3573 printf("starting oplock test 4\n");
3575 if (!torture_open_connection(&cli1, 0)) {
3576 use_level_II_oplocks = false;
3577 use_oplocks = saved_use_oplocks;
3578 return false;
3581 if (!torture_open_connection(&cli2, 1)) {
3582 use_level_II_oplocks = false;
3583 use_oplocks = saved_use_oplocks;
3584 return false;
3587 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3588 cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3590 cli_sockopt(cli1, sockops);
3591 cli_sockopt(cli2, sockops);
3593 /* Create the file. */
3594 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3595 &fnum1);
3596 if (!NT_STATUS_IS_OK(status)) {
3597 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3598 return false;
3601 status = cli_close(cli1, fnum1);
3602 if (!NT_STATUS_IS_OK(status)) {
3603 printf("close1 failed (%s)\n", nt_errstr(status));
3604 return false;
3607 /* Now create a hardlink. */
3608 status = cli_nt_hardlink(cli1, fname, fname_ln);
3609 if (!NT_STATUS_IS_OK(status)) {
3610 printf("nt hardlink failed (%s)\n", nt_errstr(status));
3611 return false;
3614 /* Prove that opening hardlinks cause deny modes to conflict. */
3615 status = cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
3616 if (!NT_STATUS_IS_OK(status)) {
3617 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3618 return false;
3621 status = cli_open(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
3622 if (NT_STATUS_IS_OK(status)) {
3623 printf("open of %s succeeded - should fail with sharing violation.\n",
3624 fname_ln);
3625 return false;
3628 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3629 printf("open of %s should fail with sharing violation. Got %s\n",
3630 fname_ln, nt_errstr(status));
3631 return false;
3634 status = cli_close(cli1, fnum1);
3635 if (!NT_STATUS_IS_OK(status)) {
3636 printf("close1 failed (%s)\n", nt_errstr(status));
3637 return false;
3640 cli1->use_oplocks = true;
3641 cli1->use_level_II_oplocks = true;
3643 cli2->use_oplocks = true;
3644 cli2->use_level_II_oplocks = true;
3646 status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3647 if (!NT_STATUS_IS_OK(status)) {
3648 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3649 return false;
3652 ev = tevent_context_init(talloc_tos());
3653 if (ev == NULL) {
3654 printf("tevent_req_create failed\n");
3655 return false;
3658 state = talloc(ev, struct oplock4_state);
3659 if (state == NULL) {
3660 printf("talloc failed\n");
3661 return false;
3663 state->ev = ev;
3664 state->cli = cli1;
3665 state->got_break = &got_break;
3666 state->fnum2 = &fnum2;
3668 oplock_req = cli_smb_oplock_break_waiter_send(
3669 talloc_tos(), ev, cli1);
3670 if (oplock_req == NULL) {
3671 printf("cli_smb_oplock_break_waiter_send failed\n");
3672 return false;
3674 tevent_req_set_callback(oplock_req, oplock4_got_break, state);
3676 open_req = cli_open_send(
3677 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
3678 if (oplock_req == NULL) {
3679 printf("cli_open_send failed\n");
3680 return false;
3682 tevent_req_set_callback(open_req, oplock4_got_open, state);
3684 got_break = false;
3685 fnum2 = 0xffff;
3687 while (!got_break || fnum2 == 0xffff) {
3688 int ret;
3689 ret = tevent_loop_once(ev);
3690 if (ret == -1) {
3691 printf("tevent_loop_once failed: %s\n",
3692 strerror(errno));
3693 return false;
3697 status = cli_close(cli2, fnum2);
3698 if (!NT_STATUS_IS_OK(status)) {
3699 printf("close2 failed (%s)\n", nt_errstr(status));
3700 correct = false;
3703 status = cli_close(cli1, fnum1);
3704 if (!NT_STATUS_IS_OK(status)) {
3705 printf("close1 failed (%s)\n", nt_errstr(status));
3706 correct = false;
3709 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3710 if (!NT_STATUS_IS_OK(status)) {
3711 printf("unlink failed (%s)\n", nt_errstr(status));
3712 correct = false;
3715 status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3716 if (!NT_STATUS_IS_OK(status)) {
3717 printf("unlink failed (%s)\n", nt_errstr(status));
3718 correct = false;
3721 if (!torture_close_connection(cli1)) {
3722 correct = false;
3725 if (!got_break) {
3726 correct = false;
3729 printf("finished oplock test 4\n");
3731 return correct;
3734 static void oplock4_got_break(struct tevent_req *req)
3736 struct oplock4_state *state = tevent_req_callback_data(
3737 req, struct oplock4_state);
3738 uint16_t fnum;
3739 uint8_t level;
3740 NTSTATUS status;
3742 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
3743 TALLOC_FREE(req);
3744 if (!NT_STATUS_IS_OK(status)) {
3745 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
3746 nt_errstr(status));
3747 return;
3749 *state->got_break = true;
3751 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
3752 NO_OPLOCK);
3753 if (req == NULL) {
3754 printf("cli_oplock_ack_send failed\n");
3755 return;
3759 static void oplock4_got_open(struct tevent_req *req)
3761 struct oplock4_state *state = tevent_req_callback_data(
3762 req, struct oplock4_state);
3763 NTSTATUS status;
3765 status = cli_open_recv(req, state->fnum2);
3766 if (!NT_STATUS_IS_OK(status)) {
3767 printf("cli_open_recv returned %s\n", nt_errstr(status));
3768 *state->fnum2 = 0xffff;
3773 Test delete on close semantics.
3775 static bool run_deletetest(int dummy)
3777 struct cli_state *cli1 = NULL;
3778 struct cli_state *cli2 = NULL;
3779 const char *fname = "\\delete.file";
3780 uint16_t fnum1 = (uint16_t)-1;
3781 uint16_t fnum2 = (uint16_t)-1;
3782 bool correct = True;
3783 NTSTATUS status;
3785 printf("starting delete test\n");
3787 if (!torture_open_connection(&cli1, 0)) {
3788 return False;
3791 cli_sockopt(cli1, sockops);
3793 /* Test 1 - this should delete the file on close. */
3795 cli_setatr(cli1, fname, 0, 0);
3796 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3798 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
3799 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
3800 FILE_DELETE_ON_CLOSE, 0, &fnum1);
3801 if (!NT_STATUS_IS_OK(status)) {
3802 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
3803 correct = False;
3804 goto fail;
3807 status = cli_close(cli1, fnum1);
3808 if (!NT_STATUS_IS_OK(status)) {
3809 printf("[1] close failed (%s)\n", nt_errstr(status));
3810 correct = False;
3811 goto fail;
3814 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1))) {
3815 printf("[1] open of %s succeeded (should fail)\n", fname);
3816 correct = False;
3817 goto fail;
3820 printf("first delete on close test succeeded.\n");
3822 /* Test 2 - this should delete the file on close. */
3824 cli_setatr(cli1, fname, 0, 0);
3825 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3827 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3828 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
3829 FILE_OVERWRITE_IF, 0, 0, &fnum1);
3830 if (!NT_STATUS_IS_OK(status)) {
3831 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
3832 correct = False;
3833 goto fail;
3836 status = cli_nt_delete_on_close(cli1, fnum1, true);
3837 if (!NT_STATUS_IS_OK(status)) {
3838 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
3839 correct = False;
3840 goto fail;
3843 status = cli_close(cli1, fnum1);
3844 if (!NT_STATUS_IS_OK(status)) {
3845 printf("[2] close failed (%s)\n", nt_errstr(status));
3846 correct = False;
3847 goto fail;
3850 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3851 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
3852 status = cli_close(cli1, fnum1);
3853 if (!NT_STATUS_IS_OK(status)) {
3854 printf("[2] close failed (%s)\n", nt_errstr(status));
3855 correct = False;
3856 goto fail;
3858 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3859 } else
3860 printf("second delete on close test succeeded.\n");
3862 /* Test 3 - ... */
3863 cli_setatr(cli1, fname, 0, 0);
3864 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3866 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3867 FILE_ATTRIBUTE_NORMAL,
3868 FILE_SHARE_READ|FILE_SHARE_WRITE,
3869 FILE_OVERWRITE_IF, 0, 0, &fnum1);
3870 if (!NT_STATUS_IS_OK(status)) {
3871 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
3872 correct = False;
3873 goto fail;
3876 /* This should fail with a sharing violation - open for delete is only compatible
3877 with SHARE_DELETE. */
3879 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
3880 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, 0, &fnum2))) {
3881 printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
3882 correct = False;
3883 goto fail;
3886 /* This should succeed. */
3887 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3888 FILE_ATTRIBUTE_NORMAL,
3889 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3890 FILE_OPEN, 0, 0, &fnum2);
3891 if (!NT_STATUS_IS_OK(status)) {
3892 printf("[3] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
3893 correct = False;
3894 goto fail;
3897 status = cli_nt_delete_on_close(cli1, fnum1, true);
3898 if (!NT_STATUS_IS_OK(status)) {
3899 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
3900 correct = False;
3901 goto fail;
3904 status = cli_close(cli1, fnum1);
3905 if (!NT_STATUS_IS_OK(status)) {
3906 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
3907 correct = False;
3908 goto fail;
3911 status = cli_close(cli1, fnum2);
3912 if (!NT_STATUS_IS_OK(status)) {
3913 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
3914 correct = False;
3915 goto fail;
3918 /* This should fail - file should no longer be there. */
3920 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3921 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
3922 status = cli_close(cli1, fnum1);
3923 if (!NT_STATUS_IS_OK(status)) {
3924 printf("[3] close failed (%s)\n", nt_errstr(status));
3926 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3927 correct = False;
3928 goto fail;
3929 } else
3930 printf("third delete on close test succeeded.\n");
3932 /* Test 4 ... */
3933 cli_setatr(cli1, fname, 0, 0);
3934 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3936 status = cli_ntcreate(cli1, fname, 0,
3937 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
3938 FILE_ATTRIBUTE_NORMAL,
3939 FILE_SHARE_READ|FILE_SHARE_WRITE,
3940 FILE_OVERWRITE_IF, 0, 0, &fnum1);
3941 if (!NT_STATUS_IS_OK(status)) {
3942 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
3943 correct = False;
3944 goto fail;
3947 /* This should succeed. */
3948 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3949 FILE_ATTRIBUTE_NORMAL,
3950 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3951 FILE_OPEN, 0, 0, &fnum2);
3952 if (!NT_STATUS_IS_OK(status)) {
3953 printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
3954 correct = False;
3955 goto fail;
3958 status = cli_close(cli1, fnum2);
3959 if (!NT_STATUS_IS_OK(status)) {
3960 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
3961 correct = False;
3962 goto fail;
3965 status = cli_nt_delete_on_close(cli1, fnum1, true);
3966 if (!NT_STATUS_IS_OK(status)) {
3967 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
3968 correct = False;
3969 goto fail;
3972 /* This should fail - no more opens once delete on close set. */
3973 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3974 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3975 FILE_OPEN, 0, 0, &fnum2))) {
3976 printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
3977 correct = False;
3978 goto fail;
3979 } else
3980 printf("fourth delete on close test succeeded.\n");
3982 status = cli_close(cli1, fnum1);
3983 if (!NT_STATUS_IS_OK(status)) {
3984 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
3985 correct = False;
3986 goto fail;
3989 /* Test 5 ... */
3990 cli_setatr(cli1, fname, 0, 0);
3991 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3993 status = cli_open(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
3994 if (!NT_STATUS_IS_OK(status)) {
3995 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
3996 correct = False;
3997 goto fail;
4000 /* This should fail - only allowed on NT opens with DELETE access. */
4002 if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4003 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
4004 correct = False;
4005 goto fail;
4008 status = cli_close(cli1, fnum1);
4009 if (!NT_STATUS_IS_OK(status)) {
4010 printf("[5] close - 2 failed (%s)\n", nt_errstr(status));
4011 correct = False;
4012 goto fail;
4015 printf("fifth delete on close test succeeded.\n");
4017 /* Test 6 ... */
4018 cli_setatr(cli1, fname, 0, 0);
4019 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4021 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4022 FILE_ATTRIBUTE_NORMAL,
4023 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4024 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4025 if (!NT_STATUS_IS_OK(status)) {
4026 printf("[6] open of %s failed (%s)\n", fname,
4027 nt_errstr(status));
4028 correct = False;
4029 goto fail;
4032 /* This should fail - only allowed on NT opens with DELETE access. */
4034 if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4035 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
4036 correct = False;
4037 goto fail;
4040 status = cli_close(cli1, fnum1);
4041 if (!NT_STATUS_IS_OK(status)) {
4042 printf("[6] close - 2 failed (%s)\n", nt_errstr(status));
4043 correct = False;
4044 goto fail;
4047 printf("sixth delete on close test succeeded.\n");
4049 /* Test 7 ... */
4050 cli_setatr(cli1, fname, 0, 0);
4051 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4053 status = cli_ntcreate(cli1, fname, 0,
4054 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4055 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
4056 0, 0, &fnum1);
4057 if (!NT_STATUS_IS_OK(status)) {
4058 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4059 correct = False;
4060 goto fail;
4063 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4064 printf("[7] setting delete_on_close on file failed !\n");
4065 correct = False;
4066 goto fail;
4069 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, false))) {
4070 printf("[7] unsetting delete_on_close on file failed !\n");
4071 correct = False;
4072 goto fail;
4075 status = cli_close(cli1, fnum1);
4076 if (!NT_STATUS_IS_OK(status)) {
4077 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4078 correct = False;
4079 goto fail;
4082 /* This next open should succeed - we reset the flag. */
4083 status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4084 if (!NT_STATUS_IS_OK(status)) {
4085 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4086 correct = False;
4087 goto fail;
4090 status = cli_close(cli1, fnum1);
4091 if (!NT_STATUS_IS_OK(status)) {
4092 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4093 correct = False;
4094 goto fail;
4097 printf("seventh delete on close test succeeded.\n");
4099 /* Test 7 ... */
4100 cli_setatr(cli1, fname, 0, 0);
4101 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4103 if (!torture_open_connection(&cli2, 1)) {
4104 printf("[8] failed to open second connection.\n");
4105 correct = False;
4106 goto fail;
4109 cli_sockopt(cli1, sockops);
4111 status = cli_ntcreate(cli1, fname, 0,
4112 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4113 FILE_ATTRIBUTE_NORMAL,
4114 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4115 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4116 if (!NT_STATUS_IS_OK(status)) {
4117 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4118 correct = False;
4119 goto fail;
4122 status = cli_ntcreate(cli2, fname, 0,
4123 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4124 FILE_ATTRIBUTE_NORMAL,
4125 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4126 FILE_OPEN, 0, 0, &fnum2);
4127 if (!NT_STATUS_IS_OK(status)) {
4128 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4129 correct = False;
4130 goto fail;
4133 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4134 printf("[8] setting delete_on_close on file failed !\n");
4135 correct = False;
4136 goto fail;
4139 status = cli_close(cli1, fnum1);
4140 if (!NT_STATUS_IS_OK(status)) {
4141 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
4142 correct = False;
4143 goto fail;
4146 status = cli_close(cli2, fnum2);
4147 if (!NT_STATUS_IS_OK(status)) {
4148 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
4149 correct = False;
4150 goto fail;
4153 /* This should fail.. */
4154 status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4155 if (NT_STATUS_IS_OK(status)) {
4156 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
4157 goto fail;
4158 correct = False;
4159 } else
4160 printf("eighth delete on close test succeeded.\n");
4162 /* This should fail - we need to set DELETE_ACCESS. */
4163 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0,FILE_READ_DATA|FILE_WRITE_DATA,
4164 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE, 0, &fnum1))) {
4165 printf("[9] open of %s succeeded should have failed!\n", fname);
4166 correct = False;
4167 goto fail;
4170 printf("ninth delete on close test succeeded.\n");
4172 status = cli_ntcreate(cli1, fname, 0,
4173 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4174 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4175 FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
4176 0, &fnum1);
4177 if (!NT_STATUS_IS_OK(status)) {
4178 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
4179 correct = False;
4180 goto fail;
4183 /* This should delete the file. */
4184 status = cli_close(cli1, fnum1);
4185 if (!NT_STATUS_IS_OK(status)) {
4186 printf("[10] close failed (%s)\n", nt_errstr(status));
4187 correct = False;
4188 goto fail;
4191 /* This should fail.. */
4192 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
4193 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
4194 goto fail;
4195 correct = False;
4196 } else
4197 printf("tenth delete on close test succeeded.\n");
4199 cli_setatr(cli1, fname, 0, 0);
4200 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4202 /* What error do we get when attempting to open a read-only file with
4203 delete access ? */
4205 /* Create a readonly file. */
4206 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4207 FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
4208 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4209 if (!NT_STATUS_IS_OK(status)) {
4210 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
4211 correct = False;
4212 goto fail;
4215 status = cli_close(cli1, fnum1);
4216 if (!NT_STATUS_IS_OK(status)) {
4217 printf("[11] close failed (%s)\n", nt_errstr(status));
4218 correct = False;
4219 goto fail;
4222 /* Now try open for delete access. */
4223 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES|DELETE_ACCESS,
4224 0, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4225 FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4226 printf("[11] open of %s succeeded should have been denied with ACCESS_DENIED!\n", fname);
4227 cli_close(cli1, fnum1);
4228 goto fail;
4229 correct = False;
4230 } else {
4231 NTSTATUS nterr = cli_nt_error(cli1);
4232 if (!NT_STATUS_EQUAL(nterr,NT_STATUS_ACCESS_DENIED)) {
4233 printf("[11] open of %s should have been denied with ACCESS_DENIED! Got error %s\n", fname, nt_errstr(nterr));
4234 goto fail;
4235 correct = False;
4236 } else {
4237 printf("eleventh delete on close test succeeded.\n");
4241 printf("finished delete test\n");
4243 fail:
4244 /* FIXME: This will crash if we aborted before cli2 got
4245 * intialized, because these functions don't handle
4246 * uninitialized connections. */
4248 if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
4249 if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
4250 cli_setatr(cli1, fname, 0, 0);
4251 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4253 if (cli1 && !torture_close_connection(cli1)) {
4254 correct = False;
4256 if (cli2 && !torture_close_connection(cli2)) {
4257 correct = False;
4259 return correct;
4262 static bool run_deletetest_ln(int dummy)
4264 struct cli_state *cli;
4265 const char *fname = "\\delete1";
4266 const char *fname_ln = "\\delete1_ln";
4267 uint16_t fnum;
4268 uint16_t fnum1;
4269 NTSTATUS status;
4270 bool correct = true;
4271 time_t t;
4273 printf("starting deletetest-ln\n");
4275 if (!torture_open_connection(&cli, 0)) {
4276 return false;
4279 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4280 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4282 cli_sockopt(cli, sockops);
4284 /* Create the file. */
4285 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
4286 if (!NT_STATUS_IS_OK(status)) {
4287 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4288 return false;
4291 status = cli_close(cli, fnum);
4292 if (!NT_STATUS_IS_OK(status)) {
4293 printf("close1 failed (%s)\n", nt_errstr(status));
4294 return false;
4297 /* Now create a hardlink. */
4298 status = cli_nt_hardlink(cli, fname, fname_ln);
4299 if (!NT_STATUS_IS_OK(status)) {
4300 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4301 return false;
4304 /* Open the original file. */
4305 status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
4306 FILE_ATTRIBUTE_NORMAL,
4307 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4308 FILE_OPEN_IF, 0, 0, &fnum);
4309 if (!NT_STATUS_IS_OK(status)) {
4310 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
4311 return false;
4314 /* Unlink the hard link path. */
4315 status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
4316 FILE_ATTRIBUTE_NORMAL,
4317 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4318 FILE_OPEN_IF, 0, 0, &fnum1);
4319 if (!NT_STATUS_IS_OK(status)) {
4320 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
4321 return false;
4323 status = cli_nt_delete_on_close(cli, fnum1, true);
4324 if (!NT_STATUS_IS_OK(status)) {
4325 d_printf("(%s) failed to set delete_on_close %s: %s\n",
4326 __location__, fname_ln, nt_errstr(status));
4327 return false;
4330 status = cli_close(cli, fnum1);
4331 if (!NT_STATUS_IS_OK(status)) {
4332 printf("close %s failed (%s)\n",
4333 fname_ln, nt_errstr(status));
4334 return false;
4337 status = cli_close(cli, fnum);
4338 if (!NT_STATUS_IS_OK(status)) {
4339 printf("close %s failed (%s)\n",
4340 fname, nt_errstr(status));
4341 return false;
4344 /* Ensure the original file is still there. */
4345 status = cli_getatr(cli, fname, NULL, NULL, &t);
4346 if (!NT_STATUS_IS_OK(status)) {
4347 printf("%s getatr on file %s failed (%s)\n",
4348 __location__,
4349 fname,
4350 nt_errstr(status));
4351 correct = False;
4354 /* Ensure the link path is gone. */
4355 status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
4356 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4357 printf("%s, getatr for file %s returned wrong error code %s "
4358 "- should have been deleted\n",
4359 __location__,
4360 fname_ln, nt_errstr(status));
4361 correct = False;
4364 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4365 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4367 if (!torture_close_connection(cli)) {
4368 correct = false;
4371 printf("finished deletetest-ln\n");
4373 return correct;
4377 print out server properties
4379 static bool run_properties(int dummy)
4381 struct cli_state *cli;
4382 bool correct = True;
4384 printf("starting properties test\n");
4386 ZERO_STRUCT(cli);
4388 if (!torture_open_connection(&cli, 0)) {
4389 return False;
4392 cli_sockopt(cli, sockops);
4394 d_printf("Capabilities 0x%08x\n", cli->capabilities);
4396 if (!torture_close_connection(cli)) {
4397 correct = False;
4400 return correct;
4405 /* FIRST_DESIRED_ACCESS 0xf019f */
4406 #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
4407 FILE_READ_EA| /* 0xf */ \
4408 FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
4409 FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
4410 DELETE_ACCESS|READ_CONTROL_ACCESS|\
4411 WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
4412 /* SECOND_DESIRED_ACCESS 0xe0080 */
4413 #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
4414 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4415 WRITE_OWNER_ACCESS /* 0xe0000 */
4417 #if 0
4418 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
4419 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4420 FILE_READ_DATA|\
4421 WRITE_OWNER_ACCESS /* */
4422 #endif
4425 Test ntcreate calls made by xcopy
4427 static bool run_xcopy(int dummy)
4429 static struct cli_state *cli1;
4430 const char *fname = "\\test.txt";
4431 bool correct = True;
4432 uint16_t fnum1, fnum2;
4433 NTSTATUS status;
4435 printf("starting xcopy test\n");
4437 if (!torture_open_connection(&cli1, 0)) {
4438 return False;
4441 status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
4442 FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
4443 FILE_OVERWRITE_IF, 0x4044, 0, &fnum1);
4444 if (!NT_STATUS_IS_OK(status)) {
4445 printf("First open failed - %s\n", nt_errstr(status));
4446 return False;
4449 status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
4450 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4451 FILE_OPEN, 0x200000, 0, &fnum2);
4452 if (!NT_STATUS_IS_OK(status)) {
4453 printf("second open failed - %s\n", nt_errstr(status));
4454 return False;
4457 if (!torture_close_connection(cli1)) {
4458 correct = False;
4461 return correct;
4465 Test rename on files open with share delete and no share delete.
4467 static bool run_rename(int dummy)
4469 static struct cli_state *cli1;
4470 const char *fname = "\\test.txt";
4471 const char *fname1 = "\\test1.txt";
4472 bool correct = True;
4473 uint16_t fnum1;
4474 uint16_t attr;
4475 NTSTATUS status;
4477 printf("starting rename test\n");
4479 if (!torture_open_connection(&cli1, 0)) {
4480 return False;
4483 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4484 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4486 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4487 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
4488 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4489 if (!NT_STATUS_IS_OK(status)) {
4490 printf("First open failed - %s\n", nt_errstr(status));
4491 return False;
4494 status = cli_rename(cli1, fname, fname1);
4495 if (!NT_STATUS_IS_OK(status)) {
4496 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
4497 } else {
4498 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
4499 correct = False;
4502 status = cli_close(cli1, fnum1);
4503 if (!NT_STATUS_IS_OK(status)) {
4504 printf("close - 1 failed (%s)\n", nt_errstr(status));
4505 return False;
4508 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4509 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4510 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4511 #if 0
4512 FILE_SHARE_DELETE|FILE_SHARE_NONE,
4513 #else
4514 FILE_SHARE_DELETE|FILE_SHARE_READ,
4515 #endif
4516 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4517 if (!NT_STATUS_IS_OK(status)) {
4518 printf("Second open failed - %s\n", nt_errstr(status));
4519 return False;
4522 status = cli_rename(cli1, fname, fname1);
4523 if (!NT_STATUS_IS_OK(status)) {
4524 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
4525 correct = False;
4526 } else {
4527 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
4530 status = cli_close(cli1, fnum1);
4531 if (!NT_STATUS_IS_OK(status)) {
4532 printf("close - 2 failed (%s)\n", nt_errstr(status));
4533 return False;
4536 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4537 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4539 status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
4540 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4541 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4542 if (!NT_STATUS_IS_OK(status)) {
4543 printf("Third open failed - %s\n", nt_errstr(status));
4544 return False;
4548 #if 0
4550 uint16_t fnum2;
4552 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
4553 FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4554 printf("Fourth open failed - %s\n", cli_errstr(cli1));
4555 return False;
4557 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum2, true))) {
4558 printf("[8] setting delete_on_close on file failed !\n");
4559 return False;
4562 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
4563 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
4564 return False;
4567 #endif
4569 status = cli_rename(cli1, fname, fname1);
4570 if (!NT_STATUS_IS_OK(status)) {
4571 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
4572 correct = False;
4573 } else {
4574 printf("Third rename succeeded (SHARE_NONE)\n");
4577 status = cli_close(cli1, fnum1);
4578 if (!NT_STATUS_IS_OK(status)) {
4579 printf("close - 3 failed (%s)\n", nt_errstr(status));
4580 return False;
4583 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4584 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4586 /*----*/
4588 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4589 FILE_ATTRIBUTE_NORMAL,
4590 FILE_SHARE_READ | FILE_SHARE_WRITE,
4591 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4592 if (!NT_STATUS_IS_OK(status)) {
4593 printf("Fourth open failed - %s\n", nt_errstr(status));
4594 return False;
4597 status = cli_rename(cli1, fname, fname1);
4598 if (!NT_STATUS_IS_OK(status)) {
4599 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
4600 } else {
4601 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
4602 correct = False;
4605 status = cli_close(cli1, fnum1);
4606 if (!NT_STATUS_IS_OK(status)) {
4607 printf("close - 4 failed (%s)\n", nt_errstr(status));
4608 return False;
4611 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4612 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4614 /*--*/
4616 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4617 FILE_ATTRIBUTE_NORMAL,
4618 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4619 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4620 if (!NT_STATUS_IS_OK(status)) {
4621 printf("Fifth open failed - %s\n", nt_errstr(status));
4622 return False;
4625 status = cli_rename(cli1, fname, fname1);
4626 if (!NT_STATUS_IS_OK(status)) {
4627 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
4628 correct = False;
4629 } else {
4630 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
4634 * Now check if the first name still exists ...
4637 /* if (!NT_STATUS_OP(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4638 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4639 printf("Opening original file after rename of open file fails: %s\n",
4640 cli_errstr(cli1));
4642 else {
4643 printf("Opening original file after rename of open file works ...\n");
4644 (void)cli_close(cli1, fnum2);
4645 } */
4647 /*--*/
4648 status = cli_close(cli1, fnum1);
4649 if (!NT_STATUS_IS_OK(status)) {
4650 printf("close - 5 failed (%s)\n", nt_errstr(status));
4651 return False;
4654 /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
4655 status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
4656 if (!NT_STATUS_IS_OK(status)) {
4657 printf("getatr on file %s failed - %s ! \n",
4658 fname1, nt_errstr(status));
4659 correct = False;
4660 } else {
4661 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
4662 printf("Renamed file %s has wrong attr 0x%x "
4663 "(should be 0x%x)\n",
4664 fname1,
4665 attr,
4666 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
4667 correct = False;
4668 } else {
4669 printf("Renamed file %s has archive bit set\n", fname1);
4673 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4674 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4676 if (!torture_close_connection(cli1)) {
4677 correct = False;
4680 return correct;
4683 static bool run_pipe_number(int dummy)
4685 struct cli_state *cli1;
4686 const char *pipe_name = "\\SPOOLSS";
4687 uint16_t fnum;
4688 int num_pipes = 0;
4689 NTSTATUS status;
4691 printf("starting pipenumber test\n");
4692 if (!torture_open_connection(&cli1, 0)) {
4693 return False;
4696 cli_sockopt(cli1, sockops);
4697 while(1) {
4698 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
4699 FILE_ATTRIBUTE_NORMAL,
4700 FILE_SHARE_READ|FILE_SHARE_WRITE,
4701 FILE_OPEN_IF, 0, 0, &fnum);
4702 if (!NT_STATUS_IS_OK(status)) {
4703 printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
4704 break;
4706 num_pipes++;
4707 printf("\r%6d", num_pipes);
4710 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
4711 torture_close_connection(cli1);
4712 return True;
4716 Test open mode returns on read-only files.
4718 static bool run_opentest(int dummy)
4720 static struct cli_state *cli1;
4721 static struct cli_state *cli2;
4722 const char *fname = "\\readonly.file";
4723 uint16_t fnum1, fnum2;
4724 char buf[20];
4725 SMB_OFF_T fsize;
4726 bool correct = True;
4727 char *tmp_path;
4728 NTSTATUS status;
4730 printf("starting open test\n");
4732 if (!torture_open_connection(&cli1, 0)) {
4733 return False;
4736 cli_setatr(cli1, fname, 0, 0);
4737 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4739 cli_sockopt(cli1, sockops);
4741 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4742 if (!NT_STATUS_IS_OK(status)) {
4743 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4744 return False;
4747 status = cli_close(cli1, fnum1);
4748 if (!NT_STATUS_IS_OK(status)) {
4749 printf("close2 failed (%s)\n", nt_errstr(status));
4750 return False;
4753 status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
4754 if (!NT_STATUS_IS_OK(status)) {
4755 printf("cli_setatr failed (%s)\n", nt_errstr(status));
4756 return False;
4759 status = cli_open(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4760 if (!NT_STATUS_IS_OK(status)) {
4761 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4762 return False;
4765 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
4766 cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4768 if (check_error(__LINE__, cli1, ERRDOS, ERRnoaccess,
4769 NT_STATUS_ACCESS_DENIED)) {
4770 printf("correct error code ERRDOS/ERRnoaccess returned\n");
4773 printf("finished open test 1\n");
4775 cli_close(cli1, fnum1);
4777 /* Now try not readonly and ensure ERRbadshare is returned. */
4779 cli_setatr(cli1, fname, 0, 0);
4781 status = cli_open(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4782 if (!NT_STATUS_IS_OK(status)) {
4783 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4784 return False;
4787 /* This will fail - but the error should be ERRshare. */
4788 cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4790 if (check_error(__LINE__, cli1, ERRDOS, ERRbadshare,
4791 NT_STATUS_SHARING_VIOLATION)) {
4792 printf("correct error code ERRDOS/ERRbadshare returned\n");
4795 status = cli_close(cli1, fnum1);
4796 if (!NT_STATUS_IS_OK(status)) {
4797 printf("close2 failed (%s)\n", nt_errstr(status));
4798 return False;
4801 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4803 printf("finished open test 2\n");
4805 /* Test truncate open disposition on file opened for read. */
4806 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4807 if (!NT_STATUS_IS_OK(status)) {
4808 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
4809 return False;
4812 /* write 20 bytes. */
4814 memset(buf, '\0', 20);
4816 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
4817 if (!NT_STATUS_IS_OK(status)) {
4818 printf("write failed (%s)\n", nt_errstr(status));
4819 correct = False;
4822 status = cli_close(cli1, fnum1);
4823 if (!NT_STATUS_IS_OK(status)) {
4824 printf("(3) close1 failed (%s)\n", nt_errstr(status));
4825 return False;
4828 /* Ensure size == 20. */
4829 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
4830 if (!NT_STATUS_IS_OK(status)) {
4831 printf("(3) getatr failed (%s)\n", nt_errstr(status));
4832 return False;
4835 if (fsize != 20) {
4836 printf("(3) file size != 20\n");
4837 return False;
4840 /* Now test if we can truncate a file opened for readonly. */
4841 status = cli_open(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
4842 if (!NT_STATUS_IS_OK(status)) {
4843 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
4844 return False;
4847 status = cli_close(cli1, fnum1);
4848 if (!NT_STATUS_IS_OK(status)) {
4849 printf("close2 failed (%s)\n", nt_errstr(status));
4850 return False;
4853 /* Ensure size == 0. */
4854 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
4855 if (!NT_STATUS_IS_OK(status)) {
4856 printf("(3) getatr failed (%s)\n", nt_errstr(status));
4857 return False;
4860 if (fsize != 0) {
4861 printf("(3) file size != 0\n");
4862 return False;
4864 printf("finished open test 3\n");
4866 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4868 printf("Do ctemp tests\n");
4869 status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
4870 if (!NT_STATUS_IS_OK(status)) {
4871 printf("ctemp failed (%s)\n", nt_errstr(status));
4872 return False;
4875 printf("ctemp gave path %s\n", tmp_path);
4876 status = cli_close(cli1, fnum1);
4877 if (!NT_STATUS_IS_OK(status)) {
4878 printf("close of temp failed (%s)\n", nt_errstr(status));
4881 status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4882 if (!NT_STATUS_IS_OK(status)) {
4883 printf("unlink of temp failed (%s)\n", nt_errstr(status));
4886 /* Test the non-io opens... */
4888 if (!torture_open_connection(&cli2, 1)) {
4889 return False;
4892 cli_setatr(cli2, fname, 0, 0);
4893 cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4895 cli_sockopt(cli2, sockops);
4897 printf("TEST #1 testing 2 non-io opens (no delete)\n");
4898 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
4899 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4900 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4901 if (!NT_STATUS_IS_OK(status)) {
4902 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4903 return False;
4906 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
4907 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4908 FILE_OPEN_IF, 0, 0, &fnum2);
4909 if (!NT_STATUS_IS_OK(status)) {
4910 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4911 return False;
4914 status = cli_close(cli1, fnum1);
4915 if (!NT_STATUS_IS_OK(status)) {
4916 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
4917 return False;
4920 status = cli_close(cli2, fnum2);
4921 if (!NT_STATUS_IS_OK(status)) {
4922 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
4923 return False;
4926 printf("non-io open test #1 passed.\n");
4928 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4930 printf("TEST #2 testing 2 non-io opens (first with delete)\n");
4932 status = cli_ntcreate(cli1, fname, 0,
4933 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
4934 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4935 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4936 if (!NT_STATUS_IS_OK(status)) {
4937 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4938 return False;
4941 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
4942 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4943 FILE_OPEN_IF, 0, 0, &fnum2);
4944 if (!NT_STATUS_IS_OK(status)) {
4945 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4946 return False;
4949 status = cli_close(cli1, fnum1);
4950 if (!NT_STATUS_IS_OK(status)) {
4951 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
4952 return False;
4955 status = cli_close(cli2, fnum2);
4956 if (!NT_STATUS_IS_OK(status)) {
4957 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
4958 return False;
4961 printf("non-io open test #2 passed.\n");
4963 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4965 printf("TEST #3 testing 2 non-io opens (second with delete)\n");
4967 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
4968 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4969 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4970 if (!NT_STATUS_IS_OK(status)) {
4971 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4972 return False;
4975 status = cli_ntcreate(cli2, fname, 0,
4976 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
4977 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4978 FILE_OPEN_IF, 0, 0, &fnum2);
4979 if (!NT_STATUS_IS_OK(status)) {
4980 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4981 return False;
4984 status = cli_close(cli1, fnum1);
4985 if (!NT_STATUS_IS_OK(status)) {
4986 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
4987 return False;
4990 status = cli_close(cli2, fnum2);
4991 if (!NT_STATUS_IS_OK(status)) {
4992 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
4993 return False;
4996 printf("non-io open test #3 passed.\n");
4998 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5000 printf("TEST #4 testing 2 non-io opens (both with delete)\n");
5002 status = cli_ntcreate(cli1, fname, 0,
5003 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5004 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5005 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5006 if (!NT_STATUS_IS_OK(status)) {
5007 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5008 return False;
5011 status = cli_ntcreate(cli2, fname, 0,
5012 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5013 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5014 FILE_OPEN_IF, 0, 0, &fnum2);
5015 if (NT_STATUS_IS_OK(status)) {
5016 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5017 return False;
5020 printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5022 status = cli_close(cli1, fnum1);
5023 if (!NT_STATUS_IS_OK(status)) {
5024 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5025 return False;
5028 printf("non-io open test #4 passed.\n");
5030 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5032 printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
5034 status = cli_ntcreate(cli1, fname, 0,
5035 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5036 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5037 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5038 if (!NT_STATUS_IS_OK(status)) {
5039 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5040 return False;
5043 status = cli_ntcreate(cli2, fname, 0,
5044 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5045 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5046 FILE_OPEN_IF, 0, 0, &fnum2);
5047 if (!NT_STATUS_IS_OK(status)) {
5048 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5049 return False;
5052 status = cli_close(cli1, fnum1);
5053 if (!NT_STATUS_IS_OK(status)) {
5054 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5055 return False;
5058 status = cli_close(cli2, fnum2);
5059 if (!NT_STATUS_IS_OK(status)) {
5060 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5061 return False;
5064 printf("non-io open test #5 passed.\n");
5066 printf("TEST #6 testing 1 non-io open, one io open\n");
5068 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5070 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5071 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5072 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5073 if (!NT_STATUS_IS_OK(status)) {
5074 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5075 return False;
5078 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5079 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
5080 FILE_OPEN_IF, 0, 0, &fnum2);
5081 if (!NT_STATUS_IS_OK(status)) {
5082 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5083 return False;
5086 status = cli_close(cli1, fnum1);
5087 if (!NT_STATUS_IS_OK(status)) {
5088 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5089 return False;
5092 status = cli_close(cli2, fnum2);
5093 if (!NT_STATUS_IS_OK(status)) {
5094 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5095 return False;
5098 printf("non-io open test #6 passed.\n");
5100 printf("TEST #7 testing 1 non-io open, one io open with delete\n");
5102 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5104 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5105 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5106 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5107 if (!NT_STATUS_IS_OK(status)) {
5108 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5109 return False;
5112 status = cli_ntcreate(cli2, fname, 0,
5113 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5114 FILE_ATTRIBUTE_NORMAL,
5115 FILE_SHARE_READ|FILE_SHARE_DELETE,
5116 FILE_OPEN_IF, 0, 0, &fnum2);
5117 if (NT_STATUS_IS_OK(status)) {
5118 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5119 return False;
5122 printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5124 status = cli_close(cli1, fnum1);
5125 if (!NT_STATUS_IS_OK(status)) {
5126 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5127 return False;
5130 printf("non-io open test #7 passed.\n");
5132 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5134 printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
5135 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
5136 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5137 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5138 if (!NT_STATUS_IS_OK(status)) {
5139 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
5140 correct = false;
5141 goto out;
5144 /* Write to ensure we have to update the file time. */
5145 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5146 NULL);
5147 if (!NT_STATUS_IS_OK(status)) {
5148 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
5149 correct = false;
5150 goto out;
5153 status = cli_close(cli1, fnum1);
5154 if (!NT_STATUS_IS_OK(status)) {
5155 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
5156 correct = false;
5159 out:
5161 if (!torture_close_connection(cli1)) {
5162 correct = False;
5164 if (!torture_close_connection(cli2)) {
5165 correct = False;
5168 return correct;
5171 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
5173 uint16 major, minor;
5174 uint32 caplow, caphigh;
5175 NTSTATUS status;
5177 if (!SERVER_HAS_UNIX_CIFS(cli)) {
5178 printf("Server doesn't support UNIX CIFS extensions.\n");
5179 return NT_STATUS_NOT_SUPPORTED;
5182 status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
5183 &caphigh);
5184 if (!NT_STATUS_IS_OK(status)) {
5185 printf("Server didn't return UNIX CIFS extensions: %s\n",
5186 nt_errstr(status));
5187 return status;
5190 status = cli_set_unix_extensions_capabilities(cli, major, minor,
5191 caplow, caphigh);
5192 if (!NT_STATUS_IS_OK(status)) {
5193 printf("Server doesn't support setting UNIX CIFS extensions: "
5194 "%s.\n", nt_errstr(status));
5195 return status;
5198 return NT_STATUS_OK;
5202 Test POSIX open /mkdir calls.
5204 static bool run_simple_posix_open_test(int dummy)
5206 static struct cli_state *cli1;
5207 const char *fname = "posix:file";
5208 const char *hname = "posix:hlink";
5209 const char *sname = "posix:symlink";
5210 const char *dname = "posix:dir";
5211 char buf[10];
5212 char namebuf[11];
5213 uint16_t fnum1 = (uint16_t)-1;
5214 SMB_STRUCT_STAT sbuf;
5215 bool correct = false;
5216 NTSTATUS status;
5218 printf("Starting simple POSIX open test\n");
5220 if (!torture_open_connection(&cli1, 0)) {
5221 return false;
5224 cli_sockopt(cli1, sockops);
5226 status = torture_setup_unix_extensions(cli1);
5227 if (!NT_STATUS_IS_OK(status)) {
5228 return false;
5231 cli_setatr(cli1, fname, 0, 0);
5232 cli_posix_unlink(cli1, fname);
5233 cli_setatr(cli1, dname, 0, 0);
5234 cli_posix_rmdir(cli1, dname);
5235 cli_setatr(cli1, hname, 0, 0);
5236 cli_posix_unlink(cli1, hname);
5237 cli_setatr(cli1, sname, 0, 0);
5238 cli_posix_unlink(cli1, sname);
5240 /* Create a directory. */
5241 status = cli_posix_mkdir(cli1, dname, 0777);
5242 if (!NT_STATUS_IS_OK(status)) {
5243 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
5244 goto out;
5247 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5248 0600, &fnum1);
5249 if (!NT_STATUS_IS_OK(status)) {
5250 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5251 goto out;
5254 /* Test ftruncate - set file size. */
5255 status = cli_ftruncate(cli1, fnum1, 1000);
5256 if (!NT_STATUS_IS_OK(status)) {
5257 printf("ftruncate failed (%s)\n", nt_errstr(status));
5258 goto out;
5261 /* Ensure st_size == 1000 */
5262 status = cli_posix_stat(cli1, fname, &sbuf);
5263 if (!NT_STATUS_IS_OK(status)) {
5264 printf("stat failed (%s)\n", nt_errstr(status));
5265 goto out;
5268 if (sbuf.st_ex_size != 1000) {
5269 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5270 goto out;
5273 /* Test ftruncate - set file size back to zero. */
5274 status = cli_ftruncate(cli1, fnum1, 0);
5275 if (!NT_STATUS_IS_OK(status)) {
5276 printf("ftruncate failed (%s)\n", nt_errstr(status));
5277 goto out;
5280 status = cli_close(cli1, fnum1);
5281 if (!NT_STATUS_IS_OK(status)) {
5282 printf("close failed (%s)\n", nt_errstr(status));
5283 goto out;
5286 /* Now open the file again for read only. */
5287 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5288 if (!NT_STATUS_IS_OK(status)) {
5289 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
5290 goto out;
5293 /* Now unlink while open. */
5294 status = cli_posix_unlink(cli1, fname);
5295 if (!NT_STATUS_IS_OK(status)) {
5296 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5297 goto out;
5300 status = cli_close(cli1, fnum1);
5301 if (!NT_STATUS_IS_OK(status)) {
5302 printf("close(2) failed (%s)\n", nt_errstr(status));
5303 goto out;
5306 /* Ensure the file has gone. */
5307 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5308 if (NT_STATUS_IS_OK(status)) {
5309 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
5310 goto out;
5313 /* Create again to test open with O_TRUNC. */
5314 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
5315 if (!NT_STATUS_IS_OK(status)) {
5316 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5317 goto out;
5320 /* Test ftruncate - set file size. */
5321 status = cli_ftruncate(cli1, fnum1, 1000);
5322 if (!NT_STATUS_IS_OK(status)) {
5323 printf("ftruncate failed (%s)\n", nt_errstr(status));
5324 goto out;
5327 /* Ensure st_size == 1000 */
5328 status = cli_posix_stat(cli1, fname, &sbuf);
5329 if (!NT_STATUS_IS_OK(status)) {
5330 printf("stat failed (%s)\n", nt_errstr(status));
5331 goto out;
5334 if (sbuf.st_ex_size != 1000) {
5335 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5336 goto out;
5339 status = cli_close(cli1, fnum1);
5340 if (!NT_STATUS_IS_OK(status)) {
5341 printf("close(2) failed (%s)\n", nt_errstr(status));
5342 goto out;
5345 /* Re-open with O_TRUNC. */
5346 status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
5347 if (!NT_STATUS_IS_OK(status)) {
5348 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5349 goto out;
5352 /* Ensure st_size == 0 */
5353 status = cli_posix_stat(cli1, fname, &sbuf);
5354 if (!NT_STATUS_IS_OK(status)) {
5355 printf("stat failed (%s)\n", nt_errstr(status));
5356 goto out;
5359 if (sbuf.st_ex_size != 0) {
5360 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
5361 goto out;
5364 status = cli_close(cli1, fnum1);
5365 if (!NT_STATUS_IS_OK(status)) {
5366 printf("close failed (%s)\n", nt_errstr(status));
5367 goto out;
5370 status = cli_posix_unlink(cli1, fname);
5371 if (!NT_STATUS_IS_OK(status)) {
5372 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5373 goto out;
5376 status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
5377 if (!NT_STATUS_IS_OK(status)) {
5378 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
5379 dname, nt_errstr(status));
5380 goto out;
5383 cli_close(cli1, fnum1);
5385 /* What happens when we try and POSIX open a directory for write ? */
5386 status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
5387 if (NT_STATUS_IS_OK(status)) {
5388 printf("POSIX open of directory %s succeeded, should have failed.\n", fname);
5389 goto out;
5390 } else {
5391 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
5392 NT_STATUS_FILE_IS_A_DIRECTORY)) {
5393 goto out;
5397 /* Create the file. */
5398 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5399 0600, &fnum1);
5400 if (!NT_STATUS_IS_OK(status)) {
5401 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5402 goto out;
5405 /* Write some data into it. */
5406 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5407 NULL);
5408 if (!NT_STATUS_IS_OK(status)) {
5409 printf("cli_write failed: %s\n", nt_errstr(status));
5410 goto out;
5413 cli_close(cli1, fnum1);
5415 /* Now create a hardlink. */
5416 status = cli_posix_hardlink(cli1, fname, hname);
5417 if (!NT_STATUS_IS_OK(status)) {
5418 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
5419 goto out;
5422 /* Now create a symlink. */
5423 status = cli_posix_symlink(cli1, fname, sname);
5424 if (!NT_STATUS_IS_OK(status)) {
5425 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
5426 goto out;
5429 /* Open the hardlink for read. */
5430 status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
5431 if (!NT_STATUS_IS_OK(status)) {
5432 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
5433 goto out;
5436 if (cli_read(cli1, fnum1, buf, 0, 10) != 10) {
5437 printf("POSIX read of %s failed (%s)\n", hname, cli_errstr(cli1));
5438 goto out;
5441 if (memcmp(buf, "TEST DATA\n", 10)) {
5442 printf("invalid data read from hardlink\n");
5443 goto out;
5446 /* Do a POSIX lock/unlock. */
5447 status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
5448 if (!NT_STATUS_IS_OK(status)) {
5449 printf("POSIX lock failed %s\n", nt_errstr(status));
5450 goto out;
5453 /* Punch a hole in the locked area. */
5454 status = cli_posix_unlock(cli1, fnum1, 10, 80);
5455 if (!NT_STATUS_IS_OK(status)) {
5456 printf("POSIX unlock failed %s\n", nt_errstr(status));
5457 goto out;
5460 cli_close(cli1, fnum1);
5462 /* Open the symlink for read - this should fail. A POSIX
5463 client should not be doing opens on a symlink. */
5464 status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
5465 if (NT_STATUS_IS_OK(status)) {
5466 printf("POSIX open of %s succeeded (should have failed)\n", sname);
5467 goto out;
5468 } else {
5469 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
5470 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
5471 printf("POSIX open of %s should have failed "
5472 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
5473 "failed with %s instead.\n",
5474 sname, nt_errstr(status));
5475 goto out;
5479 status = cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf));
5480 if (!NT_STATUS_IS_OK(status)) {
5481 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
5482 goto out;
5485 if (strcmp(namebuf, fname) != 0) {
5486 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
5487 sname, fname, namebuf);
5488 goto out;
5491 status = cli_posix_rmdir(cli1, dname);
5492 if (!NT_STATUS_IS_OK(status)) {
5493 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
5494 goto out;
5497 printf("Simple POSIX open test passed\n");
5498 correct = true;
5500 out:
5502 if (fnum1 != (uint16_t)-1) {
5503 cli_close(cli1, fnum1);
5504 fnum1 = (uint16_t)-1;
5507 cli_setatr(cli1, sname, 0, 0);
5508 cli_posix_unlink(cli1, sname);
5509 cli_setatr(cli1, hname, 0, 0);
5510 cli_posix_unlink(cli1, hname);
5511 cli_setatr(cli1, fname, 0, 0);
5512 cli_posix_unlink(cli1, fname);
5513 cli_setatr(cli1, dname, 0, 0);
5514 cli_posix_rmdir(cli1, dname);
5516 if (!torture_close_connection(cli1)) {
5517 correct = false;
5520 return correct;
5524 static uint32 open_attrs_table[] = {
5525 FILE_ATTRIBUTE_NORMAL,
5526 FILE_ATTRIBUTE_ARCHIVE,
5527 FILE_ATTRIBUTE_READONLY,
5528 FILE_ATTRIBUTE_HIDDEN,
5529 FILE_ATTRIBUTE_SYSTEM,
5531 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
5532 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
5533 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
5534 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5535 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5536 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5538 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5539 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5540 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5541 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
5544 struct trunc_open_results {
5545 unsigned int num;
5546 uint32 init_attr;
5547 uint32 trunc_attr;
5548 uint32 result_attr;
5551 static struct trunc_open_results attr_results[] = {
5552 { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5553 { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5554 { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5555 { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5556 { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5557 { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5558 { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5559 { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5560 { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5561 { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5562 { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5563 { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
5564 { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5565 { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5566 { 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 },
5567 { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5568 { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5569 { 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 },
5570 { 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 },
5571 { 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 },
5572 { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5573 { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5574 { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5575 { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5576 { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5577 { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
5580 static bool run_openattrtest(int dummy)
5582 static struct cli_state *cli1;
5583 const char *fname = "\\openattr.file";
5584 uint16_t fnum1;
5585 bool correct = True;
5586 uint16 attr;
5587 unsigned int i, j, k, l;
5588 NTSTATUS status;
5590 printf("starting open attr test\n");
5592 if (!torture_open_connection(&cli1, 0)) {
5593 return False;
5596 cli_sockopt(cli1, sockops);
5598 for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32); i++) {
5599 cli_setatr(cli1, fname, 0, 0);
5600 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5602 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
5603 open_attrs_table[i], FILE_SHARE_NONE,
5604 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5605 if (!NT_STATUS_IS_OK(status)) {
5606 printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5607 return False;
5610 status = cli_close(cli1, fnum1);
5611 if (!NT_STATUS_IS_OK(status)) {
5612 printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5613 return False;
5616 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32); j++) {
5617 status = cli_ntcreate(cli1, fname, 0,
5618 FILE_READ_DATA|FILE_WRITE_DATA,
5619 open_attrs_table[j],
5620 FILE_SHARE_NONE, FILE_OVERWRITE,
5621 0, 0, &fnum1);
5622 if (!NT_STATUS_IS_OK(status)) {
5623 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5624 if (attr_results[l].num == k) {
5625 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
5626 k, open_attrs_table[i],
5627 open_attrs_table[j],
5628 fname, NT_STATUS_V(status), nt_errstr(status));
5629 correct = False;
5633 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5634 printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
5635 k, open_attrs_table[i], open_attrs_table[j],
5636 nt_errstr(status));
5637 correct = False;
5639 #if 0
5640 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
5641 #endif
5642 k++;
5643 continue;
5646 status = cli_close(cli1, fnum1);
5647 if (!NT_STATUS_IS_OK(status)) {
5648 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
5649 return False;
5652 status = cli_getatr(cli1, fname, &attr, NULL, NULL);
5653 if (!NT_STATUS_IS_OK(status)) {
5654 printf("getatr(2) failed (%s)\n", nt_errstr(status));
5655 return False;
5658 #if 0
5659 printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
5660 k, open_attrs_table[i], open_attrs_table[j], attr );
5661 #endif
5663 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5664 if (attr_results[l].num == k) {
5665 if (attr != attr_results[l].result_attr ||
5666 open_attrs_table[i] != attr_results[l].init_attr ||
5667 open_attrs_table[j] != attr_results[l].trunc_attr) {
5668 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
5669 open_attrs_table[i],
5670 open_attrs_table[j],
5671 (unsigned int)attr,
5672 attr_results[l].result_attr);
5673 correct = False;
5675 break;
5678 k++;
5682 cli_setatr(cli1, fname, 0, 0);
5683 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5685 printf("open attr test %s.\n", correct ? "passed" : "failed");
5687 if (!torture_close_connection(cli1)) {
5688 correct = False;
5690 return correct;
5693 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
5694 const char *name, void *state)
5696 int *matched = (int *)state;
5697 if (matched != NULL) {
5698 *matched += 1;
5700 return NT_STATUS_OK;
5704 test directory listing speed
5706 static bool run_dirtest(int dummy)
5708 int i;
5709 static struct cli_state *cli;
5710 uint16_t fnum;
5711 struct timeval core_start;
5712 bool correct = True;
5713 int matched;
5715 printf("starting directory test\n");
5717 if (!torture_open_connection(&cli, 0)) {
5718 return False;
5721 cli_sockopt(cli, sockops);
5723 srandom(0);
5724 for (i=0;i<torture_numops;i++) {
5725 fstring fname;
5726 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5727 if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
5728 fprintf(stderr,"Failed to open %s\n", fname);
5729 return False;
5731 cli_close(cli, fnum);
5734 core_start = timeval_current();
5736 matched = 0;
5737 cli_list(cli, "a*.*", 0, list_fn, &matched);
5738 printf("Matched %d\n", matched);
5740 matched = 0;
5741 cli_list(cli, "b*.*", 0, list_fn, &matched);
5742 printf("Matched %d\n", matched);
5744 matched = 0;
5745 cli_list(cli, "xyzabc", 0, list_fn, &matched);
5746 printf("Matched %d\n", matched);
5748 printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
5750 srandom(0);
5751 for (i=0;i<torture_numops;i++) {
5752 fstring fname;
5753 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5754 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5757 if (!torture_close_connection(cli)) {
5758 correct = False;
5761 printf("finished dirtest\n");
5763 return correct;
5766 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
5767 void *state)
5769 struct cli_state *pcli = (struct cli_state *)state;
5770 fstring fname;
5771 slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
5773 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
5774 return NT_STATUS_OK;
5776 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
5777 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
5778 printf("del_fn: failed to rmdir %s\n,", fname );
5779 } else {
5780 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
5781 printf("del_fn: failed to unlink %s\n,", fname );
5783 return NT_STATUS_OK;
5788 sees what IOCTLs are supported
5790 bool torture_ioctl_test(int dummy)
5792 static struct cli_state *cli;
5793 uint16_t device, function;
5794 uint16_t fnum;
5795 const char *fname = "\\ioctl.dat";
5796 DATA_BLOB blob;
5797 NTSTATUS status;
5799 if (!torture_open_connection(&cli, 0)) {
5800 return False;
5803 printf("starting ioctl test\n");
5805 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5807 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5808 if (!NT_STATUS_IS_OK(status)) {
5809 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5810 return False;
5813 status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
5814 printf("ioctl device info: %s\n", nt_errstr(status));
5816 status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
5817 printf("ioctl job info: %s\n", nt_errstr(status));
5819 for (device=0;device<0x100;device++) {
5820 printf("ioctl test with device = 0x%x\n", device);
5821 for (function=0;function<0x100;function++) {
5822 uint32 code = (device<<16) | function;
5824 status = cli_raw_ioctl(cli, fnum, code, &blob);
5826 if (NT_STATUS_IS_OK(status)) {
5827 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
5828 (int)blob.length);
5829 data_blob_free(&blob);
5834 if (!torture_close_connection(cli)) {
5835 return False;
5838 return True;
5843 tries varients of chkpath
5845 bool torture_chkpath_test(int dummy)
5847 static struct cli_state *cli;
5848 uint16_t fnum;
5849 bool ret;
5850 NTSTATUS status;
5852 if (!torture_open_connection(&cli, 0)) {
5853 return False;
5856 printf("starting chkpath test\n");
5858 /* cleanup from an old run */
5859 cli_rmdir(cli, "\\chkpath.dir\\dir2");
5860 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5861 cli_rmdir(cli, "\\chkpath.dir");
5863 status = cli_mkdir(cli, "\\chkpath.dir");
5864 if (!NT_STATUS_IS_OK(status)) {
5865 printf("mkdir1 failed : %s\n", nt_errstr(status));
5866 return False;
5869 status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
5870 if (!NT_STATUS_IS_OK(status)) {
5871 printf("mkdir2 failed : %s\n", nt_errstr(status));
5872 return False;
5875 status = cli_open(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
5876 DENY_NONE, &fnum);
5877 if (!NT_STATUS_IS_OK(status)) {
5878 printf("open1 failed (%s)\n", nt_errstr(status));
5879 return False;
5881 cli_close(cli, fnum);
5883 status = cli_chkpath(cli, "\\chkpath.dir");
5884 if (!NT_STATUS_IS_OK(status)) {
5885 printf("chkpath1 failed: %s\n", nt_errstr(status));
5886 ret = False;
5889 status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
5890 if (!NT_STATUS_IS_OK(status)) {
5891 printf("chkpath2 failed: %s\n", nt_errstr(status));
5892 ret = False;
5895 status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
5896 if (!NT_STATUS_IS_OK(status)) {
5897 ret = check_error(__LINE__, cli, ERRDOS, ERRbadpath,
5898 NT_STATUS_NOT_A_DIRECTORY);
5899 } else {
5900 printf("* chkpath on a file should fail\n");
5901 ret = False;
5904 if (!NT_STATUS_IS_OK(cli_chkpath(cli, "\\chkpath.dir\\bar.txt"))) {
5905 ret = check_error(__LINE__, cli, ERRDOS, ERRbadfile,
5906 NT_STATUS_OBJECT_NAME_NOT_FOUND);
5907 } else {
5908 printf("* chkpath on a non existant file should fail\n");
5909 ret = False;
5912 if (!NT_STATUS_IS_OK(cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt"))) {
5913 ret = check_error(__LINE__, cli, ERRDOS, ERRbadpath,
5914 NT_STATUS_OBJECT_PATH_NOT_FOUND);
5915 } else {
5916 printf("* chkpath on a non existent component should fail\n");
5917 ret = False;
5920 cli_rmdir(cli, "\\chkpath.dir\\dir2");
5921 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5922 cli_rmdir(cli, "\\chkpath.dir");
5924 if (!torture_close_connection(cli)) {
5925 return False;
5928 return ret;
5931 static bool run_eatest(int dummy)
5933 static struct cli_state *cli;
5934 const char *fname = "\\eatest.txt";
5935 bool correct = True;
5936 uint16_t fnum;
5937 int i;
5938 size_t num_eas;
5939 struct ea_struct *ea_list = NULL;
5940 TALLOC_CTX *mem_ctx = talloc_init("eatest");
5941 NTSTATUS status;
5943 printf("starting eatest\n");
5945 if (!torture_open_connection(&cli, 0)) {
5946 talloc_destroy(mem_ctx);
5947 return False;
5950 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5952 status = cli_ntcreate(cli, fname, 0,
5953 FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
5954 FILE_SHARE_NONE, FILE_OVERWRITE_IF,
5955 0x4044, 0, &fnum);
5956 if (!NT_STATUS_IS_OK(status)) {
5957 printf("open failed - %s\n", nt_errstr(status));
5958 talloc_destroy(mem_ctx);
5959 return False;
5962 for (i = 0; i < 10; i++) {
5963 fstring ea_name, ea_val;
5965 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
5966 memset(ea_val, (char)i+1, i+1);
5967 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
5968 if (!NT_STATUS_IS_OK(status)) {
5969 printf("ea_set of name %s failed - %s\n", ea_name,
5970 nt_errstr(status));
5971 talloc_destroy(mem_ctx);
5972 return False;
5976 cli_close(cli, fnum);
5977 for (i = 0; i < 10; i++) {
5978 fstring ea_name, ea_val;
5980 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
5981 memset(ea_val, (char)i+1, i+1);
5982 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
5983 if (!NT_STATUS_IS_OK(status)) {
5984 printf("ea_set of name %s failed - %s\n", ea_name,
5985 nt_errstr(status));
5986 talloc_destroy(mem_ctx);
5987 return False;
5991 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
5992 if (!NT_STATUS_IS_OK(status)) {
5993 printf("ea_get list failed - %s\n", nt_errstr(status));
5994 correct = False;
5997 printf("num_eas = %d\n", (int)num_eas);
5999 if (num_eas != 20) {
6000 printf("Should be 20 EA's stored... failing.\n");
6001 correct = False;
6004 for (i = 0; i < num_eas; i++) {
6005 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6006 dump_data(0, ea_list[i].value.data,
6007 ea_list[i].value.length);
6010 /* Setting EA's to zero length deletes them. Test this */
6011 printf("Now deleting all EA's - case indepenent....\n");
6013 #if 1
6014 cli_set_ea_path(cli, fname, "", "", 0);
6015 #else
6016 for (i = 0; i < 20; i++) {
6017 fstring ea_name;
6018 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
6019 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
6020 if (!NT_STATUS_IS_OK(status)) {
6021 printf("ea_set of name %s failed - %s\n", ea_name,
6022 nt_errstr(status));
6023 talloc_destroy(mem_ctx);
6024 return False;
6027 #endif
6029 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6030 if (!NT_STATUS_IS_OK(status)) {
6031 printf("ea_get list failed - %s\n", nt_errstr(status));
6032 correct = False;
6035 printf("num_eas = %d\n", (int)num_eas);
6036 for (i = 0; i < num_eas; i++) {
6037 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6038 dump_data(0, ea_list[i].value.data,
6039 ea_list[i].value.length);
6042 if (num_eas != 0) {
6043 printf("deleting EA's failed.\n");
6044 correct = False;
6047 /* Try and delete a non existant EA. */
6048 status = cli_set_ea_path(cli, fname, "foo", "", 0);
6049 if (!NT_STATUS_IS_OK(status)) {
6050 printf("deleting non-existant EA 'foo' should succeed. %s\n",
6051 nt_errstr(status));
6052 correct = False;
6055 talloc_destroy(mem_ctx);
6056 if (!torture_close_connection(cli)) {
6057 correct = False;
6060 return correct;
6063 static bool run_dirtest1(int dummy)
6065 int i;
6066 static struct cli_state *cli;
6067 uint16_t fnum;
6068 int num_seen;
6069 bool correct = True;
6071 printf("starting directory test\n");
6073 if (!torture_open_connection(&cli, 0)) {
6074 return False;
6077 cli_sockopt(cli, sockops);
6079 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6080 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6081 cli_rmdir(cli, "\\LISTDIR");
6082 cli_mkdir(cli, "\\LISTDIR");
6084 /* Create 1000 files and 1000 directories. */
6085 for (i=0;i<1000;i++) {
6086 fstring fname;
6087 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
6088 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6089 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum))) {
6090 fprintf(stderr,"Failed to open %s\n", fname);
6091 return False;
6093 cli_close(cli, fnum);
6095 for (i=0;i<1000;i++) {
6096 fstring fname;
6097 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
6098 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
6099 fprintf(stderr,"Failed to open %s\n", fname);
6100 return False;
6104 /* Now ensure that doing an old list sees both files and directories. */
6105 num_seen = 0;
6106 cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6107 printf("num_seen = %d\n", num_seen );
6108 /* We should see 100 files + 1000 directories + . and .. */
6109 if (num_seen != 2002)
6110 correct = False;
6112 /* Ensure if we have the "must have" bits we only see the
6113 * relevent entries.
6115 num_seen = 0;
6116 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6117 printf("num_seen = %d\n", num_seen );
6118 if (num_seen != 1002)
6119 correct = False;
6121 num_seen = 0;
6122 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6123 printf("num_seen = %d\n", num_seen );
6124 if (num_seen != 1000)
6125 correct = False;
6127 /* Delete everything. */
6128 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6129 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6130 cli_rmdir(cli, "\\LISTDIR");
6132 #if 0
6133 printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
6134 printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
6135 printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
6136 #endif
6138 if (!torture_close_connection(cli)) {
6139 correct = False;
6142 printf("finished dirtest1\n");
6144 return correct;
6147 static bool run_error_map_extract(int dummy) {
6149 static struct cli_state *c_dos;
6150 static struct cli_state *c_nt;
6151 NTSTATUS status;
6153 uint32 error;
6155 uint32 errnum;
6156 uint8 errclass;
6158 NTSTATUS nt_status;
6160 fstring user;
6162 /* NT-Error connection */
6164 if (!(c_nt = open_nbt_connection())) {
6165 return False;
6168 c_nt->use_spnego = False;
6170 status = cli_negprot(c_nt);
6172 if (!NT_STATUS_IS_OK(status)) {
6173 printf("%s rejected the NT-error negprot (%s)\n", host,
6174 nt_errstr(status));
6175 cli_shutdown(c_nt);
6176 return False;
6179 status = cli_session_setup(c_nt, "", "", 0, "", 0, workgroup);
6180 if (!NT_STATUS_IS_OK(status)) {
6181 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
6182 return False;
6185 /* DOS-Error connection */
6187 if (!(c_dos = open_nbt_connection())) {
6188 return False;
6191 c_dos->use_spnego = False;
6192 c_dos->force_dos_errors = True;
6194 status = cli_negprot(c_dos);
6195 if (!NT_STATUS_IS_OK(status)) {
6196 printf("%s rejected the DOS-error negprot (%s)\n", host,
6197 nt_errstr(status));
6198 cli_shutdown(c_dos);
6199 return False;
6202 status = cli_session_setup(c_dos, "", "", 0, "", 0, workgroup);
6203 if (!NT_STATUS_IS_OK(status)) {
6204 printf("%s rejected the DOS-error initial session setup (%s)\n",
6205 host, nt_errstr(status));
6206 return False;
6209 for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
6210 fstr_sprintf(user, "%X", error);
6212 status = cli_session_setup(c_nt, user,
6213 password, strlen(password),
6214 password, strlen(password),
6215 workgroup);
6216 if (NT_STATUS_IS_OK(status)) {
6217 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
6220 /* Case #1: 32-bit NT errors */
6221 if (cli_is_nt_error(c_nt)) {
6222 nt_status = cli_nt_error(c_nt);
6223 } else {
6224 printf("/** Dos error on NT connection! (%s) */\n",
6225 cli_errstr(c_nt));
6226 nt_status = NT_STATUS(0xc0000000);
6229 status = cli_session_setup(c_dos, user,
6230 password, strlen(password),
6231 password, strlen(password),
6232 workgroup);
6233 if (NT_STATUS_IS_OK(status)) {
6234 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
6237 /* Case #1: 32-bit NT errors */
6238 if (!cli_is_dos_error(c_dos)) {
6239 printf("/** NT error on DOS connection! (%s) */\n",
6240 cli_errstr(c_dos));
6241 errnum = errclass = 0;
6242 } else {
6243 cli_dos_error(c_dos, &errclass, &errnum);
6246 if (NT_STATUS_V(nt_status) != error) {
6247 printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
6248 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
6249 get_nt_error_c_code(talloc_tos(), nt_status));
6252 printf("\t{%s,\t%s,\t%s},\n",
6253 smb_dos_err_class(errclass),
6254 smb_dos_err_name(errclass, errnum),
6255 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
6257 return True;
6260 static bool run_sesssetup_bench(int dummy)
6262 static struct cli_state *c;
6263 const char *fname = "\\file.dat";
6264 uint16_t fnum;
6265 NTSTATUS status;
6266 int i;
6268 if (!torture_open_connection(&c, 0)) {
6269 return false;
6272 status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6273 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6274 FILE_DELETE_ON_CLOSE, 0, &fnum);
6275 if (!NT_STATUS_IS_OK(status)) {
6276 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
6277 return false;
6280 for (i=0; i<torture_numops; i++) {
6281 status = cli_session_setup(
6282 c, username,
6283 password, strlen(password),
6284 password, strlen(password),
6285 workgroup);
6286 if (!NT_STATUS_IS_OK(status)) {
6287 d_printf("(%s) cli_session_setup failed: %s\n",
6288 __location__, nt_errstr(status));
6289 return false;
6292 d_printf("\r%d ", (int)c->vuid);
6294 status = cli_ulogoff(c);
6295 if (!NT_STATUS_IS_OK(status)) {
6296 d_printf("(%s) cli_ulogoff failed: %s\n",
6297 __location__, nt_errstr(status));
6298 return false;
6300 c->vuid = 0;
6303 return true;
6306 static bool subst_test(const char *str, const char *user, const char *domain,
6307 uid_t uid, gid_t gid, const char *expected)
6309 char *subst;
6310 bool result = true;
6312 subst = talloc_sub_specified(talloc_tos(), str, user, domain, uid, gid);
6314 if (strcmp(subst, expected) != 0) {
6315 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
6316 "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
6317 expected);
6318 result = false;
6321 TALLOC_FREE(subst);
6322 return result;
6325 static void chain1_open_completion(struct tevent_req *req)
6327 uint16_t fnum;
6328 NTSTATUS status;
6329 status = cli_open_recv(req, &fnum);
6330 TALLOC_FREE(req);
6332 d_printf("cli_open_recv returned %s: %d\n",
6333 nt_errstr(status),
6334 NT_STATUS_IS_OK(status) ? fnum : -1);
6337 static void chain1_write_completion(struct tevent_req *req)
6339 size_t written;
6340 NTSTATUS status;
6341 status = cli_write_andx_recv(req, &written);
6342 TALLOC_FREE(req);
6344 d_printf("cli_write_andx_recv returned %s: %d\n",
6345 nt_errstr(status),
6346 NT_STATUS_IS_OK(status) ? (int)written : -1);
6349 static void chain1_close_completion(struct tevent_req *req)
6351 NTSTATUS status;
6352 bool *done = (bool *)tevent_req_callback_data_void(req);
6354 status = cli_close_recv(req);
6355 *done = true;
6357 TALLOC_FREE(req);
6359 d_printf("cli_close returned %s\n", nt_errstr(status));
6362 static bool run_chain1(int dummy)
6364 struct cli_state *cli1;
6365 struct event_context *evt = event_context_init(NULL);
6366 struct tevent_req *reqs[3], *smbreqs[3];
6367 bool done = false;
6368 const char *str = "foobar";
6369 NTSTATUS status;
6371 printf("starting chain1 test\n");
6372 if (!torture_open_connection(&cli1, 0)) {
6373 return False;
6376 cli_sockopt(cli1, sockops);
6378 reqs[0] = cli_open_create(talloc_tos(), evt, cli1, "\\test",
6379 O_CREAT|O_RDWR, 0, &smbreqs[0]);
6380 if (reqs[0] == NULL) return false;
6381 tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
6384 reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
6385 (const uint8_t *)str, 0, strlen(str)+1,
6386 smbreqs, 1, &smbreqs[1]);
6387 if (reqs[1] == NULL) return false;
6388 tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
6390 reqs[2] = cli_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
6391 if (reqs[2] == NULL) return false;
6392 tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
6394 status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
6395 if (!NT_STATUS_IS_OK(status)) {
6396 return false;
6399 while (!done) {
6400 event_loop_once(evt);
6403 torture_close_connection(cli1);
6404 return True;
6407 static void chain2_sesssetup_completion(struct tevent_req *req)
6409 NTSTATUS status;
6410 status = cli_session_setup_guest_recv(req);
6411 d_printf("sesssetup returned %s\n", nt_errstr(status));
6414 static void chain2_tcon_completion(struct tevent_req *req)
6416 bool *done = (bool *)tevent_req_callback_data_void(req);
6417 NTSTATUS status;
6418 status = cli_tcon_andx_recv(req);
6419 d_printf("tcon_and_x returned %s\n", nt_errstr(status));
6420 *done = true;
6423 static bool run_chain2(int dummy)
6425 struct cli_state *cli1;
6426 struct event_context *evt = event_context_init(NULL);
6427 struct tevent_req *reqs[2], *smbreqs[2];
6428 bool done = false;
6429 NTSTATUS status;
6431 printf("starting chain2 test\n");
6432 status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
6433 port_to_use, Undefined, 0);
6434 if (!NT_STATUS_IS_OK(status)) {
6435 return False;
6438 cli_sockopt(cli1, sockops);
6440 reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
6441 &smbreqs[0]);
6442 if (reqs[0] == NULL) return false;
6443 tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
6445 reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
6446 "?????", NULL, 0, &smbreqs[1]);
6447 if (reqs[1] == NULL) return false;
6448 tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
6450 status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
6451 if (!NT_STATUS_IS_OK(status)) {
6452 return false;
6455 while (!done) {
6456 event_loop_once(evt);
6459 torture_close_connection(cli1);
6460 return True;
6464 struct torture_createdel_state {
6465 struct tevent_context *ev;
6466 struct cli_state *cli;
6469 static void torture_createdel_created(struct tevent_req *subreq);
6470 static void torture_createdel_closed(struct tevent_req *subreq);
6472 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
6473 struct tevent_context *ev,
6474 struct cli_state *cli,
6475 const char *name)
6477 struct tevent_req *req, *subreq;
6478 struct torture_createdel_state *state;
6480 req = tevent_req_create(mem_ctx, &state,
6481 struct torture_createdel_state);
6482 if (req == NULL) {
6483 return NULL;
6485 state->ev = ev;
6486 state->cli = cli;
6488 subreq = cli_ntcreate_send(
6489 state, ev, cli, name, 0,
6490 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
6491 FILE_ATTRIBUTE_NORMAL,
6492 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6493 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
6495 if (tevent_req_nomem(subreq, req)) {
6496 return tevent_req_post(req, ev);
6498 tevent_req_set_callback(subreq, torture_createdel_created, req);
6499 return req;
6502 static void torture_createdel_created(struct tevent_req *subreq)
6504 struct tevent_req *req = tevent_req_callback_data(
6505 subreq, struct tevent_req);
6506 struct torture_createdel_state *state = tevent_req_data(
6507 req, struct torture_createdel_state);
6508 NTSTATUS status;
6509 uint16_t fnum;
6511 status = cli_ntcreate_recv(subreq, &fnum);
6512 TALLOC_FREE(subreq);
6513 if (!NT_STATUS_IS_OK(status)) {
6514 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
6515 nt_errstr(status)));
6516 tevent_req_nterror(req, status);
6517 return;
6520 subreq = cli_close_send(state, state->ev, state->cli, fnum);
6521 if (tevent_req_nomem(subreq, req)) {
6522 return;
6524 tevent_req_set_callback(subreq, torture_createdel_closed, req);
6527 static void torture_createdel_closed(struct tevent_req *subreq)
6529 struct tevent_req *req = tevent_req_callback_data(
6530 subreq, struct tevent_req);
6531 NTSTATUS status;
6533 status = cli_close_recv(subreq);
6534 if (!NT_STATUS_IS_OK(status)) {
6535 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
6536 tevent_req_nterror(req, status);
6537 return;
6539 tevent_req_done(req);
6542 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
6544 return tevent_req_simple_recv_ntstatus(req);
6547 struct torture_createdels_state {
6548 struct tevent_context *ev;
6549 struct cli_state *cli;
6550 const char *base_name;
6551 int sent;
6552 int received;
6553 int num_files;
6554 struct tevent_req **reqs;
6557 static void torture_createdels_done(struct tevent_req *subreq);
6559 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
6560 struct tevent_context *ev,
6561 struct cli_state *cli,
6562 const char *base_name,
6563 int num_parallel,
6564 int num_files)
6566 struct tevent_req *req;
6567 struct torture_createdels_state *state;
6568 int i;
6570 req = tevent_req_create(mem_ctx, &state,
6571 struct torture_createdels_state);
6572 if (req == NULL) {
6573 return NULL;
6575 state->ev = ev;
6576 state->cli = cli;
6577 state->base_name = talloc_strdup(state, base_name);
6578 if (tevent_req_nomem(state->base_name, req)) {
6579 return tevent_req_post(req, ev);
6581 state->num_files = MAX(num_parallel, num_files);
6582 state->sent = 0;
6583 state->received = 0;
6585 state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
6586 if (tevent_req_nomem(state->reqs, req)) {
6587 return tevent_req_post(req, ev);
6590 for (i=0; i<num_parallel; i++) {
6591 char *name;
6593 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6594 state->sent);
6595 if (tevent_req_nomem(name, req)) {
6596 return tevent_req_post(req, ev);
6598 state->reqs[i] = torture_createdel_send(
6599 state->reqs, state->ev, state->cli, name);
6600 if (tevent_req_nomem(state->reqs[i], req)) {
6601 return tevent_req_post(req, ev);
6603 name = talloc_move(state->reqs[i], &name);
6604 tevent_req_set_callback(state->reqs[i],
6605 torture_createdels_done, req);
6606 state->sent += 1;
6608 return req;
6611 static void torture_createdels_done(struct tevent_req *subreq)
6613 struct tevent_req *req = tevent_req_callback_data(
6614 subreq, struct tevent_req);
6615 struct torture_createdels_state *state = tevent_req_data(
6616 req, struct torture_createdels_state);
6617 size_t num_parallel = talloc_array_length(state->reqs);
6618 NTSTATUS status;
6619 char *name;
6620 int i;
6622 status = torture_createdel_recv(subreq);
6623 if (!NT_STATUS_IS_OK(status)){
6624 DEBUG(10, ("torture_createdel_recv returned %s\n",
6625 nt_errstr(status)));
6626 TALLOC_FREE(subreq);
6627 tevent_req_nterror(req, status);
6628 return;
6631 for (i=0; i<num_parallel; i++) {
6632 if (subreq == state->reqs[i]) {
6633 break;
6636 if (i == num_parallel) {
6637 DEBUG(10, ("received something we did not send\n"));
6638 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
6639 return;
6641 TALLOC_FREE(state->reqs[i]);
6643 if (state->sent >= state->num_files) {
6644 tevent_req_done(req);
6645 return;
6648 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6649 state->sent);
6650 if (tevent_req_nomem(name, req)) {
6651 return;
6653 state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
6654 state->cli, name);
6655 if (tevent_req_nomem(state->reqs[i], req)) {
6656 return;
6658 name = talloc_move(state->reqs[i], &name);
6659 tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
6660 state->sent += 1;
6663 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
6665 return tevent_req_simple_recv_ntstatus(req);
6668 struct swallow_notify_state {
6669 struct tevent_context *ev;
6670 struct cli_state *cli;
6671 uint16_t fnum;
6672 uint32_t completion_filter;
6673 bool recursive;
6674 bool (*fn)(uint32_t action, const char *name, void *priv);
6675 void *priv;
6678 static void swallow_notify_done(struct tevent_req *subreq);
6680 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
6681 struct tevent_context *ev,
6682 struct cli_state *cli,
6683 uint16_t fnum,
6684 uint32_t completion_filter,
6685 bool recursive,
6686 bool (*fn)(uint32_t action,
6687 const char *name,
6688 void *priv),
6689 void *priv)
6691 struct tevent_req *req, *subreq;
6692 struct swallow_notify_state *state;
6694 req = tevent_req_create(mem_ctx, &state,
6695 struct swallow_notify_state);
6696 if (req == NULL) {
6697 return NULL;
6699 state->ev = ev;
6700 state->cli = cli;
6701 state->fnum = fnum;
6702 state->completion_filter = completion_filter;
6703 state->recursive = recursive;
6704 state->fn = fn;
6705 state->priv = priv;
6707 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6708 0xffff, state->completion_filter,
6709 state->recursive);
6710 if (tevent_req_nomem(subreq, req)) {
6711 return tevent_req_post(req, ev);
6713 tevent_req_set_callback(subreq, swallow_notify_done, req);
6714 return req;
6717 static void swallow_notify_done(struct tevent_req *subreq)
6719 struct tevent_req *req = tevent_req_callback_data(
6720 subreq, struct tevent_req);
6721 struct swallow_notify_state *state = tevent_req_data(
6722 req, struct swallow_notify_state);
6723 NTSTATUS status;
6724 uint32_t i, num_changes;
6725 struct notify_change *changes;
6727 status = cli_notify_recv(subreq, state, &num_changes, &changes);
6728 TALLOC_FREE(subreq);
6729 if (!NT_STATUS_IS_OK(status)) {
6730 DEBUG(10, ("cli_notify_recv returned %s\n",
6731 nt_errstr(status)));
6732 tevent_req_nterror(req, status);
6733 return;
6736 for (i=0; i<num_changes; i++) {
6737 state->fn(changes[i].action, changes[i].name, state->priv);
6739 TALLOC_FREE(changes);
6741 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6742 0xffff, state->completion_filter,
6743 state->recursive);
6744 if (tevent_req_nomem(subreq, req)) {
6745 return;
6747 tevent_req_set_callback(subreq, swallow_notify_done, req);
6750 static bool print_notifies(uint32_t action, const char *name, void *priv)
6752 if (DEBUGLEVEL > 5) {
6753 d_printf("%d %s\n", (int)action, name);
6755 return true;
6758 static void notify_bench_done(struct tevent_req *req)
6760 int *num_finished = (int *)tevent_req_callback_data_void(req);
6761 *num_finished += 1;
6764 static bool run_notify_bench(int dummy)
6766 const char *dname = "\\notify-bench";
6767 struct tevent_context *ev;
6768 NTSTATUS status;
6769 uint16_t dnum;
6770 struct tevent_req *req1;
6771 struct tevent_req *req2 = NULL;
6772 int i, num_unc_names;
6773 int num_finished = 0;
6775 printf("starting notify-bench test\n");
6777 if (use_multishare_conn) {
6778 char **unc_list;
6779 unc_list = file_lines_load(multishare_conn_fname,
6780 &num_unc_names, 0, NULL);
6781 if (!unc_list || num_unc_names <= 0) {
6782 d_printf("Failed to load unc names list from '%s'\n",
6783 multishare_conn_fname);
6784 return false;
6786 TALLOC_FREE(unc_list);
6787 } else {
6788 num_unc_names = 1;
6791 ev = tevent_context_init(talloc_tos());
6792 if (ev == NULL) {
6793 d_printf("tevent_context_init failed\n");
6794 return false;
6797 for (i=0; i<num_unc_names; i++) {
6798 struct cli_state *cli;
6799 char *base_fname;
6801 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
6802 dname, i);
6803 if (base_fname == NULL) {
6804 return false;
6807 if (!torture_open_connection(&cli, i)) {
6808 return false;
6811 status = cli_ntcreate(cli, dname, 0,
6812 MAXIMUM_ALLOWED_ACCESS,
6813 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
6814 FILE_SHARE_DELETE,
6815 FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
6816 &dnum);
6818 if (!NT_STATUS_IS_OK(status)) {
6819 d_printf("Could not create %s: %s\n", dname,
6820 nt_errstr(status));
6821 return false;
6824 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
6825 FILE_NOTIFY_CHANGE_FILE_NAME |
6826 FILE_NOTIFY_CHANGE_DIR_NAME |
6827 FILE_NOTIFY_CHANGE_ATTRIBUTES |
6828 FILE_NOTIFY_CHANGE_LAST_WRITE,
6829 false, print_notifies, NULL);
6830 if (req1 == NULL) {
6831 d_printf("Could not create notify request\n");
6832 return false;
6835 req2 = torture_createdels_send(talloc_tos(), ev, cli,
6836 base_fname, 10, torture_numops);
6837 if (req2 == NULL) {
6838 d_printf("Could not create createdels request\n");
6839 return false;
6841 TALLOC_FREE(base_fname);
6843 tevent_req_set_callback(req2, notify_bench_done,
6844 &num_finished);
6847 while (num_finished < num_unc_names) {
6848 int ret;
6849 ret = tevent_loop_once(ev);
6850 if (ret != 0) {
6851 d_printf("tevent_loop_once failed\n");
6852 return false;
6856 if (!tevent_req_poll(req2, ev)) {
6857 d_printf("tevent_req_poll failed\n");
6860 status = torture_createdels_recv(req2);
6861 d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
6863 return true;
6866 static bool run_mangle1(int dummy)
6868 struct cli_state *cli;
6869 const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
6870 uint16_t fnum;
6871 fstring alt_name;
6872 NTSTATUS status;
6873 time_t change_time, access_time, write_time;
6874 SMB_OFF_T size;
6875 uint16_t mode;
6877 printf("starting mangle1 test\n");
6878 if (!torture_open_connection(&cli, 0)) {
6879 return False;
6882 cli_sockopt(cli, sockops);
6884 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6885 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6886 0, 0, &fnum);
6887 if (!NT_STATUS_IS_OK(status)) {
6888 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
6889 return false;
6891 cli_close(cli, fnum);
6893 status = cli_qpathinfo_alt_name(cli, fname, alt_name);
6894 if (!NT_STATUS_IS_OK(status)) {
6895 d_printf("cli_qpathinfo_alt_name failed: %s\n",
6896 nt_errstr(status));
6897 return false;
6899 d_printf("alt_name: %s\n", alt_name);
6901 status = cli_open(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
6902 if (!NT_STATUS_IS_OK(status)) {
6903 d_printf("cli_open(%s) failed: %s\n", alt_name,
6904 nt_errstr(status));
6905 return false;
6907 cli_close(cli, fnum);
6909 status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
6910 &write_time, &size, &mode);
6911 if (!NT_STATUS_IS_OK(status)) {
6912 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
6913 nt_errstr(status));
6914 return false;
6917 return true;
6920 static size_t null_source(uint8_t *buf, size_t n, void *priv)
6922 size_t *to_pull = (size_t *)priv;
6923 size_t thistime = *to_pull;
6925 thistime = MIN(thistime, n);
6926 if (thistime == 0) {
6927 return 0;
6930 memset(buf, 0, thistime);
6931 *to_pull -= thistime;
6932 return thistime;
6935 static bool run_windows_write(int dummy)
6937 struct cli_state *cli1;
6938 uint16_t fnum;
6939 int i;
6940 bool ret = false;
6941 const char *fname = "\\writetest.txt";
6942 struct timeval start_time;
6943 double seconds;
6944 double kbytes;
6945 NTSTATUS status;
6947 printf("starting windows_write test\n");
6948 if (!torture_open_connection(&cli1, 0)) {
6949 return False;
6952 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6953 if (!NT_STATUS_IS_OK(status)) {
6954 printf("open failed (%s)\n", nt_errstr(status));
6955 return False;
6958 cli_sockopt(cli1, sockops);
6960 start_time = timeval_current();
6962 for (i=0; i<torture_numops; i++) {
6963 uint8_t c = 0;
6964 off_t start = i * torture_blocksize;
6965 size_t to_pull = torture_blocksize - 1;
6967 status = cli_writeall(cli1, fnum, 0, &c,
6968 start + torture_blocksize - 1, 1, NULL);
6969 if (!NT_STATUS_IS_OK(status)) {
6970 printf("cli_write failed: %s\n", nt_errstr(status));
6971 goto fail;
6974 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
6975 null_source, &to_pull);
6976 if (!NT_STATUS_IS_OK(status)) {
6977 printf("cli_push returned: %s\n", nt_errstr(status));
6978 goto fail;
6982 seconds = timeval_elapsed(&start_time);
6983 kbytes = (double)torture_blocksize * torture_numops;
6984 kbytes /= 1024;
6986 printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
6987 (double)seconds, (int)(kbytes/seconds));
6989 ret = true;
6990 fail:
6991 cli_close(cli1, fnum);
6992 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6993 torture_close_connection(cli1);
6994 return ret;
6997 static bool run_cli_echo(int dummy)
6999 struct cli_state *cli;
7000 NTSTATUS status;
7002 printf("starting cli_echo test\n");
7003 if (!torture_open_connection(&cli, 0)) {
7004 return false;
7006 cli_sockopt(cli, sockops);
7008 status = cli_echo(cli, 5, data_blob_const("hello", 5));
7010 d_printf("cli_echo returned %s\n", nt_errstr(status));
7012 torture_close_connection(cli);
7013 return NT_STATUS_IS_OK(status);
7016 static bool run_uid_regression_test(int dummy)
7018 static struct cli_state *cli;
7019 int16_t old_vuid;
7020 int16_t old_cnum;
7021 bool correct = True;
7022 NTSTATUS status;
7024 printf("starting uid regression test\n");
7026 if (!torture_open_connection(&cli, 0)) {
7027 return False;
7030 cli_sockopt(cli, sockops);
7032 /* Ok - now save then logoff our current user. */
7033 old_vuid = cli->vuid;
7035 status = cli_ulogoff(cli);
7036 if (!NT_STATUS_IS_OK(status)) {
7037 d_printf("(%s) cli_ulogoff failed: %s\n",
7038 __location__, nt_errstr(status));
7039 correct = false;
7040 goto out;
7043 cli->vuid = old_vuid;
7045 /* Try an operation. */
7046 status = cli_mkdir(cli, "\\uid_reg_test");
7047 if (NT_STATUS_IS_OK(status)) {
7048 d_printf("(%s) cli_mkdir succeeded\n",
7049 __location__);
7050 correct = false;
7051 goto out;
7052 } else {
7053 /* Should be bad uid. */
7054 if (!check_error(__LINE__, cli, ERRSRV, ERRbaduid,
7055 NT_STATUS_USER_SESSION_DELETED)) {
7056 correct = false;
7057 goto out;
7061 old_cnum = cli->cnum;
7063 /* Now try a SMBtdis with the invald vuid set to zero. */
7064 cli->vuid = 0;
7066 /* This should succeed. */
7067 status = cli_tdis(cli);
7069 if (NT_STATUS_IS_OK(status)) {
7070 d_printf("First tdis with invalid vuid should succeed.\n");
7071 } else {
7072 d_printf("First tdis failed (%s)\n", nt_errstr(status));
7073 correct = false;
7074 goto out;
7077 cli->vuid = old_vuid;
7078 cli->cnum = old_cnum;
7080 /* This should fail. */
7081 status = cli_tdis(cli);
7082 if (NT_STATUS_IS_OK(status)) {
7083 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
7084 correct = false;
7085 goto out;
7086 } else {
7087 /* Should be bad tid. */
7088 if (!check_error(__LINE__, cli, ERRSRV, ERRinvnid,
7089 NT_STATUS_NETWORK_NAME_DELETED)) {
7090 correct = false;
7091 goto out;
7095 cli_rmdir(cli, "\\uid_reg_test");
7097 out:
7099 cli_shutdown(cli);
7100 return correct;
7104 static const char *illegal_chars = "*\\/?<>|\":";
7105 static char force_shortname_chars[] = " +,.[];=\177";
7107 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
7108 const char *mask, void *state)
7110 struct cli_state *pcli = (struct cli_state *)state;
7111 fstring fname;
7112 NTSTATUS status = NT_STATUS_OK;
7114 slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
7116 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
7117 return NT_STATUS_OK;
7119 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
7120 status = cli_rmdir(pcli, fname);
7121 if (!NT_STATUS_IS_OK(status)) {
7122 printf("del_fn: failed to rmdir %s\n,", fname );
7124 } else {
7125 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7126 if (!NT_STATUS_IS_OK(status)) {
7127 printf("del_fn: failed to unlink %s\n,", fname );
7130 return status;
7133 struct sn_state {
7134 int matched;
7135 int i;
7136 bool val;
7139 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
7140 const char *name, void *state)
7142 struct sn_state *s = (struct sn_state *)state;
7143 int i = s->i;
7145 #if 0
7146 printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
7147 i, finfo->name, finfo->short_name);
7148 #endif
7150 if (strchr(force_shortname_chars, i)) {
7151 if (!finfo->short_name) {
7152 /* Shortname not created when it should be. */
7153 d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
7154 __location__, finfo->name, i);
7155 s->val = true;
7157 } else if (finfo->short_name){
7158 /* Shortname created when it should not be. */
7159 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
7160 __location__, finfo->short_name, finfo->name);
7161 s->val = true;
7163 s->matched += 1;
7164 return NT_STATUS_OK;
7167 static bool run_shortname_test(int dummy)
7169 static struct cli_state *cli;
7170 bool correct = True;
7171 int i;
7172 struct sn_state s;
7173 char fname[20];
7174 NTSTATUS status;
7176 printf("starting shortname test\n");
7178 if (!torture_open_connection(&cli, 0)) {
7179 return False;
7182 cli_sockopt(cli, sockops);
7184 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7185 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7186 cli_rmdir(cli, "\\shortname");
7188 status = cli_mkdir(cli, "\\shortname");
7189 if (!NT_STATUS_IS_OK(status)) {
7190 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
7191 __location__, nt_errstr(status));
7192 correct = false;
7193 goto out;
7196 strlcpy(fname, "\\shortname\\", sizeof(fname));
7197 strlcat(fname, "test .txt", sizeof(fname));
7199 s.val = false;
7201 for (i = 32; i < 128; i++) {
7202 uint16_t fnum = (uint16_t)-1;
7204 s.i = i;
7206 if (strchr(illegal_chars, i)) {
7207 continue;
7209 fname[15] = i;
7211 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
7212 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum);
7213 if (!NT_STATUS_IS_OK(status)) {
7214 d_printf("(%s) cli_nt_create of %s failed: %s\n",
7215 __location__, fname, nt_errstr(status));
7216 correct = false;
7217 goto out;
7219 cli_close(cli, fnum);
7221 s.matched = 0;
7222 status = cli_list(cli, "\\shortname\\test*.*", 0,
7223 shortname_list_fn, &s);
7224 if (s.matched != 1) {
7225 d_printf("(%s) failed to list %s: %s\n",
7226 __location__, fname, nt_errstr(status));
7227 correct = false;
7228 goto out;
7231 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7232 if (!NT_STATUS_IS_OK(status)) {
7233 d_printf("(%s) failed to delete %s: %s\n",
7234 __location__, fname, nt_errstr(status));
7235 correct = false;
7236 goto out;
7239 if (s.val) {
7240 correct = false;
7241 goto out;
7245 out:
7247 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7248 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7249 cli_rmdir(cli, "\\shortname");
7250 torture_close_connection(cli);
7251 return correct;
7254 static void pagedsearch_cb(struct tevent_req *req)
7256 int rc;
7257 struct tldap_message *msg;
7258 char *dn;
7260 rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
7261 if (rc != TLDAP_SUCCESS) {
7262 d_printf("tldap_search_paged_recv failed: %s\n",
7263 tldap_err2string(rc));
7264 return;
7266 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
7267 TALLOC_FREE(msg);
7268 return;
7270 if (!tldap_entry_dn(msg, &dn)) {
7271 d_printf("tldap_entry_dn failed\n");
7272 return;
7274 d_printf("%s\n", dn);
7275 TALLOC_FREE(msg);
7278 static bool run_tldap(int dummy)
7280 struct tldap_context *ld;
7281 int fd, rc;
7282 NTSTATUS status;
7283 struct sockaddr_storage addr;
7284 struct tevent_context *ev;
7285 struct tevent_req *req;
7286 char *basedn;
7287 const char *filter;
7289 if (!resolve_name(host, &addr, 0, false)) {
7290 d_printf("could not find host %s\n", host);
7291 return false;
7293 status = open_socket_out(&addr, 389, 9999, &fd);
7294 if (!NT_STATUS_IS_OK(status)) {
7295 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
7296 return false;
7299 ld = tldap_context_create(talloc_tos(), fd);
7300 if (ld == NULL) {
7301 close(fd);
7302 d_printf("tldap_context_create failed\n");
7303 return false;
7306 rc = tldap_fetch_rootdse(ld);
7307 if (rc != TLDAP_SUCCESS) {
7308 d_printf("tldap_fetch_rootdse failed: %s\n",
7309 tldap_errstr(talloc_tos(), ld, rc));
7310 return false;
7313 basedn = tldap_talloc_single_attribute(
7314 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
7315 if (basedn == NULL) {
7316 d_printf("no defaultNamingContext\n");
7317 return false;
7319 d_printf("defaultNamingContext: %s\n", basedn);
7321 ev = tevent_context_init(talloc_tos());
7322 if (ev == NULL) {
7323 d_printf("tevent_context_init failed\n");
7324 return false;
7327 req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
7328 TLDAP_SCOPE_SUB, "(objectclass=*)",
7329 NULL, 0, 0,
7330 NULL, 0, NULL, 0, 0, 0, 0, 5);
7331 if (req == NULL) {
7332 d_printf("tldap_search_paged_send failed\n");
7333 return false;
7335 tevent_req_set_callback(req, pagedsearch_cb, NULL);
7337 tevent_req_poll(req, ev);
7339 TALLOC_FREE(req);
7341 /* test search filters against rootDSE */
7342 filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
7343 "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
7345 rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
7346 NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
7347 talloc_tos(), NULL, NULL);
7348 if (rc != TLDAP_SUCCESS) {
7349 d_printf("tldap_search with complex filter failed: %s\n",
7350 tldap_errstr(talloc_tos(), ld, rc));
7351 return false;
7354 TALLOC_FREE(ld);
7355 return true;
7358 /* Torture test to ensure no regression of :
7359 https://bugzilla.samba.org/show_bug.cgi?id=7084
7362 static bool run_dir_createtime(int dummy)
7364 struct cli_state *cli;
7365 const char *dname = "\\testdir";
7366 const char *fname = "\\testdir\\testfile";
7367 NTSTATUS status;
7368 struct timespec create_time;
7369 struct timespec create_time1;
7370 uint16_t fnum;
7371 bool ret = false;
7373 if (!torture_open_connection(&cli, 0)) {
7374 return false;
7377 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7378 cli_rmdir(cli, dname);
7380 status = cli_mkdir(cli, dname);
7381 if (!NT_STATUS_IS_OK(status)) {
7382 printf("mkdir failed: %s\n", nt_errstr(status));
7383 goto out;
7386 status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
7387 NULL, NULL, NULL);
7388 if (!NT_STATUS_IS_OK(status)) {
7389 printf("cli_qpathinfo2 returned %s\n",
7390 nt_errstr(status));
7391 goto out;
7394 /* Sleep 3 seconds, then create a file. */
7395 sleep(3);
7397 status = cli_open(cli, fname, O_RDWR | O_CREAT | O_EXCL,
7398 DENY_NONE, &fnum);
7399 if (!NT_STATUS_IS_OK(status)) {
7400 printf("cli_open failed: %s\n", nt_errstr(status));
7401 goto out;
7404 status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
7405 NULL, NULL, NULL);
7406 if (!NT_STATUS_IS_OK(status)) {
7407 printf("cli_qpathinfo2 (2) returned %s\n",
7408 nt_errstr(status));
7409 goto out;
7412 if (timespec_compare(&create_time1, &create_time)) {
7413 printf("run_dir_createtime: create time was updated (error)\n");
7414 } else {
7415 printf("run_dir_createtime: create time was not updated (correct)\n");
7416 ret = true;
7419 out:
7421 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7422 cli_rmdir(cli, dname);
7423 if (!torture_close_connection(cli)) {
7424 ret = false;
7426 return ret;
7430 static bool run_streamerror(int dummy)
7432 struct cli_state *cli;
7433 const char *dname = "\\testdir";
7434 const char *streamname =
7435 "testdir:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
7436 NTSTATUS status;
7437 time_t change_time, access_time, write_time;
7438 SMB_OFF_T size;
7439 uint16_t mode, fnum;
7440 bool ret = true;
7442 if (!torture_open_connection(&cli, 0)) {
7443 return false;
7446 cli_unlink(cli, "\\testdir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7447 cli_rmdir(cli, dname);
7449 status = cli_mkdir(cli, dname);
7450 if (!NT_STATUS_IS_OK(status)) {
7451 printf("mkdir failed: %s\n", nt_errstr(status));
7452 return false;
7455 cli_qpathinfo1(cli, streamname, &change_time, &access_time, &write_time,
7456 &size, &mode);
7457 status = cli_nt_error(cli);
7459 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7460 printf("pathinfo returned %s, expected "
7461 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
7462 nt_errstr(status));
7463 ret = false;
7466 status = cli_ntcreate(cli, streamname, 0x16,
7467 FILE_READ_DATA|FILE_READ_EA|
7468 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
7469 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7470 FILE_OPEN, 0, 0, &fnum);
7472 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7473 printf("ntcreate returned %s, expected "
7474 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
7475 nt_errstr(status));
7476 ret = false;
7480 cli_rmdir(cli, dname);
7481 return ret;
7484 static bool run_local_substitute(int dummy)
7486 bool ok = true;
7488 ok &= subst_test("%U", "bla", "", -1, -1, "bla");
7489 ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
7490 ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
7491 ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
7492 ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
7493 ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
7494 ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
7495 ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
7497 /* Different captialization rules in sub_basic... */
7499 ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
7500 "blaDOM") == 0);
7502 return ok;
7505 static bool run_local_base64(int dummy)
7507 int i;
7508 bool ret = true;
7510 for (i=1; i<2000; i++) {
7511 DATA_BLOB blob1, blob2;
7512 char *b64;
7514 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
7515 blob1.length = i;
7516 generate_random_buffer(blob1.data, blob1.length);
7518 b64 = base64_encode_data_blob(talloc_tos(), blob1);
7519 if (b64 == NULL) {
7520 d_fprintf(stderr, "base64_encode_data_blob failed "
7521 "for %d bytes\n", i);
7522 ret = false;
7524 blob2 = base64_decode_data_blob(b64);
7525 TALLOC_FREE(b64);
7527 if (data_blob_cmp(&blob1, &blob2)) {
7528 d_fprintf(stderr, "data_blob_cmp failed for %d "
7529 "bytes\n", i);
7530 ret = false;
7532 TALLOC_FREE(blob1.data);
7533 data_blob_free(&blob2);
7535 return ret;
7538 static bool run_local_gencache(int dummy)
7540 char *val;
7541 time_t tm;
7542 DATA_BLOB blob;
7544 if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
7545 d_printf("%s: gencache_set() failed\n", __location__);
7546 return False;
7549 if (!gencache_get("foo", NULL, NULL)) {
7550 d_printf("%s: gencache_get() failed\n", __location__);
7551 return False;
7554 if (!gencache_get("foo", &val, &tm)) {
7555 d_printf("%s: gencache_get() failed\n", __location__);
7556 return False;
7559 if (strcmp(val, "bar") != 0) {
7560 d_printf("%s: gencache_get() returned %s, expected %s\n",
7561 __location__, val, "bar");
7562 SAFE_FREE(val);
7563 return False;
7566 SAFE_FREE(val);
7568 if (!gencache_del("foo")) {
7569 d_printf("%s: gencache_del() failed\n", __location__);
7570 return False;
7572 if (gencache_del("foo")) {
7573 d_printf("%s: second gencache_del() succeeded\n",
7574 __location__);
7575 return False;
7578 if (gencache_get("foo", &val, &tm)) {
7579 d_printf("%s: gencache_get() on deleted entry "
7580 "succeeded\n", __location__);
7581 return False;
7584 blob = data_blob_string_const_null("bar");
7585 tm = time(NULL) + 60;
7587 if (!gencache_set_data_blob("foo", &blob, tm)) {
7588 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
7589 return False;
7592 if (!gencache_get_data_blob("foo", &blob, NULL, NULL)) {
7593 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
7594 return False;
7597 if (strcmp((const char *)blob.data, "bar") != 0) {
7598 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
7599 __location__, (const char *)blob.data, "bar");
7600 data_blob_free(&blob);
7601 return False;
7604 data_blob_free(&blob);
7606 if (!gencache_del("foo")) {
7607 d_printf("%s: gencache_del() failed\n", __location__);
7608 return False;
7610 if (gencache_del("foo")) {
7611 d_printf("%s: second gencache_del() succeeded\n",
7612 __location__);
7613 return False;
7616 if (gencache_get_data_blob("foo", &blob, NULL, NULL)) {
7617 d_printf("%s: gencache_get_data_blob() on deleted entry "
7618 "succeeded\n", __location__);
7619 return False;
7622 return True;
7625 static bool rbt_testval(struct db_context *db, const char *key,
7626 const char *value)
7628 struct db_record *rec;
7629 TDB_DATA data = string_tdb_data(value);
7630 bool ret = false;
7631 NTSTATUS status;
7633 rec = db->fetch_locked(db, db, string_tdb_data(key));
7634 if (rec == NULL) {
7635 d_fprintf(stderr, "fetch_locked failed\n");
7636 goto done;
7638 status = rec->store(rec, data, 0);
7639 if (!NT_STATUS_IS_OK(status)) {
7640 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
7641 goto done;
7643 TALLOC_FREE(rec);
7645 rec = db->fetch_locked(db, db, string_tdb_data(key));
7646 if (rec == NULL) {
7647 d_fprintf(stderr, "second fetch_locked failed\n");
7648 goto done;
7650 if ((rec->value.dsize != data.dsize)
7651 || (memcmp(rec->value.dptr, data.dptr, data.dsize) != 0)) {
7652 d_fprintf(stderr, "Got wrong data back\n");
7653 goto done;
7656 ret = true;
7657 done:
7658 TALLOC_FREE(rec);
7659 return ret;
7662 static bool run_local_rbtree(int dummy)
7664 struct db_context *db;
7665 bool ret = false;
7666 int i;
7668 db = db_open_rbt(NULL);
7670 if (db == NULL) {
7671 d_fprintf(stderr, "db_open_rbt failed\n");
7672 return false;
7675 for (i=0; i<1000; i++) {
7676 char *key, *value;
7678 if (asprintf(&key, "key%ld", random()) == -1) {
7679 goto done;
7681 if (asprintf(&value, "value%ld", random()) == -1) {
7682 SAFE_FREE(key);
7683 goto done;
7686 if (!rbt_testval(db, key, value)) {
7687 SAFE_FREE(key);
7688 SAFE_FREE(value);
7689 goto done;
7692 SAFE_FREE(value);
7693 if (asprintf(&value, "value%ld", random()) == -1) {
7694 SAFE_FREE(key);
7695 goto done;
7698 if (!rbt_testval(db, key, value)) {
7699 SAFE_FREE(key);
7700 SAFE_FREE(value);
7701 goto done;
7704 SAFE_FREE(key);
7705 SAFE_FREE(value);
7708 ret = true;
7710 done:
7711 TALLOC_FREE(db);
7712 return ret;
7717 local test for character set functions
7719 This is a very simple test for the functionality in convert_string_error()
7721 static bool run_local_convert_string(int dummy)
7723 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
7724 const char *test_strings[2] = { "March", "M\303\244rz" };
7725 char dst[7];
7726 int i;
7728 for (i=0; i<2; i++) {
7729 const char *str = test_strings[i];
7730 int len = strlen(str);
7731 size_t converted_size;
7732 bool ret;
7734 memset(dst, 'X', sizeof(dst));
7736 /* first try with real source length */
7737 ret = convert_string_error(CH_UNIX, CH_UTF8,
7738 str, len,
7739 dst, sizeof(dst),
7740 &converted_size);
7741 if (ret != true) {
7742 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
7743 goto failed;
7746 if (converted_size != len) {
7747 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
7748 str, len, (int)converted_size);
7749 goto failed;
7752 if (strncmp(str, dst, converted_size) != 0) {
7753 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
7754 goto failed;
7757 if (strlen(str) != converted_size) {
7758 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
7759 (int)strlen(str), (int)converted_size);
7760 goto failed;
7763 if (dst[converted_size] != 'X') {
7764 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
7765 goto failed;
7768 /* now with srclen==-1, this causes the nul to be
7769 * converted too */
7770 ret = convert_string_error(CH_UNIX, CH_UTF8,
7771 str, -1,
7772 dst, sizeof(dst),
7773 &converted_size);
7774 if (ret != true) {
7775 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
7776 goto failed;
7779 if (converted_size != len+1) {
7780 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
7781 str, len, (int)converted_size);
7782 goto failed;
7785 if (strncmp(str, dst, converted_size) != 0) {
7786 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
7787 goto failed;
7790 if (len+1 != converted_size) {
7791 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
7792 len+1, (int)converted_size);
7793 goto failed;
7796 if (dst[converted_size] != 'X') {
7797 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
7798 goto failed;
7804 TALLOC_FREE(tmp_ctx);
7805 return true;
7806 failed:
7807 TALLOC_FREE(tmp_ctx);
7808 return false;
7812 struct talloc_dict_test {
7813 int content;
7816 static int talloc_dict_traverse_fn(DATA_BLOB key, void *data, void *priv)
7818 int *count = (int *)priv;
7819 *count += 1;
7820 return 0;
7823 static bool run_local_talloc_dict(int dummy)
7825 struct talloc_dict *dict;
7826 struct talloc_dict_test *t;
7827 int key, count;
7829 dict = talloc_dict_init(talloc_tos());
7830 if (dict == NULL) {
7831 return false;
7834 t = talloc(talloc_tos(), struct talloc_dict_test);
7835 if (t == NULL) {
7836 return false;
7839 key = 1;
7840 t->content = 1;
7841 if (!talloc_dict_set(dict, data_blob_const(&key, sizeof(key)), t)) {
7842 return false;
7845 count = 0;
7846 if (talloc_dict_traverse(dict, talloc_dict_traverse_fn, &count) != 0) {
7847 return false;
7850 if (count != 1) {
7851 return false;
7854 TALLOC_FREE(dict);
7856 return true;
7859 static bool run_local_string_to_sid(int dummy) {
7860 struct dom_sid sid;
7862 if (string_to_sid(&sid, "S--1-5-32-545")) {
7863 printf("allowing S--1-5-32-545\n");
7864 return false;
7866 if (string_to_sid(&sid, "S-1-5-32-+545")) {
7867 printf("allowing S-1-5-32-+545\n");
7868 return false;
7870 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")) {
7871 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
7872 return false;
7874 if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
7875 printf("allowing S-1-5-32-545-abc\n");
7876 return false;
7878 if (!string_to_sid(&sid, "S-1-5-32-545")) {
7879 printf("could not parse S-1-5-32-545\n");
7880 return false;
7882 if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
7883 printf("mis-parsed S-1-5-32-545 as %s\n",
7884 sid_string_tos(&sid));
7885 return false;
7887 return true;
7890 static bool run_local_binary_to_sid(int dummy) {
7891 struct dom_sid *sid = talloc(NULL, struct dom_sid);
7892 static const char good_binary_sid[] = {
7893 0x1, /* revision number */
7894 15, /* num auths */
7895 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
7896 0x1, 0x1, 0x1, 0x1, /* auth[0] */
7897 0x1, 0x1, 0x1, 0x1, /* auth[1] */
7898 0x1, 0x1, 0x1, 0x1, /* auth[2] */
7899 0x1, 0x1, 0x1, 0x1, /* auth[3] */
7900 0x1, 0x1, 0x1, 0x1, /* auth[4] */
7901 0x1, 0x1, 0x1, 0x1, /* auth[5] */
7902 0x1, 0x1, 0x1, 0x1, /* auth[6] */
7903 0x1, 0x1, 0x1, 0x1, /* auth[7] */
7904 0x1, 0x1, 0x1, 0x1, /* auth[8] */
7905 0x1, 0x1, 0x1, 0x1, /* auth[9] */
7906 0x1, 0x1, 0x1, 0x1, /* auth[10] */
7907 0x1, 0x1, 0x1, 0x1, /* auth[11] */
7908 0x1, 0x1, 0x1, 0x1, /* auth[12] */
7909 0x1, 0x1, 0x1, 0x1, /* auth[13] */
7910 0x1, 0x1, 0x1, 0x1, /* auth[14] */
7913 static const char long_binary_sid[] = {
7914 0x1, /* revision number */
7915 15, /* num auths */
7916 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
7917 0x1, 0x1, 0x1, 0x1, /* auth[0] */
7918 0x1, 0x1, 0x1, 0x1, /* auth[1] */
7919 0x1, 0x1, 0x1, 0x1, /* auth[2] */
7920 0x1, 0x1, 0x1, 0x1, /* auth[3] */
7921 0x1, 0x1, 0x1, 0x1, /* auth[4] */
7922 0x1, 0x1, 0x1, 0x1, /* auth[5] */
7923 0x1, 0x1, 0x1, 0x1, /* auth[6] */
7924 0x1, 0x1, 0x1, 0x1, /* auth[7] */
7925 0x1, 0x1, 0x1, 0x1, /* auth[8] */
7926 0x1, 0x1, 0x1, 0x1, /* auth[9] */
7927 0x1, 0x1, 0x1, 0x1, /* auth[10] */
7928 0x1, 0x1, 0x1, 0x1, /* auth[11] */
7929 0x1, 0x1, 0x1, 0x1, /* auth[12] */
7930 0x1, 0x1, 0x1, 0x1, /* auth[13] */
7931 0x1, 0x1, 0x1, 0x1, /* auth[14] */
7932 0x1, 0x1, 0x1, 0x1, /* auth[15] */
7933 0x1, 0x1, 0x1, 0x1, /* auth[16] */
7934 0x1, 0x1, 0x1, 0x1, /* auth[17] */
7937 static const char long_binary_sid2[] = {
7938 0x1, /* revision number */
7939 32, /* num auths */
7940 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
7941 0x1, 0x1, 0x1, 0x1, /* auth[0] */
7942 0x1, 0x1, 0x1, 0x1, /* auth[1] */
7943 0x1, 0x1, 0x1, 0x1, /* auth[2] */
7944 0x1, 0x1, 0x1, 0x1, /* auth[3] */
7945 0x1, 0x1, 0x1, 0x1, /* auth[4] */
7946 0x1, 0x1, 0x1, 0x1, /* auth[5] */
7947 0x1, 0x1, 0x1, 0x1, /* auth[6] */
7948 0x1, 0x1, 0x1, 0x1, /* auth[7] */
7949 0x1, 0x1, 0x1, 0x1, /* auth[8] */
7950 0x1, 0x1, 0x1, 0x1, /* auth[9] */
7951 0x1, 0x1, 0x1, 0x1, /* auth[10] */
7952 0x1, 0x1, 0x1, 0x1, /* auth[11] */
7953 0x1, 0x1, 0x1, 0x1, /* auth[12] */
7954 0x1, 0x1, 0x1, 0x1, /* auth[13] */
7955 0x1, 0x1, 0x1, 0x1, /* auth[14] */
7956 0x1, 0x1, 0x1, 0x1, /* auth[15] */
7957 0x1, 0x1, 0x1, 0x1, /* auth[16] */
7958 0x1, 0x1, 0x1, 0x1, /* auth[17] */
7959 0x1, 0x1, 0x1, 0x1, /* auth[18] */
7960 0x1, 0x1, 0x1, 0x1, /* auth[19] */
7961 0x1, 0x1, 0x1, 0x1, /* auth[20] */
7962 0x1, 0x1, 0x1, 0x1, /* auth[21] */
7963 0x1, 0x1, 0x1, 0x1, /* auth[22] */
7964 0x1, 0x1, 0x1, 0x1, /* auth[23] */
7965 0x1, 0x1, 0x1, 0x1, /* auth[24] */
7966 0x1, 0x1, 0x1, 0x1, /* auth[25] */
7967 0x1, 0x1, 0x1, 0x1, /* auth[26] */
7968 0x1, 0x1, 0x1, 0x1, /* auth[27] */
7969 0x1, 0x1, 0x1, 0x1, /* auth[28] */
7970 0x1, 0x1, 0x1, 0x1, /* auth[29] */
7971 0x1, 0x1, 0x1, 0x1, /* auth[30] */
7972 0x1, 0x1, 0x1, 0x1, /* auth[31] */
7975 if (!sid_parse(good_binary_sid, sizeof(good_binary_sid), sid)) {
7976 return false;
7978 if (sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid)) {
7979 return false;
7981 if (sid_parse(long_binary_sid, sizeof(long_binary_sid), sid)) {
7982 return false;
7984 return true;
7987 /* Split a path name into filename and stream name components. Canonicalise
7988 * such that an implicit $DATA token is always explicit.
7990 * The "specification" of this function can be found in the
7991 * run_local_stream_name() function in torture.c, I've tried those
7992 * combinations against a W2k3 server.
7995 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
7996 char **pbase, char **pstream)
7998 char *base = NULL;
7999 char *stream = NULL;
8000 char *sname; /* stream name */
8001 const char *stype; /* stream type */
8003 DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
8005 sname = strchr_m(fname, ':');
8007 if (lp_posix_pathnames() || (sname == NULL)) {
8008 if (pbase != NULL) {
8009 base = talloc_strdup(mem_ctx, fname);
8010 NT_STATUS_HAVE_NO_MEMORY(base);
8012 goto done;
8015 if (pbase != NULL) {
8016 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
8017 NT_STATUS_HAVE_NO_MEMORY(base);
8020 sname += 1;
8022 stype = strchr_m(sname, ':');
8024 if (stype == NULL) {
8025 sname = talloc_strdup(mem_ctx, sname);
8026 stype = "$DATA";
8028 else {
8029 if (strcasecmp_m(stype, ":$DATA") != 0) {
8031 * If there is an explicit stream type, so far we only
8032 * allow $DATA. Is there anything else allowed? -- vl
8034 DEBUG(10, ("[%s] is an invalid stream type\n", stype));
8035 TALLOC_FREE(base);
8036 return NT_STATUS_OBJECT_NAME_INVALID;
8038 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
8039 stype += 1;
8042 if (sname == NULL) {
8043 TALLOC_FREE(base);
8044 return NT_STATUS_NO_MEMORY;
8047 if (sname[0] == '\0') {
8049 * no stream name, so no stream
8051 goto done;
8054 if (pstream != NULL) {
8055 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
8056 if (stream == NULL) {
8057 TALLOC_FREE(sname);
8058 TALLOC_FREE(base);
8059 return NT_STATUS_NO_MEMORY;
8062 * upper-case the type field
8064 strupper_m(strchr_m(stream, ':')+1);
8067 done:
8068 if (pbase != NULL) {
8069 *pbase = base;
8071 if (pstream != NULL) {
8072 *pstream = stream;
8074 return NT_STATUS_OK;
8077 static bool test_stream_name(const char *fname, const char *expected_base,
8078 const char *expected_stream,
8079 NTSTATUS expected_status)
8081 NTSTATUS status;
8082 char *base = NULL;
8083 char *stream = NULL;
8085 status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
8086 if (!NT_STATUS_EQUAL(status, expected_status)) {
8087 goto error;
8090 if (!NT_STATUS_IS_OK(status)) {
8091 return true;
8094 if (base == NULL) goto error;
8096 if (strcmp(expected_base, base) != 0) goto error;
8098 if ((expected_stream != NULL) && (stream == NULL)) goto error;
8099 if ((expected_stream == NULL) && (stream != NULL)) goto error;
8101 if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
8102 goto error;
8104 TALLOC_FREE(base);
8105 TALLOC_FREE(stream);
8106 return true;
8108 error:
8109 d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
8110 fname, expected_base ? expected_base : "<NULL>",
8111 expected_stream ? expected_stream : "<NULL>",
8112 nt_errstr(expected_status));
8113 d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
8114 base ? base : "<NULL>", stream ? stream : "<NULL>",
8115 nt_errstr(status));
8116 TALLOC_FREE(base);
8117 TALLOC_FREE(stream);
8118 return false;
8121 static bool run_local_stream_name(int dummy)
8123 bool ret = true;
8125 ret &= test_stream_name(
8126 "bla", "bla", NULL, NT_STATUS_OK);
8127 ret &= test_stream_name(
8128 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
8129 ret &= test_stream_name(
8130 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8131 ret &= test_stream_name(
8132 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
8133 ret &= test_stream_name(
8134 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8135 ret &= test_stream_name(
8136 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
8137 ret &= test_stream_name(
8138 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
8139 ret &= test_stream_name(
8140 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
8142 return ret;
8145 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
8147 if (a.length != b.length) {
8148 printf("a.length=%d != b.length=%d\n",
8149 (int)a.length, (int)b.length);
8150 return false;
8152 if (memcmp(a.data, b.data, a.length) != 0) {
8153 printf("a.data and b.data differ\n");
8154 return false;
8156 return true;
8159 static bool run_local_memcache(int dummy)
8161 struct memcache *cache;
8162 DATA_BLOB k1, k2;
8163 DATA_BLOB d1, d2, d3;
8164 DATA_BLOB v1, v2, v3;
8166 TALLOC_CTX *mem_ctx;
8167 char *str1, *str2;
8168 size_t size1, size2;
8169 bool ret = false;
8171 cache = memcache_init(NULL, 100);
8173 if (cache == NULL) {
8174 printf("memcache_init failed\n");
8175 return false;
8178 d1 = data_blob_const("d1", 2);
8179 d2 = data_blob_const("d2", 2);
8180 d3 = data_blob_const("d3", 2);
8182 k1 = data_blob_const("d1", 2);
8183 k2 = data_blob_const("d2", 2);
8185 memcache_add(cache, STAT_CACHE, k1, d1);
8186 memcache_add(cache, GETWD_CACHE, k2, d2);
8188 if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
8189 printf("could not find k1\n");
8190 return false;
8192 if (!data_blob_equal(d1, v1)) {
8193 return false;
8196 if (!memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8197 printf("could not find k2\n");
8198 return false;
8200 if (!data_blob_equal(d2, v2)) {
8201 return false;
8204 memcache_add(cache, STAT_CACHE, k1, d3);
8206 if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
8207 printf("could not find replaced k1\n");
8208 return false;
8210 if (!data_blob_equal(d3, v3)) {
8211 return false;
8214 memcache_add(cache, GETWD_CACHE, k1, d1);
8216 if (memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8217 printf("Did find k2, should have been purged\n");
8218 return false;
8221 TALLOC_FREE(cache);
8223 cache = memcache_init(NULL, 0);
8225 mem_ctx = talloc_init("foo");
8227 str1 = talloc_strdup(mem_ctx, "string1");
8228 str2 = talloc_strdup(mem_ctx, "string2");
8230 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8231 data_blob_string_const("torture"), &str1);
8232 size1 = talloc_total_size(cache);
8234 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8235 data_blob_string_const("torture"), &str2);
8236 size2 = talloc_total_size(cache);
8238 printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
8240 if (size2 > size1) {
8241 printf("memcache leaks memory!\n");
8242 goto fail;
8245 ret = true;
8246 fail:
8247 TALLOC_FREE(cache);
8248 return ret;
8251 static void wbclient_done(struct tevent_req *req)
8253 wbcErr wbc_err;
8254 struct winbindd_response *wb_resp;
8255 int *i = (int *)tevent_req_callback_data_void(req);
8257 wbc_err = wb_trans_recv(req, req, &wb_resp);
8258 TALLOC_FREE(req);
8259 *i += 1;
8260 d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
8263 static bool run_local_wbclient(int dummy)
8265 struct event_context *ev;
8266 struct wb_context **wb_ctx;
8267 struct winbindd_request wb_req;
8268 bool result = false;
8269 int i, j;
8271 BlockSignals(True, SIGPIPE);
8273 ev = tevent_context_init_byname(talloc_tos(), "epoll");
8274 if (ev == NULL) {
8275 goto fail;
8278 wb_ctx = talloc_array(ev, struct wb_context *, nprocs);
8279 if (wb_ctx == NULL) {
8280 goto fail;
8283 ZERO_STRUCT(wb_req);
8284 wb_req.cmd = WINBINDD_PING;
8286 d_printf("nprocs=%d, numops=%d\n", (int)nprocs, (int)torture_numops);
8288 for (i=0; i<nprocs; i++) {
8289 wb_ctx[i] = wb_context_init(ev, NULL);
8290 if (wb_ctx[i] == NULL) {
8291 goto fail;
8293 for (j=0; j<torture_numops; j++) {
8294 struct tevent_req *req;
8295 req = wb_trans_send(ev, ev, wb_ctx[i],
8296 (j % 2) == 0, &wb_req);
8297 if (req == NULL) {
8298 goto fail;
8300 tevent_req_set_callback(req, wbclient_done, &i);
8304 i = 0;
8306 while (i < nprocs * torture_numops) {
8307 event_loop_once(ev);
8310 result = true;
8311 fail:
8312 TALLOC_FREE(ev);
8313 return result;
8316 static void getaddrinfo_finished(struct tevent_req *req)
8318 char *name = (char *)tevent_req_callback_data_void(req);
8319 struct addrinfo *ainfo;
8320 int res;
8322 res = getaddrinfo_recv(req, &ainfo);
8323 if (res != 0) {
8324 d_printf("gai(%s) returned %s\n", name, gai_strerror(res));
8325 return;
8327 d_printf("gai(%s) succeeded\n", name);
8328 freeaddrinfo(ainfo);
8331 static bool run_getaddrinfo_send(int dummy)
8333 TALLOC_CTX *frame = talloc_stackframe();
8334 struct fncall_context *ctx;
8335 struct tevent_context *ev;
8336 bool result = false;
8337 const char *names[4] = { "www.samba.org", "notfound.samba.org",
8338 "www.slashdot.org", "heise.de" };
8339 struct tevent_req *reqs[4];
8340 int i;
8342 ev = event_context_init(frame);
8343 if (ev == NULL) {
8344 goto fail;
8347 ctx = fncall_context_init(frame, 4);
8349 for (i=0; i<ARRAY_SIZE(names); i++) {
8350 reqs[i] = getaddrinfo_send(frame, ev, ctx, names[i], NULL,
8351 NULL);
8352 if (reqs[i] == NULL) {
8353 goto fail;
8355 tevent_req_set_callback(reqs[i], getaddrinfo_finished,
8356 discard_const_p(void, names[i]));
8359 for (i=0; i<ARRAY_SIZE(reqs); i++) {
8360 tevent_loop_once(ev);
8363 result = true;
8364 fail:
8365 TALLOC_FREE(frame);
8366 return result;
8369 static bool dbtrans_inc(struct db_context *db)
8371 struct db_record *rec;
8372 uint32_t *val;
8373 bool ret = false;
8374 NTSTATUS status;
8376 rec = db->fetch_locked(db, db, string_term_tdb_data("transtest"));
8377 if (rec == NULL) {
8378 printf(__location__ "fetch_lock failed\n");
8379 return false;
8382 if (rec->value.dsize != sizeof(uint32_t)) {
8383 printf(__location__ "value.dsize = %d\n",
8384 (int)rec->value.dsize);
8385 goto fail;
8388 val = (uint32_t *)rec->value.dptr;
8389 *val += 1;
8391 status = rec->store(rec, make_tdb_data((uint8_t *)val,
8392 sizeof(uint32_t)),
8394 if (!NT_STATUS_IS_OK(status)) {
8395 printf(__location__ "store failed: %s\n",
8396 nt_errstr(status));
8397 goto fail;
8400 ret = true;
8401 fail:
8402 TALLOC_FREE(rec);
8403 return ret;
8406 static bool run_local_dbtrans(int dummy)
8408 struct db_context *db;
8409 struct db_record *rec;
8410 NTSTATUS status;
8411 uint32_t initial;
8412 int res;
8414 db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
8415 O_RDWR|O_CREAT, 0600);
8416 if (db == NULL) {
8417 printf("Could not open transtest.db\n");
8418 return false;
8421 res = db->transaction_start(db);
8422 if (res != 0) {
8423 printf(__location__ "transaction_start failed\n");
8424 return false;
8427 rec = db->fetch_locked(db, db, string_term_tdb_data("transtest"));
8428 if (rec == NULL) {
8429 printf(__location__ "fetch_lock failed\n");
8430 return false;
8433 if (rec->value.dptr == NULL) {
8434 initial = 0;
8435 status = rec->store(
8436 rec, make_tdb_data((uint8_t *)&initial,
8437 sizeof(initial)),
8439 if (!NT_STATUS_IS_OK(status)) {
8440 printf(__location__ "store returned %s\n",
8441 nt_errstr(status));
8442 return false;
8446 TALLOC_FREE(rec);
8448 res = db->transaction_commit(db);
8449 if (res != 0) {
8450 printf(__location__ "transaction_commit failed\n");
8451 return false;
8454 while (true) {
8455 uint32_t val, val2;
8456 int i;
8458 res = db->transaction_start(db);
8459 if (res != 0) {
8460 printf(__location__ "transaction_start failed\n");
8461 break;
8464 if (!dbwrap_fetch_uint32(db, "transtest", &val)) {
8465 printf(__location__ "dbwrap_fetch_uint32 failed\n");
8466 break;
8469 for (i=0; i<10; i++) {
8470 if (!dbtrans_inc(db)) {
8471 return false;
8475 if (!dbwrap_fetch_uint32(db, "transtest", &val2)) {
8476 printf(__location__ "dbwrap_fetch_uint32 failed\n");
8477 break;
8480 if (val2 != val + 10) {
8481 printf(__location__ "val=%d, val2=%d\n",
8482 (int)val, (int)val2);
8483 break;
8486 printf("val2=%d\r", val2);
8488 res = db->transaction_commit(db);
8489 if (res != 0) {
8490 printf(__location__ "transaction_commit failed\n");
8491 break;
8495 TALLOC_FREE(db);
8496 return true;
8500 * Just a dummy test to be run under a debugger. There's no real way
8501 * to inspect the tevent_select specific function from outside of
8502 * tevent_select.c.
8505 static bool run_local_tevent_select(int dummy)
8507 struct tevent_context *ev;
8508 struct tevent_fd *fd1, *fd2;
8509 bool result = false;
8511 ev = tevent_context_init_byname(NULL, "select");
8512 if (ev == NULL) {
8513 d_fprintf(stderr, "tevent_context_init_byname failed\n");
8514 goto fail;
8517 fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
8518 if (fd1 == NULL) {
8519 d_fprintf(stderr, "tevent_add_fd failed\n");
8520 goto fail;
8522 fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
8523 if (fd2 == NULL) {
8524 d_fprintf(stderr, "tevent_add_fd failed\n");
8525 goto fail;
8527 TALLOC_FREE(fd2);
8529 fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
8530 if (fd2 == NULL) {
8531 d_fprintf(stderr, "tevent_add_fd failed\n");
8532 goto fail;
8535 result = true;
8536 fail:
8537 TALLOC_FREE(ev);
8538 return result;
8541 static double create_procs(bool (*fn)(int), bool *result)
8543 int i, status;
8544 volatile pid_t *child_status;
8545 volatile bool *child_status_out;
8546 int synccount;
8547 int tries = 8;
8548 struct timeval start;
8550 synccount = 0;
8552 child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*nprocs);
8553 if (!child_status) {
8554 printf("Failed to setup shared memory\n");
8555 return -1;
8558 child_status_out = (volatile bool *)shm_setup(sizeof(bool)*nprocs);
8559 if (!child_status_out) {
8560 printf("Failed to setup result status shared memory\n");
8561 return -1;
8564 for (i = 0; i < nprocs; i++) {
8565 child_status[i] = 0;
8566 child_status_out[i] = True;
8569 start = timeval_current();
8571 for (i=0;i<nprocs;i++) {
8572 procnum = i;
8573 if (fork() == 0) {
8574 pid_t mypid = getpid();
8575 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
8577 slprintf(myname,sizeof(myname),"CLIENT%d", i);
8579 while (1) {
8580 if (torture_open_connection(&current_cli, i)) break;
8581 if (tries-- == 0) {
8582 printf("pid %d failed to start\n", (int)getpid());
8583 _exit(1);
8585 smb_msleep(10);
8588 child_status[i] = getpid();
8590 while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
8592 child_status_out[i] = fn(i);
8593 _exit(0);
8597 do {
8598 synccount = 0;
8599 for (i=0;i<nprocs;i++) {
8600 if (child_status[i]) synccount++;
8602 if (synccount == nprocs) break;
8603 smb_msleep(10);
8604 } while (timeval_elapsed(&start) < 30);
8606 if (synccount != nprocs) {
8607 printf("FAILED TO START %d CLIENTS (started %d)\n", nprocs, synccount);
8608 *result = False;
8609 return timeval_elapsed(&start);
8612 /* start the client load */
8613 start = timeval_current();
8615 for (i=0;i<nprocs;i++) {
8616 child_status[i] = 0;
8619 printf("%d clients started\n", nprocs);
8621 for (i=0;i<nprocs;i++) {
8622 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
8625 printf("\n");
8627 for (i=0;i<nprocs;i++) {
8628 if (!child_status_out[i]) {
8629 *result = False;
8632 return timeval_elapsed(&start);
8635 #define FLAG_MULTIPROC 1
8637 static struct {
8638 const char *name;
8639 bool (*fn)(int);
8640 unsigned flags;
8641 } torture_ops[] = {
8642 {"FDPASS", run_fdpasstest, 0},
8643 {"LOCK1", run_locktest1, 0},
8644 {"LOCK2", run_locktest2, 0},
8645 {"LOCK3", run_locktest3, 0},
8646 {"LOCK4", run_locktest4, 0},
8647 {"LOCK5", run_locktest5, 0},
8648 {"LOCK6", run_locktest6, 0},
8649 {"LOCK7", run_locktest7, 0},
8650 {"LOCK8", run_locktest8, 0},
8651 {"LOCK9", run_locktest9, 0},
8652 {"UNLINK", run_unlinktest, 0},
8653 {"BROWSE", run_browsetest, 0},
8654 {"ATTR", run_attrtest, 0},
8655 {"TRANS2", run_trans2test, 0},
8656 {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
8657 {"TORTURE",run_torture, FLAG_MULTIPROC},
8658 {"RANDOMIPC", run_randomipc, 0},
8659 {"NEGNOWAIT", run_negprot_nowait, 0},
8660 {"NBENCH", run_nbench, 0},
8661 {"NBENCH2", run_nbench2, 0},
8662 {"OPLOCK1", run_oplock1, 0},
8663 {"OPLOCK2", run_oplock2, 0},
8664 {"OPLOCK4", run_oplock4, 0},
8665 {"DIR", run_dirtest, 0},
8666 {"DIR1", run_dirtest1, 0},
8667 {"DIR-CREATETIME", run_dir_createtime, 0},
8668 {"DENY1", torture_denytest1, 0},
8669 {"DENY2", torture_denytest2, 0},
8670 {"TCON", run_tcon_test, 0},
8671 {"TCONDEV", run_tcon_devtype_test, 0},
8672 {"RW1", run_readwritetest, 0},
8673 {"RW2", run_readwritemulti, FLAG_MULTIPROC},
8674 {"RW3", run_readwritelarge, 0},
8675 {"RW-SIGNING", run_readwritelarge_signtest, 0},
8676 {"OPEN", run_opentest, 0},
8677 {"POSIX", run_simple_posix_open_test, 0},
8678 {"POSIX-APPEND", run_posix_append, 0},
8679 {"CASE-INSENSITIVE-CREATE", run_case_insensitive_create, 0},
8680 {"ASYNC-ECHO", run_async_echo, 0},
8681 { "UID-REGRESSION-TEST", run_uid_regression_test, 0},
8682 { "SHORTNAME-TEST", run_shortname_test, 0},
8683 { "ADDRCHANGE", run_addrchange, 0},
8684 #if 1
8685 {"OPENATTR", run_openattrtest, 0},
8686 #endif
8687 {"XCOPY", run_xcopy, 0},
8688 {"RENAME", run_rename, 0},
8689 {"DELETE", run_deletetest, 0},
8690 {"DELETE-LN", run_deletetest_ln, 0},
8691 {"PROPERTIES", run_properties, 0},
8692 {"MANGLE", torture_mangle, 0},
8693 {"MANGLE1", run_mangle1, 0},
8694 {"W2K", run_w2ktest, 0},
8695 {"TRANS2SCAN", torture_trans2_scan, 0},
8696 {"NTTRANSSCAN", torture_nttrans_scan, 0},
8697 {"UTABLE", torture_utable, 0},
8698 {"CASETABLE", torture_casetable, 0},
8699 {"ERRMAPEXTRACT", run_error_map_extract, 0},
8700 {"PIPE_NUMBER", run_pipe_number, 0},
8701 {"TCON2", run_tcon2_test, 0},
8702 {"IOCTL", torture_ioctl_test, 0},
8703 {"CHKPATH", torture_chkpath_test, 0},
8704 {"FDSESS", run_fdsesstest, 0},
8705 { "EATEST", run_eatest, 0},
8706 { "SESSSETUP_BENCH", run_sesssetup_bench, 0},
8707 { "CHAIN1", run_chain1, 0},
8708 { "CHAIN2", run_chain2, 0},
8709 { "WINDOWS-WRITE", run_windows_write, 0},
8710 { "NTTRANS-CREATE", run_nttrans_create, 0},
8711 { "CLI_ECHO", run_cli_echo, 0},
8712 { "GETADDRINFO", run_getaddrinfo_send, 0},
8713 { "TLDAP", run_tldap },
8714 { "STREAMERROR", run_streamerror },
8715 { "NOTIFY-BENCH", run_notify_bench },
8716 { "BAD-NBT-SESSION", run_bad_nbt_session },
8717 { "SMB-ANY-CONNECT", run_smb_any_connect },
8718 { "NOTIFY-ONLINE", run_notify_online },
8719 { "SMB2-BASIC", run_smb2_basic },
8720 { "LOCAL-SUBSTITUTE", run_local_substitute, 0},
8721 { "LOCAL-GENCACHE", run_local_gencache, 0},
8722 { "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0},
8723 { "LOCAL-BASE64", run_local_base64, 0},
8724 { "LOCAL-RBTREE", run_local_rbtree, 0},
8725 { "LOCAL-MEMCACHE", run_local_memcache, 0},
8726 { "LOCAL-STREAM-NAME", run_local_stream_name, 0},
8727 { "LOCAL-WBCLIENT", run_local_wbclient, 0},
8728 { "LOCAL-string_to_sid", run_local_string_to_sid, 0},
8729 { "LOCAL-binary_to_sid", run_local_binary_to_sid, 0},
8730 { "LOCAL-DBTRANS", run_local_dbtrans, 0},
8731 { "LOCAL-TEVENT-SELECT", run_local_tevent_select, 0},
8732 { "LOCAL-CONVERT-STRING", run_local_convert_string, 0},
8733 {NULL, NULL, 0}};
8737 /****************************************************************************
8738 run a specified test or "ALL"
8739 ****************************************************************************/
8740 static bool run_test(const char *name)
8742 bool ret = True;
8743 bool result = True;
8744 bool found = False;
8745 int i;
8746 double t;
8747 if (strequal(name,"ALL")) {
8748 for (i=0;torture_ops[i].name;i++) {
8749 run_test(torture_ops[i].name);
8751 found = True;
8754 for (i=0;torture_ops[i].name;i++) {
8755 fstr_sprintf(randomfname, "\\XX%x",
8756 (unsigned)random());
8758 if (strequal(name, torture_ops[i].name)) {
8759 found = True;
8760 printf("Running %s\n", name);
8761 if (torture_ops[i].flags & FLAG_MULTIPROC) {
8762 t = create_procs(torture_ops[i].fn, &result);
8763 if (!result) {
8764 ret = False;
8765 printf("TEST %s FAILED!\n", name);
8767 } else {
8768 struct timeval start;
8769 start = timeval_current();
8770 if (!torture_ops[i].fn(0)) {
8771 ret = False;
8772 printf("TEST %s FAILED!\n", name);
8774 t = timeval_elapsed(&start);
8776 printf("%s took %g secs\n\n", name, t);
8780 if (!found) {
8781 printf("Did not find a test named %s\n", name);
8782 ret = False;
8785 return ret;
8789 static void usage(void)
8791 int i;
8793 printf("WARNING samba4 test suite is much more complete nowadays.\n");
8794 printf("Please use samba4 torture.\n\n");
8796 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
8798 printf("\t-d debuglevel\n");
8799 printf("\t-U user%%pass\n");
8800 printf("\t-k use kerberos\n");
8801 printf("\t-N numprocs\n");
8802 printf("\t-n my_netbios_name\n");
8803 printf("\t-W workgroup\n");
8804 printf("\t-o num_operations\n");
8805 printf("\t-O socket_options\n");
8806 printf("\t-m maximum protocol\n");
8807 printf("\t-L use oplocks\n");
8808 printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
8809 printf("\t-A showall\n");
8810 printf("\t-p port\n");
8811 printf("\t-s seed\n");
8812 printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
8813 printf("\t-f filename filename to test\n");
8814 printf("\n\n");
8816 printf("tests are:");
8817 for (i=0;torture_ops[i].name;i++) {
8818 printf(" %s", torture_ops[i].name);
8820 printf("\n");
8822 printf("default test is ALL\n");
8824 exit(1);
8827 /****************************************************************************
8828 main program
8829 ****************************************************************************/
8830 int main(int argc,char *argv[])
8832 int opt, i;
8833 char *p;
8834 int gotuser = 0;
8835 int gotpass = 0;
8836 bool correct = True;
8837 TALLOC_CTX *frame = talloc_stackframe();
8838 int seed = time(NULL);
8840 #ifdef HAVE_SETBUFFER
8841 setbuffer(stdout, NULL, 0);
8842 #endif
8844 setup_logging("smbtorture", DEBUG_STDOUT);
8846 load_case_tables();
8848 if (is_default_dyn_CONFIGFILE()) {
8849 if(getenv("SMB_CONF_PATH")) {
8850 set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
8853 lp_load(get_dyn_CONFIGFILE(),True,False,False,True);
8854 load_interfaces();
8856 if (argc < 2) {
8857 usage();
8860 for(p = argv[1]; *p; p++)
8861 if(*p == '\\')
8862 *p = '/';
8864 if (strncmp(argv[1], "//", 2)) {
8865 usage();
8868 fstrcpy(host, &argv[1][2]);
8869 p = strchr_m(&host[2],'/');
8870 if (!p) {
8871 usage();
8873 *p = 0;
8874 fstrcpy(share, p+1);
8876 fstrcpy(myname, get_myname(talloc_tos()));
8877 if (!*myname) {
8878 fprintf(stderr, "Failed to get my hostname.\n");
8879 return 1;
8882 if (*username == 0 && getenv("LOGNAME")) {
8883 fstrcpy(username,getenv("LOGNAME"));
8886 argc--;
8887 argv++;
8889 fstrcpy(workgroup, lp_workgroup());
8891 while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
8892 != EOF) {
8893 switch (opt) {
8894 case 'p':
8895 port_to_use = atoi(optarg);
8896 break;
8897 case 's':
8898 seed = atoi(optarg);
8899 break;
8900 case 'W':
8901 fstrcpy(workgroup,optarg);
8902 break;
8903 case 'm':
8904 max_protocol = interpret_protocol(optarg, max_protocol);
8905 break;
8906 case 'N':
8907 nprocs = atoi(optarg);
8908 break;
8909 case 'o':
8910 torture_numops = atoi(optarg);
8911 break;
8912 case 'd':
8913 lp_set_cmdline("log level", optarg);
8914 break;
8915 case 'O':
8916 sockops = optarg;
8917 break;
8918 case 'L':
8919 use_oplocks = True;
8920 break;
8921 case 'l':
8922 local_path = optarg;
8923 break;
8924 case 'A':
8925 torture_showall = True;
8926 break;
8927 case 'n':
8928 fstrcpy(myname, optarg);
8929 break;
8930 case 'c':
8931 client_txt = optarg;
8932 break;
8933 case 'e':
8934 do_encrypt = true;
8935 break;
8936 case 'k':
8937 #ifdef HAVE_KRB5
8938 use_kerberos = True;
8939 #else
8940 d_printf("No kerberos support compiled in\n");
8941 exit(1);
8942 #endif
8943 break;
8944 case 'U':
8945 gotuser = 1;
8946 fstrcpy(username,optarg);
8947 p = strchr_m(username,'%');
8948 if (p) {
8949 *p = 0;
8950 fstrcpy(password, p+1);
8951 gotpass = 1;
8953 break;
8954 case 'b':
8955 fstrcpy(multishare_conn_fname, optarg);
8956 use_multishare_conn = True;
8957 break;
8958 case 'B':
8959 torture_blocksize = atoi(optarg);
8960 break;
8961 case 'f':
8962 test_filename = SMB_STRDUP(optarg);
8963 break;
8964 default:
8965 printf("Unknown option %c (%d)\n", (char)opt, opt);
8966 usage();
8970 d_printf("using seed %d\n", seed);
8972 srandom(seed);
8974 if(use_kerberos && !gotuser) gotpass = True;
8976 while (!gotpass) {
8977 p = getpass("Password:");
8978 if (p) {
8979 fstrcpy(password, p);
8980 gotpass = 1;
8984 printf("host=%s share=%s user=%s myname=%s\n",
8985 host, share, username, myname);
8987 if (argc == optind) {
8988 correct = run_test("ALL");
8989 } else {
8990 for (i=optind;i<argc;i++) {
8991 if (!run_test(argv[i])) {
8992 correct = False;
8997 TALLOC_FREE(frame);
8999 if (correct) {
9000 return(0);
9001 } else {
9002 return(1);