s3-torture: rw_torture3(): replace cli_read_old() with cli_read()
[Samba/gebeck_regimport.git] / source3 / torture / torture.c
blobb17171138fbc91cf1ee7dc7f8d0108c8009f07fe
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 size_t nread = 0;
573 NTSTATUS status;
575 memset(buf, '\0', sizeof(buf));
577 status = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
578 DENY_NONE, &fnum2);
579 if (!NT_STATUS_IS_OK(status)) {
580 status = cli_open(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
582 if (!NT_STATUS_IS_OK(status)) {
583 printf("open of %s failed (%s)\n",
584 lockfname, nt_errstr(status));
585 return False;
588 for (i=0;i<torture_numops;i++) {
589 unsigned n = (unsigned)sys_random()%10;
591 if (i % 10 == 0) {
592 printf("%d\r", i); fflush(stdout);
594 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
596 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
597 return False;
600 status = cli_open(c, fname, O_RDWR | O_CREAT | O_TRUNC,
601 DENY_ALL, &fnum);
602 if (!NT_STATUS_IS_OK(status)) {
603 printf("open failed (%s)\n", nt_errstr(status));
604 correct = False;
605 break;
608 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
609 sizeof(pid), NULL);
610 if (!NT_STATUS_IS_OK(status)) {
611 printf("write failed (%s)\n", nt_errstr(status));
612 correct = False;
615 for (j=0;j<50;j++) {
616 status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
617 sizeof(pid)+(j*sizeof(buf)),
618 sizeof(buf), NULL);
619 if (!NT_STATUS_IS_OK(status)) {
620 printf("write failed (%s)\n",
621 nt_errstr(status));
622 correct = False;
626 pid2 = 0;
628 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
629 &nread);
630 if (!NT_STATUS_IS_OK(status)) {
631 printf("read failed (%s)\n", nt_errstr(status));
632 correct = false;
633 } else if (nread != sizeof(pid)) {
634 printf("read/write compare failed: "
635 "recv %ld req %ld\n", (unsigned long)nread,
636 (unsigned long)sizeof(pid));
637 correct = false;
640 if (pid2 != pid) {
641 printf("data corruption!\n");
642 correct = False;
645 status = cli_close(c, fnum);
646 if (!NT_STATUS_IS_OK(status)) {
647 printf("close failed (%s)\n", nt_errstr(status));
648 correct = False;
651 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
652 if (!NT_STATUS_IS_OK(status)) {
653 printf("unlink failed (%s)\n", nt_errstr(status));
654 correct = False;
657 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
658 if (!NT_STATUS_IS_OK(status)) {
659 printf("unlock failed (%s)\n", nt_errstr(status));
660 correct = False;
664 cli_close(c, fnum2);
665 cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
667 printf("%d\n", i);
669 return correct;
672 static bool run_torture(int dummy)
674 struct cli_state *cli;
675 bool ret;
677 cli = current_cli;
679 cli_sockopt(cli, sockops);
681 ret = rw_torture(cli);
683 if (!torture_close_connection(cli)) {
684 ret = False;
687 return ret;
690 static bool rw_torture3(struct cli_state *c, char *lockfname)
692 uint16_t fnum = (uint16_t)-1;
693 unsigned int i = 0;
694 char buf[131072];
695 char buf_rd[131072];
696 unsigned count;
697 unsigned countprev = 0;
698 size_t sent = 0;
699 bool correct = True;
700 NTSTATUS status = NT_STATUS_OK;
702 srandom(1);
703 for (i = 0; i < sizeof(buf); i += sizeof(uint32))
705 SIVAL(buf, i, sys_random());
708 if (procnum == 0)
710 status = cli_unlink(
711 c, lockfname,
712 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
713 if (!NT_STATUS_IS_OK(status)) {
714 printf("unlink failed (%s) (normal, this file should "
715 "not exist)\n", nt_errstr(status));
718 status = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
719 DENY_NONE, &fnum);
720 if (!NT_STATUS_IS_OK(status)) {
721 printf("first open read/write of %s failed (%s)\n",
722 lockfname, nt_errstr(status));
723 return False;
726 else
728 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
730 status = cli_open(c, lockfname, O_RDONLY,
731 DENY_NONE, &fnum);
732 if (!NT_STATUS_IS_OK(status)) {
733 break;
735 smb_msleep(10);
737 if (!NT_STATUS_IS_OK(status)) {
738 printf("second open read-only of %s failed (%s)\n",
739 lockfname, nt_errstr(status));
740 return False;
744 i = 0;
745 for (count = 0; count < sizeof(buf); count += sent)
747 if (count >= countprev) {
748 printf("%d %8d\r", i, count);
749 fflush(stdout);
750 i++;
751 countprev += (sizeof(buf) / 20);
754 if (procnum == 0)
756 sent = ((unsigned)sys_random()%(20))+ 1;
757 if (sent > sizeof(buf) - count)
759 sent = sizeof(buf) - count;
762 status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
763 count, sent, NULL);
764 if (!NT_STATUS_IS_OK(status)) {
765 printf("write failed (%s)\n",
766 nt_errstr(status));
767 correct = False;
770 else
772 status = cli_read(c, fnum, buf_rd+count, count,
773 sizeof(buf)-count, &sent);
774 if(!NT_STATUS_IS_OK(status)) {
775 printf("read failed offset:%d size:%ld (%s)\n",
776 count, (unsigned long)sizeof(buf)-count,
777 nt_errstr(status));
778 correct = False;
779 sent = 0;
780 } else if (sent > 0) {
781 if (memcmp(buf_rd+count, buf+count, sent) != 0)
783 printf("read/write compare failed\n");
784 printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
785 correct = False;
786 break;
793 status = cli_close(c, fnum);
794 if (!NT_STATUS_IS_OK(status)) {
795 printf("close failed (%s)\n", nt_errstr(status));
796 correct = False;
799 return correct;
802 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
804 const char *lockfname = "\\torture2.lck";
805 uint16_t fnum1;
806 uint16_t fnum2;
807 int i;
808 char buf[131072];
809 char buf_rd[131072];
810 bool correct = True;
811 ssize_t bytes_read;
812 NTSTATUS status;
814 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
815 if (!NT_STATUS_IS_OK(status)) {
816 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
819 status = cli_open(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
820 DENY_NONE, &fnum1);
821 if (!NT_STATUS_IS_OK(status)) {
822 printf("first open read/write of %s failed (%s)\n",
823 lockfname, nt_errstr(status));
824 return False;
827 status = cli_open(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
828 if (!NT_STATUS_IS_OK(status)) {
829 printf("second open read-only of %s failed (%s)\n",
830 lockfname, nt_errstr(status));
831 cli_close(c1, fnum1);
832 return False;
835 for (i = 0; i < torture_numops; i++)
837 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
838 if (i % 10 == 0) {
839 printf("%d\r", i); fflush(stdout);
842 generate_random_buffer((unsigned char *)buf, buf_size);
844 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
845 buf_size, NULL);
846 if (!NT_STATUS_IS_OK(status)) {
847 printf("write failed (%s)\n", nt_errstr(status));
848 correct = False;
849 break;
852 if ((bytes_read = cli_read_old(c2, fnum2, buf_rd, 0, buf_size)) != buf_size) {
853 printf("read failed (%s)\n", cli_errstr(c2));
854 printf("read %d, expected %ld\n", (int)bytes_read,
855 (unsigned long)buf_size);
856 correct = False;
857 break;
860 if (memcmp(buf_rd, buf, buf_size) != 0)
862 printf("read/write compare failed\n");
863 correct = False;
864 break;
868 status = cli_close(c2, fnum2);
869 if (!NT_STATUS_IS_OK(status)) {
870 printf("close failed (%s)\n", nt_errstr(status));
871 correct = False;
874 status = cli_close(c1, fnum1);
875 if (!NT_STATUS_IS_OK(status)) {
876 printf("close failed (%s)\n", nt_errstr(status));
877 correct = False;
880 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
881 if (!NT_STATUS_IS_OK(status)) {
882 printf("unlink failed (%s)\n", nt_errstr(status));
883 correct = False;
886 return correct;
889 static bool run_readwritetest(int dummy)
891 struct cli_state *cli1, *cli2;
892 bool test1, test2 = False;
894 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
895 return False;
897 cli_sockopt(cli1, sockops);
898 cli_sockopt(cli2, sockops);
900 printf("starting readwritetest\n");
902 test1 = rw_torture2(cli1, cli2);
903 printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
905 if (test1) {
906 test2 = rw_torture2(cli1, cli1);
907 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
910 if (!torture_close_connection(cli1)) {
911 test1 = False;
914 if (!torture_close_connection(cli2)) {
915 test2 = False;
918 return (test1 && test2);
921 static bool run_readwritemulti(int dummy)
923 struct cli_state *cli;
924 bool test;
926 cli = current_cli;
928 cli_sockopt(cli, sockops);
930 printf("run_readwritemulti: fname %s\n", randomfname);
931 test = rw_torture3(cli, randomfname);
933 if (!torture_close_connection(cli)) {
934 test = False;
937 return test;
940 static bool run_readwritelarge_internal(int max_xmit_k)
942 static struct cli_state *cli1;
943 uint16_t fnum1;
944 const char *lockfname = "\\large.dat";
945 SMB_OFF_T fsize;
946 char buf[126*1024];
947 bool correct = True;
948 NTSTATUS status;
950 if (!torture_open_connection(&cli1, 0)) {
951 return False;
953 cli_sockopt(cli1, sockops);
954 memset(buf,'\0',sizeof(buf));
956 cli1->max_xmit = max_xmit_k*1024;
958 if (signing_state == Required) {
959 /* Horrible cheat to force
960 multiple signed outstanding
961 packets against a Samba server.
963 cli1->is_samba = false;
966 printf("starting readwritelarge_internal\n");
968 cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
970 status = cli_open(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
971 DENY_NONE, &fnum1);
972 if (!NT_STATUS_IS_OK(status)) {
973 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
974 return False;
977 cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
979 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
980 NULL, NULL, NULL);
981 if (!NT_STATUS_IS_OK(status)) {
982 printf("qfileinfo failed (%s)\n", nt_errstr(status));
983 correct = False;
986 if (fsize == sizeof(buf))
987 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
988 (unsigned long)fsize);
989 else {
990 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
991 (unsigned long)fsize);
992 correct = False;
995 status = cli_close(cli1, fnum1);
996 if (!NT_STATUS_IS_OK(status)) {
997 printf("close failed (%s)\n", nt_errstr(status));
998 correct = False;
1001 status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1002 if (!NT_STATUS_IS_OK(status)) {
1003 printf("unlink failed (%s)\n", nt_errstr(status));
1004 correct = False;
1007 status = cli_open(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1008 DENY_NONE, &fnum1);
1009 if (!NT_STATUS_IS_OK(status)) {
1010 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1011 return False;
1014 cli1->max_xmit = 4*1024;
1016 cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1018 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1019 NULL, NULL, NULL);
1020 if (!NT_STATUS_IS_OK(status)) {
1021 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1022 correct = False;
1025 if (fsize == sizeof(buf))
1026 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1027 (unsigned long)fsize);
1028 else {
1029 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1030 (unsigned long)fsize);
1031 correct = False;
1034 #if 0
1035 /* ToDo - set allocation. JRA */
1036 if(!cli_set_allocation_size(cli1, fnum1, 0)) {
1037 printf("set allocation size to zero failed (%s)\n", cli_errstr(&cli1));
1038 return False;
1040 if (!cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL, NULL,
1041 NULL, NULL)) {
1042 printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
1043 correct = False;
1045 if (fsize != 0)
1046 printf("readwritelarge test 3 (truncate test) succeeded (size = %x)\n", fsize);
1047 #endif
1049 status = cli_close(cli1, fnum1);
1050 if (!NT_STATUS_IS_OK(status)) {
1051 printf("close failed (%s)\n", nt_errstr(status));
1052 correct = False;
1055 if (!torture_close_connection(cli1)) {
1056 correct = False;
1058 return correct;
1061 static bool run_readwritelarge(int dummy)
1063 return run_readwritelarge_internal(128);
1066 static bool run_readwritelarge_signtest(int dummy)
1068 bool ret;
1069 signing_state = Required;
1070 ret = run_readwritelarge_internal(2);
1071 signing_state = Undefined;
1072 return ret;
1075 int line_count = 0;
1076 int nbio_id;
1078 #define ival(s) strtol(s, NULL, 0)
1080 /* run a test that simulates an approximate netbench client load */
1081 static bool run_netbench(int client)
1083 struct cli_state *cli;
1084 int i;
1085 char line[1024];
1086 char cname[20];
1087 FILE *f;
1088 const char *params[20];
1089 bool correct = True;
1091 cli = current_cli;
1093 nbio_id = client;
1095 cli_sockopt(cli, sockops);
1097 nb_setup(cli);
1099 slprintf(cname,sizeof(cname)-1, "client%d", client);
1101 f = fopen(client_txt, "r");
1103 if (!f) {
1104 perror(client_txt);
1105 return False;
1108 while (fgets(line, sizeof(line)-1, f)) {
1109 char *saveptr;
1110 line_count++;
1112 line[strlen(line)-1] = 0;
1114 /* printf("[%d] %s\n", line_count, line); */
1116 all_string_sub(line,"client1", cname, sizeof(line));
1118 /* parse the command parameters */
1119 params[0] = strtok_r(line, " ", &saveptr);
1120 i = 0;
1121 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1123 params[i] = "";
1125 if (i < 2) continue;
1127 if (!strncmp(params[0],"SMB", 3)) {
1128 printf("ERROR: You are using a dbench 1 load file\n");
1129 exit(1);
1132 if (!strcmp(params[0],"NTCreateX")) {
1133 nb_createx(params[1], ival(params[2]), ival(params[3]),
1134 ival(params[4]));
1135 } else if (!strcmp(params[0],"Close")) {
1136 nb_close(ival(params[1]));
1137 } else if (!strcmp(params[0],"Rename")) {
1138 nb_rename(params[1], params[2]);
1139 } else if (!strcmp(params[0],"Unlink")) {
1140 nb_unlink(params[1]);
1141 } else if (!strcmp(params[0],"Deltree")) {
1142 nb_deltree(params[1]);
1143 } else if (!strcmp(params[0],"Rmdir")) {
1144 nb_rmdir(params[1]);
1145 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1146 nb_qpathinfo(params[1]);
1147 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1148 nb_qfileinfo(ival(params[1]));
1149 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1150 nb_qfsinfo(ival(params[1]));
1151 } else if (!strcmp(params[0],"FIND_FIRST")) {
1152 nb_findfirst(params[1]);
1153 } else if (!strcmp(params[0],"WriteX")) {
1154 nb_writex(ival(params[1]),
1155 ival(params[2]), ival(params[3]), ival(params[4]));
1156 } else if (!strcmp(params[0],"ReadX")) {
1157 nb_readx(ival(params[1]),
1158 ival(params[2]), ival(params[3]), ival(params[4]));
1159 } else if (!strcmp(params[0],"Flush")) {
1160 nb_flush(ival(params[1]));
1161 } else {
1162 printf("Unknown operation %s\n", params[0]);
1163 exit(1);
1166 fclose(f);
1168 nb_cleanup();
1170 if (!torture_close_connection(cli)) {
1171 correct = False;
1174 return correct;
1178 /* run a test that simulates an approximate netbench client load */
1179 static bool run_nbench(int dummy)
1181 double t;
1182 bool correct = True;
1184 nbio_shmem(nprocs);
1186 nbio_id = -1;
1188 signal(SIGALRM, nb_alarm);
1189 alarm(1);
1190 t = create_procs(run_netbench, &correct);
1191 alarm(0);
1193 printf("\nThroughput %g MB/sec\n",
1194 1.0e-6 * nbio_total() / t);
1195 return correct;
1200 This test checks for two things:
1202 1) correct support for retaining locks over a close (ie. the server
1203 must not use posix semantics)
1204 2) support for lock timeouts
1206 static bool run_locktest1(int dummy)
1208 struct cli_state *cli1, *cli2;
1209 const char *fname = "\\lockt1.lck";
1210 uint16_t fnum1, fnum2, fnum3;
1211 time_t t1, t2;
1212 unsigned lock_timeout;
1213 NTSTATUS status;
1215 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1216 return False;
1218 cli_sockopt(cli1, sockops);
1219 cli_sockopt(cli2, sockops);
1221 printf("starting locktest1\n");
1223 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1225 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1226 &fnum1);
1227 if (!NT_STATUS_IS_OK(status)) {
1228 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1229 return False;
1232 status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1233 if (!NT_STATUS_IS_OK(status)) {
1234 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1235 return False;
1238 status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1239 if (!NT_STATUS_IS_OK(status)) {
1240 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1241 return False;
1244 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1245 if (!NT_STATUS_IS_OK(status)) {
1246 printf("lock1 failed (%s)\n", nt_errstr(status));
1247 return false;
1250 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1251 if (NT_STATUS_IS_OK(status)) {
1252 printf("lock2 succeeded! This is a locking bug\n");
1253 return false;
1254 } else {
1255 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1256 NT_STATUS_LOCK_NOT_GRANTED)) {
1257 return false;
1261 lock_timeout = (1 + (random() % 20));
1262 printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1263 t1 = time(NULL);
1264 status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1265 if (NT_STATUS_IS_OK(status)) {
1266 printf("lock3 succeeded! This is a locking bug\n");
1267 return false;
1268 } else {
1269 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1270 NT_STATUS_FILE_LOCK_CONFLICT)) {
1271 return false;
1274 t2 = time(NULL);
1276 if (ABS(t2 - t1) < lock_timeout-1) {
1277 printf("error: This server appears not to support timed lock requests\n");
1280 printf("server slept for %u seconds for a %u second timeout\n",
1281 (unsigned int)(t2-t1), lock_timeout);
1283 status = cli_close(cli1, fnum2);
1284 if (!NT_STATUS_IS_OK(status)) {
1285 printf("close1 failed (%s)\n", nt_errstr(status));
1286 return False;
1289 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1290 if (NT_STATUS_IS_OK(status)) {
1291 printf("lock4 succeeded! This is a locking bug\n");
1292 return false;
1293 } else {
1294 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1295 NT_STATUS_FILE_LOCK_CONFLICT)) {
1296 return false;
1300 status = cli_close(cli1, fnum1);
1301 if (!NT_STATUS_IS_OK(status)) {
1302 printf("close2 failed (%s)\n", nt_errstr(status));
1303 return False;
1306 status = cli_close(cli2, fnum3);
1307 if (!NT_STATUS_IS_OK(status)) {
1308 printf("close3 failed (%s)\n", nt_errstr(status));
1309 return False;
1312 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1313 if (!NT_STATUS_IS_OK(status)) {
1314 printf("unlink failed (%s)\n", nt_errstr(status));
1315 return False;
1319 if (!torture_close_connection(cli1)) {
1320 return False;
1323 if (!torture_close_connection(cli2)) {
1324 return False;
1327 printf("Passed locktest1\n");
1328 return True;
1332 this checks to see if a secondary tconx can use open files from an
1333 earlier tconx
1335 static bool run_tcon_test(int dummy)
1337 static struct cli_state *cli;
1338 const char *fname = "\\tcontest.tmp";
1339 uint16 fnum1;
1340 uint16 cnum1, cnum2, cnum3;
1341 uint16 vuid1, vuid2;
1342 char buf[4];
1343 bool ret = True;
1344 NTSTATUS status;
1346 memset(buf, '\0', sizeof(buf));
1348 if (!torture_open_connection(&cli, 0)) {
1349 return False;
1351 cli_sockopt(cli, sockops);
1353 printf("starting tcontest\n");
1355 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1357 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1358 if (!NT_STATUS_IS_OK(status)) {
1359 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1360 return False;
1363 cnum1 = cli_state_get_tid(cli);
1364 vuid1 = cli->vuid;
1366 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1367 if (!NT_STATUS_IS_OK(status)) {
1368 printf("initial write failed (%s)", nt_errstr(status));
1369 return False;
1372 status = cli_tcon_andx(cli, share, "?????",
1373 password, strlen(password)+1);
1374 if (!NT_STATUS_IS_OK(status)) {
1375 printf("%s refused 2nd tree connect (%s)\n", host,
1376 nt_errstr(status));
1377 cli_shutdown(cli);
1378 return False;
1381 cnum2 = cli_state_get_tid(cli);
1382 cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1383 vuid2 = cli->vuid + 1;
1385 /* try a write with the wrong tid */
1386 cli_state_set_tid(cli, cnum2);
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 wrong TID\n");
1391 ret = False;
1392 } else {
1393 printf("server fails write with wrong TID : %s\n",
1394 nt_errstr(status));
1398 /* try a write with an invalid tid */
1399 cli_state_set_tid(cli, cnum3);
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 TID\n");
1404 ret = False;
1405 } else {
1406 printf("server fails write with invalid TID : %s\n",
1407 nt_errstr(status));
1410 /* try a write with an invalid vuid */
1411 cli->vuid = vuid2;
1412 cli_state_set_tid(cli, cnum1);
1414 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1415 if (NT_STATUS_IS_OK(status)) {
1416 printf("* server allows write with invalid VUID\n");
1417 ret = False;
1418 } else {
1419 printf("server fails write with invalid VUID : %s\n",
1420 nt_errstr(status));
1423 cli_state_set_tid(cli, cnum1);
1424 cli->vuid = vuid1;
1426 status = cli_close(cli, fnum1);
1427 if (!NT_STATUS_IS_OK(status)) {
1428 printf("close failed (%s)\n", nt_errstr(status));
1429 return False;
1432 cli_state_set_tid(cli, cnum2);
1434 status = cli_tdis(cli);
1435 if (!NT_STATUS_IS_OK(status)) {
1436 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1437 return False;
1440 cli_state_set_tid(cli, cnum1);
1442 if (!torture_close_connection(cli)) {
1443 return False;
1446 return ret;
1451 checks for old style tcon support
1453 static bool run_tcon2_test(int dummy)
1455 static struct cli_state *cli;
1456 uint16 cnum, max_xmit;
1457 char *service;
1458 NTSTATUS status;
1460 if (!torture_open_connection(&cli, 0)) {
1461 return False;
1463 cli_sockopt(cli, sockops);
1465 printf("starting tcon2 test\n");
1467 if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1468 return false;
1471 status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1473 SAFE_FREE(service);
1475 if (!NT_STATUS_IS_OK(status)) {
1476 printf("tcon2 failed : %s\n", nt_errstr(status));
1477 } else {
1478 printf("tcon OK : max_xmit=%d cnum=%d\n",
1479 (int)max_xmit, (int)cnum);
1482 if (!torture_close_connection(cli)) {
1483 return False;
1486 printf("Passed tcon2 test\n");
1487 return True;
1490 static bool tcon_devtest(struct cli_state *cli,
1491 const char *myshare, const char *devtype,
1492 const char *return_devtype,
1493 NTSTATUS expected_error)
1495 NTSTATUS status;
1496 bool ret;
1498 status = cli_tcon_andx(cli, myshare, devtype,
1499 password, strlen(password)+1);
1501 if (NT_STATUS_IS_OK(expected_error)) {
1502 if (NT_STATUS_IS_OK(status)) {
1503 if (strcmp(cli->dev, return_devtype) == 0) {
1504 ret = True;
1505 } else {
1506 printf("tconX to share %s with type %s "
1507 "succeeded but returned the wrong "
1508 "device type (got [%s] but should have got [%s])\n",
1509 myshare, devtype, cli->dev, return_devtype);
1510 ret = False;
1512 } else {
1513 printf("tconX to share %s with type %s "
1514 "should have succeeded but failed\n",
1515 myshare, devtype);
1516 ret = False;
1518 cli_tdis(cli);
1519 } else {
1520 if (NT_STATUS_IS_OK(status)) {
1521 printf("tconx to share %s with type %s "
1522 "should have failed but succeeded\n",
1523 myshare, devtype);
1524 ret = False;
1525 } else {
1526 if (NT_STATUS_EQUAL(cli_nt_error(cli),
1527 expected_error)) {
1528 ret = True;
1529 } else {
1530 printf("Returned unexpected error\n");
1531 ret = False;
1535 return ret;
1539 checks for correct tconX support
1541 static bool run_tcon_devtype_test(int dummy)
1543 static struct cli_state *cli1 = NULL;
1544 int flags = 0;
1545 NTSTATUS status;
1546 bool ret = True;
1548 status = cli_full_connection(&cli1, myname,
1549 host, NULL, port_to_use,
1550 NULL, NULL,
1551 username, workgroup,
1552 password, flags, signing_state);
1554 if (!NT_STATUS_IS_OK(status)) {
1555 printf("could not open connection\n");
1556 return False;
1559 if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1560 ret = False;
1562 if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1563 ret = False;
1565 if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1566 ret = False;
1568 if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1569 ret = False;
1571 if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1572 ret = False;
1574 if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1575 ret = False;
1577 if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1578 ret = False;
1580 if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1581 ret = False;
1583 if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1584 ret = False;
1586 if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1587 ret = False;
1589 cli_shutdown(cli1);
1591 if (ret)
1592 printf("Passed tcondevtest\n");
1594 return ret;
1599 This test checks that
1601 1) the server supports multiple locking contexts on the one SMB
1602 connection, distinguished by PID.
1604 2) the server correctly fails overlapping locks made by the same PID (this
1605 goes against POSIX behaviour, which is why it is tricky to implement)
1607 3) the server denies unlock requests by an incorrect client PID
1609 static bool run_locktest2(int dummy)
1611 static struct cli_state *cli;
1612 const char *fname = "\\lockt2.lck";
1613 uint16_t fnum1, fnum2, fnum3;
1614 bool correct = True;
1615 NTSTATUS status;
1617 if (!torture_open_connection(&cli, 0)) {
1618 return False;
1621 cli_sockopt(cli, sockops);
1623 printf("starting locktest2\n");
1625 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1627 cli_setpid(cli, 1);
1629 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1630 if (!NT_STATUS_IS_OK(status)) {
1631 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1632 return False;
1635 status = cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1636 if (!NT_STATUS_IS_OK(status)) {
1637 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1638 return False;
1641 cli_setpid(cli, 2);
1643 status = cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1644 if (!NT_STATUS_IS_OK(status)) {
1645 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1646 return False;
1649 cli_setpid(cli, 1);
1651 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1652 if (!NT_STATUS_IS_OK(status)) {
1653 printf("lock1 failed (%s)\n", nt_errstr(status));
1654 return false;
1657 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1658 if (NT_STATUS_IS_OK(status)) {
1659 printf("WRITE lock1 succeeded! This is a locking bug\n");
1660 correct = false;
1661 } else {
1662 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1663 NT_STATUS_LOCK_NOT_GRANTED)) {
1664 return false;
1668 status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1669 if (NT_STATUS_IS_OK(status)) {
1670 printf("WRITE lock2 succeeded! This is a locking bug\n");
1671 correct = false;
1672 } else {
1673 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1674 NT_STATUS_LOCK_NOT_GRANTED)) {
1675 return false;
1679 status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1680 if (NT_STATUS_IS_OK(status)) {
1681 printf("READ lock2 succeeded! This is a locking bug\n");
1682 correct = false;
1683 } else {
1684 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1685 NT_STATUS_FILE_LOCK_CONFLICT)) {
1686 return false;
1690 status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1691 if (!NT_STATUS_IS_OK(status)) {
1692 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1694 cli_setpid(cli, 2);
1695 if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1696 printf("unlock at 100 succeeded! This is a locking bug\n");
1697 correct = False;
1700 status = cli_unlock(cli, fnum1, 0, 4);
1701 if (NT_STATUS_IS_OK(status)) {
1702 printf("unlock1 succeeded! This is a locking bug\n");
1703 correct = false;
1704 } else {
1705 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1706 NT_STATUS_RANGE_NOT_LOCKED)) {
1707 return false;
1711 status = cli_unlock(cli, fnum1, 0, 8);
1712 if (NT_STATUS_IS_OK(status)) {
1713 printf("unlock2 succeeded! This is a locking bug\n");
1714 correct = false;
1715 } else {
1716 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1717 NT_STATUS_RANGE_NOT_LOCKED)) {
1718 return false;
1722 status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1723 if (NT_STATUS_IS_OK(status)) {
1724 printf("lock3 succeeded! This is a locking bug\n");
1725 correct = false;
1726 } else {
1727 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1728 NT_STATUS_LOCK_NOT_GRANTED)) {
1729 return false;
1733 cli_setpid(cli, 1);
1735 status = cli_close(cli, fnum1);
1736 if (!NT_STATUS_IS_OK(status)) {
1737 printf("close1 failed (%s)\n", nt_errstr(status));
1738 return False;
1741 status = cli_close(cli, fnum2);
1742 if (!NT_STATUS_IS_OK(status)) {
1743 printf("close2 failed (%s)\n", nt_errstr(status));
1744 return False;
1747 status = cli_close(cli, fnum3);
1748 if (!NT_STATUS_IS_OK(status)) {
1749 printf("close3 failed (%s)\n", nt_errstr(status));
1750 return False;
1753 if (!torture_close_connection(cli)) {
1754 correct = False;
1757 printf("locktest2 finished\n");
1759 return correct;
1764 This test checks that
1766 1) the server supports the full offset range in lock requests
1768 static bool run_locktest3(int dummy)
1770 static struct cli_state *cli1, *cli2;
1771 const char *fname = "\\lockt3.lck";
1772 uint16_t fnum1, fnum2;
1773 int i;
1774 uint32 offset;
1775 bool correct = True;
1776 NTSTATUS status;
1778 #define NEXT_OFFSET offset += (~(uint32)0) / torture_numops
1780 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1781 return False;
1783 cli_sockopt(cli1, sockops);
1784 cli_sockopt(cli2, sockops);
1786 printf("starting locktest3\n");
1788 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1790 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1791 &fnum1);
1792 if (!NT_STATUS_IS_OK(status)) {
1793 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1794 return False;
1797 status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1798 if (!NT_STATUS_IS_OK(status)) {
1799 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1800 return False;
1803 for (offset=i=0;i<torture_numops;i++) {
1804 NEXT_OFFSET;
1806 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1807 if (!NT_STATUS_IS_OK(status)) {
1808 printf("lock1 %d failed (%s)\n",
1810 nt_errstr(status));
1811 return False;
1814 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1815 if (!NT_STATUS_IS_OK(status)) {
1816 printf("lock2 %d failed (%s)\n",
1818 nt_errstr(status));
1819 return False;
1823 for (offset=i=0;i<torture_numops;i++) {
1824 NEXT_OFFSET;
1826 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1827 if (NT_STATUS_IS_OK(status)) {
1828 printf("error: lock1 %d succeeded!\n", i);
1829 return False;
1832 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1833 if (NT_STATUS_IS_OK(status)) {
1834 printf("error: lock2 %d succeeded!\n", i);
1835 return False;
1838 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1839 if (NT_STATUS_IS_OK(status)) {
1840 printf("error: lock3 %d succeeded!\n", i);
1841 return False;
1844 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1845 if (NT_STATUS_IS_OK(status)) {
1846 printf("error: lock4 %d succeeded!\n", i);
1847 return False;
1851 for (offset=i=0;i<torture_numops;i++) {
1852 NEXT_OFFSET;
1854 status = cli_unlock(cli1, fnum1, offset-1, 1);
1855 if (!NT_STATUS_IS_OK(status)) {
1856 printf("unlock1 %d failed (%s)\n",
1858 nt_errstr(status));
1859 return False;
1862 status = cli_unlock(cli2, fnum2, offset-2, 1);
1863 if (!NT_STATUS_IS_OK(status)) {
1864 printf("unlock2 %d failed (%s)\n",
1866 nt_errstr(status));
1867 return False;
1871 status = cli_close(cli1, fnum1);
1872 if (!NT_STATUS_IS_OK(status)) {
1873 printf("close1 failed (%s)\n", nt_errstr(status));
1874 return False;
1877 status = cli_close(cli2, fnum2);
1878 if (!NT_STATUS_IS_OK(status)) {
1879 printf("close2 failed (%s)\n", nt_errstr(status));
1880 return False;
1883 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1884 if (!NT_STATUS_IS_OK(status)) {
1885 printf("unlink failed (%s)\n", nt_errstr(status));
1886 return False;
1889 if (!torture_close_connection(cli1)) {
1890 correct = False;
1893 if (!torture_close_connection(cli2)) {
1894 correct = False;
1897 printf("finished locktest3\n");
1899 return correct;
1902 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1903 printf("** "); correct = False; \
1907 looks at overlapping locks
1909 static bool run_locktest4(int dummy)
1911 static struct cli_state *cli1, *cli2;
1912 const char *fname = "\\lockt4.lck";
1913 uint16_t fnum1, fnum2, f;
1914 bool ret;
1915 char buf[1000];
1916 bool correct = True;
1917 NTSTATUS status;
1919 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1920 return False;
1923 cli_sockopt(cli1, sockops);
1924 cli_sockopt(cli2, sockops);
1926 printf("starting locktest4\n");
1928 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1930 cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1931 cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1933 memset(buf, 0, sizeof(buf));
1935 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
1936 NULL);
1937 if (!NT_STATUS_IS_OK(status)) {
1938 printf("Failed to create file: %s\n", nt_errstr(status));
1939 correct = False;
1940 goto fail;
1943 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1944 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
1945 EXPECTED(ret, False);
1946 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1948 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
1949 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
1950 EXPECTED(ret, True);
1951 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1953 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
1954 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
1955 EXPECTED(ret, False);
1956 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1958 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
1959 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
1960 EXPECTED(ret, True);
1961 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1963 ret = (cli_setpid(cli1, 1),
1964 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
1965 (cli_setpid(cli1, 2),
1966 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
1967 EXPECTED(ret, False);
1968 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1970 ret = (cli_setpid(cli1, 1),
1971 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
1972 (cli_setpid(cli1, 2),
1973 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
1974 EXPECTED(ret, True);
1975 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1977 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
1978 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
1979 EXPECTED(ret, True);
1980 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1982 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
1983 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
1984 EXPECTED(ret, False);
1985 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1987 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
1988 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
1989 EXPECTED(ret, False);
1990 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
1992 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
1993 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
1994 EXPECTED(ret, True);
1995 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1997 ret = (cli_setpid(cli1, 1),
1998 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
1999 (cli_setpid(cli1, 2),
2000 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2001 EXPECTED(ret, False);
2002 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2004 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2005 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2006 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2007 EXPECTED(ret, False);
2008 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2011 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2012 (cli_read_old(cli2, fnum2, buf, 120, 4) == 4);
2013 EXPECTED(ret, False);
2014 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2016 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2017 ret = NT_STATUS_IS_OK(status);
2018 if (ret) {
2019 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2020 NULL);
2021 ret = NT_STATUS_IS_OK(status);
2023 EXPECTED(ret, False);
2024 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2027 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2028 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2029 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2030 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2031 EXPECTED(ret, True);
2032 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2035 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2036 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2037 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2038 (cli_read_old(cli2, fnum2, buf, 150, 4) == 4) &&
2039 !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2040 150, 4, NULL))) &&
2041 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2042 EXPECTED(ret, True);
2043 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2045 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2046 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2047 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2048 160, 4, NULL)) &&
2049 (cli_read_old(cli2, fnum2, buf, 160, 4) == 4);
2050 EXPECTED(ret, True);
2051 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2053 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2054 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2055 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2056 170, 4, NULL)) &&
2057 (cli_read_old(cli2, fnum2, buf, 170, 4) == 4);
2058 EXPECTED(ret, True);
2059 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2061 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2062 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2063 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2064 !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2065 190, 4, NULL)) &&
2066 (cli_read_old(cli2, fnum2, buf, 190, 4) == 4);
2067 EXPECTED(ret, True);
2068 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2070 cli_close(cli1, fnum1);
2071 cli_close(cli2, fnum2);
2072 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2073 cli_open(cli1, fname, O_RDWR, DENY_NONE, &f);
2074 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2075 NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2076 NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2077 NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2078 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2079 cli_close(cli1, f);
2080 cli_close(cli1, fnum1);
2081 EXPECTED(ret, True);
2082 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2084 fail:
2085 cli_close(cli1, fnum1);
2086 cli_close(cli2, fnum2);
2087 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2088 torture_close_connection(cli1);
2089 torture_close_connection(cli2);
2091 printf("finished locktest4\n");
2092 return correct;
2096 looks at lock upgrade/downgrade.
2098 static bool run_locktest5(int dummy)
2100 static struct cli_state *cli1, *cli2;
2101 const char *fname = "\\lockt5.lck";
2102 uint16_t fnum1, fnum2, fnum3;
2103 bool ret;
2104 char buf[1000];
2105 bool correct = True;
2106 NTSTATUS status;
2108 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2109 return False;
2112 cli_sockopt(cli1, sockops);
2113 cli_sockopt(cli2, sockops);
2115 printf("starting locktest5\n");
2117 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2119 cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2120 cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2121 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2123 memset(buf, 0, sizeof(buf));
2125 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2126 NULL);
2127 if (!NT_STATUS_IS_OK(status)) {
2128 printf("Failed to create file: %s\n", nt_errstr(status));
2129 correct = False;
2130 goto fail;
2133 /* Check for NT bug... */
2134 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2135 NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2136 cli_close(cli1, fnum1);
2137 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2138 status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2139 ret = NT_STATUS_IS_OK(status);
2140 EXPECTED(ret, True);
2141 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2142 cli_close(cli1, fnum1);
2143 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2144 cli_unlock(cli1, fnum3, 0, 1);
2146 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2147 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2148 EXPECTED(ret, True);
2149 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2151 status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2152 ret = NT_STATUS_IS_OK(status);
2153 EXPECTED(ret, False);
2155 printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2157 /* Unlock the process 2 lock. */
2158 cli_unlock(cli2, fnum2, 0, 4);
2160 status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2161 ret = NT_STATUS_IS_OK(status);
2162 EXPECTED(ret, False);
2164 printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
2166 /* Unlock the process 1 fnum3 lock. */
2167 cli_unlock(cli1, fnum3, 0, 4);
2169 /* Stack 2 more locks here. */
2170 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2171 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2173 EXPECTED(ret, True);
2174 printf("the same process %s stack read locks\n", ret?"can":"cannot");
2176 /* Unlock the first process lock, then check this was the WRITE lock that was
2177 removed. */
2179 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2180 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2182 EXPECTED(ret, True);
2183 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2185 /* Unlock the process 2 lock. */
2186 cli_unlock(cli2, fnum2, 0, 4);
2188 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2190 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2191 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2192 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2194 EXPECTED(ret, True);
2195 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2197 /* Ensure the next unlock fails. */
2198 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2199 EXPECTED(ret, False);
2200 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2202 /* Ensure connection 2 can get a write lock. */
2203 status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2204 ret = NT_STATUS_IS_OK(status);
2205 EXPECTED(ret, True);
2207 printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2210 fail:
2211 cli_close(cli1, fnum1);
2212 cli_close(cli2, fnum2);
2213 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2214 if (!torture_close_connection(cli1)) {
2215 correct = False;
2217 if (!torture_close_connection(cli2)) {
2218 correct = False;
2221 printf("finished locktest5\n");
2223 return correct;
2227 tries the unusual lockingX locktype bits
2229 static bool run_locktest6(int dummy)
2231 static struct cli_state *cli;
2232 const char *fname[1] = { "\\lock6.txt" };
2233 int i;
2234 uint16_t fnum;
2235 NTSTATUS status;
2237 if (!torture_open_connection(&cli, 0)) {
2238 return False;
2241 cli_sockopt(cli, sockops);
2243 printf("starting locktest6\n");
2245 for (i=0;i<1;i++) {
2246 printf("Testing %s\n", fname[i]);
2248 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2250 cli_open(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2251 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2252 cli_close(cli, fnum);
2253 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2255 cli_open(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2256 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2257 cli_close(cli, fnum);
2258 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2260 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2263 torture_close_connection(cli);
2265 printf("finished locktest6\n");
2266 return True;
2269 static bool run_locktest7(int dummy)
2271 struct cli_state *cli1;
2272 const char *fname = "\\lockt7.lck";
2273 uint16_t fnum1;
2274 char buf[200];
2275 bool correct = False;
2276 NTSTATUS status;
2278 if (!torture_open_connection(&cli1, 0)) {
2279 return False;
2282 cli_sockopt(cli1, sockops);
2284 printf("starting locktest7\n");
2286 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2288 cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2290 memset(buf, 0, sizeof(buf));
2292 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2293 NULL);
2294 if (!NT_STATUS_IS_OK(status)) {
2295 printf("Failed to create file: %s\n", nt_errstr(status));
2296 goto fail;
2299 cli_setpid(cli1, 1);
2301 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2302 if (!NT_STATUS_IS_OK(status)) {
2303 printf("Unable to apply read lock on range 130:4, error was %s\n", nt_errstr(status));
2304 goto fail;
2305 } else {
2306 printf("pid1 successfully locked range 130:4 for READ\n");
2309 if (cli_read_old(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 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2321 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2322 goto fail;
2324 } else {
2325 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2326 goto fail;
2329 cli_setpid(cli1, 2);
2331 if (cli_read_old(cli1, fnum1, buf, 130, 4) != 4) {
2332 printf("pid2 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2333 } else {
2334 printf("pid2 successfully read the range 130:4\n");
2337 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2338 if (!NT_STATUS_IS_OK(status)) {
2339 printf("pid2 unable to write to the range 130:4, error was "
2340 "%s\n", nt_errstr(status));
2341 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2342 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2343 goto fail;
2345 } else {
2346 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2347 goto fail;
2350 cli_setpid(cli1, 1);
2351 cli_unlock(cli1, fnum1, 130, 4);
2353 status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2354 if (!NT_STATUS_IS_OK(status)) {
2355 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2356 goto fail;
2357 } else {
2358 printf("pid1 successfully locked range 130:4 for WRITE\n");
2361 if (cli_read_old(cli1, fnum1, buf, 130, 4) != 4) {
2362 printf("pid1 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2363 goto fail;
2364 } else {
2365 printf("pid1 successfully read the range 130:4\n");
2368 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2369 if (!NT_STATUS_IS_OK(status)) {
2370 printf("pid1 unable to write to the range 130:4, error was "
2371 "%s\n", nt_errstr(status));
2372 goto fail;
2373 } else {
2374 printf("pid1 successfully wrote to the range 130:4\n");
2377 cli_setpid(cli1, 2);
2379 if (cli_read_old(cli1, fnum1, buf, 130, 4) != 4) {
2380 printf("pid2 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2381 if (NT_STATUS_V(cli_nt_error(cli1)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
2382 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2383 goto fail;
2385 } else {
2386 printf("pid2 successfully read the range 130:4 (should be denied)\n");
2387 goto fail;
2390 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2391 if (!NT_STATUS_IS_OK(status)) {
2392 printf("pid2 unable to write to the range 130:4, error was "
2393 "%s\n", nt_errstr(status));
2394 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2395 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2396 goto fail;
2398 } else {
2399 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2400 goto fail;
2403 cli_unlock(cli1, fnum1, 130, 0);
2404 correct = True;
2406 fail:
2407 cli_close(cli1, fnum1);
2408 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2409 torture_close_connection(cli1);
2411 printf("finished locktest7\n");
2412 return correct;
2416 * This demonstrates a problem with our use of GPFS share modes: A file
2417 * descriptor sitting in the pending close queue holding a GPFS share mode
2418 * blocks opening a file another time. Happens with Word 2007 temp files.
2419 * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2420 * open is denied with NT_STATUS_SHARING_VIOLATION.
2423 static bool run_locktest8(int dummy)
2425 struct cli_state *cli1;
2426 const char *fname = "\\lockt8.lck";
2427 uint16_t fnum1, fnum2;
2428 char buf[200];
2429 bool correct = False;
2430 NTSTATUS status;
2432 if (!torture_open_connection(&cli1, 0)) {
2433 return False;
2436 cli_sockopt(cli1, sockops);
2438 printf("starting locktest8\n");
2440 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2442 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2443 &fnum1);
2444 if (!NT_STATUS_IS_OK(status)) {
2445 d_fprintf(stderr, "cli_open returned %s\n", nt_errstr(status));
2446 return false;
2449 memset(buf, 0, sizeof(buf));
2451 status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2452 if (!NT_STATUS_IS_OK(status)) {
2453 d_fprintf(stderr, "cli_open second time returned %s\n",
2454 nt_errstr(status));
2455 goto fail;
2458 status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2459 if (!NT_STATUS_IS_OK(status)) {
2460 printf("Unable to apply read lock on range 1:1, error was "
2461 "%s\n", nt_errstr(status));
2462 goto fail;
2465 status = cli_close(cli1, fnum1);
2466 if (!NT_STATUS_IS_OK(status)) {
2467 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2468 goto fail;
2471 status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2472 if (!NT_STATUS_IS_OK(status)) {
2473 d_fprintf(stderr, "cli_open third time returned %s\n",
2474 nt_errstr(status));
2475 goto fail;
2478 correct = true;
2480 fail:
2481 cli_close(cli1, fnum1);
2482 cli_close(cli1, fnum2);
2483 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2484 torture_close_connection(cli1);
2486 printf("finished locktest8\n");
2487 return correct;
2491 * This test is designed to be run in conjunction with
2492 * external NFS or POSIX locks taken in the filesystem.
2493 * It checks that the smbd server will block until the
2494 * lock is released and then acquire it. JRA.
2497 static bool got_alarm;
2498 static int alarm_fd;
2500 static void alarm_handler(int dummy)
2502 got_alarm = True;
2505 static void alarm_handler_parent(int dummy)
2507 close(alarm_fd);
2510 static void do_local_lock(int read_fd, int write_fd)
2512 int fd;
2513 char c = '\0';
2514 struct flock lock;
2515 const char *local_pathname = NULL;
2516 int ret;
2518 local_pathname = talloc_asprintf(talloc_tos(),
2519 "%s/lockt9.lck", local_path);
2520 if (!local_pathname) {
2521 printf("child: alloc fail\n");
2522 exit(1);
2525 unlink(local_pathname);
2526 fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2527 if (fd == -1) {
2528 printf("child: open of %s failed %s.\n",
2529 local_pathname, strerror(errno));
2530 exit(1);
2533 /* Now take a fcntl lock. */
2534 lock.l_type = F_WRLCK;
2535 lock.l_whence = SEEK_SET;
2536 lock.l_start = 0;
2537 lock.l_len = 4;
2538 lock.l_pid = getpid();
2540 ret = fcntl(fd,F_SETLK,&lock);
2541 if (ret == -1) {
2542 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2543 local_pathname, strerror(errno));
2544 exit(1);
2545 } else {
2546 printf("child: got lock 0:4 on file %s.\n",
2547 local_pathname );
2548 fflush(stdout);
2551 CatchSignal(SIGALRM, alarm_handler);
2552 alarm(5);
2553 /* Signal the parent. */
2554 if (write(write_fd, &c, 1) != 1) {
2555 printf("child: start signal fail %s.\n",
2556 strerror(errno));
2557 exit(1);
2559 alarm(0);
2561 alarm(10);
2562 /* Wait for the parent to be ready. */
2563 if (read(read_fd, &c, 1) != 1) {
2564 printf("child: reply signal fail %s.\n",
2565 strerror(errno));
2566 exit(1);
2568 alarm(0);
2570 sleep(5);
2571 close(fd);
2572 printf("child: released lock 0:4 on file %s.\n",
2573 local_pathname );
2574 fflush(stdout);
2575 exit(0);
2578 static bool run_locktest9(int dummy)
2580 struct cli_state *cli1;
2581 const char *fname = "\\lockt9.lck";
2582 uint16_t fnum;
2583 bool correct = False;
2584 int pipe_in[2], pipe_out[2];
2585 pid_t child_pid;
2586 char c = '\0';
2587 int ret;
2588 struct timeval start;
2589 double seconds;
2590 NTSTATUS status;
2592 printf("starting locktest9\n");
2594 if (local_path == NULL) {
2595 d_fprintf(stderr, "locktest9 must be given a local path via -l <localpath>\n");
2596 return false;
2599 if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2600 return false;
2603 child_pid = fork();
2604 if (child_pid == -1) {
2605 return false;
2608 if (child_pid == 0) {
2609 /* Child. */
2610 do_local_lock(pipe_out[0], pipe_in[1]);
2611 exit(0);
2614 close(pipe_out[0]);
2615 close(pipe_in[1]);
2616 pipe_out[0] = -1;
2617 pipe_in[1] = -1;
2619 /* Parent. */
2620 ret = read(pipe_in[0], &c, 1);
2621 if (ret != 1) {
2622 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2623 strerror(errno));
2624 return false;
2627 if (!torture_open_connection(&cli1, 0)) {
2628 return false;
2631 cli_sockopt(cli1, sockops);
2633 status = cli_open(cli1, fname, O_RDWR, DENY_NONE,
2634 &fnum);
2635 if (!NT_STATUS_IS_OK(status)) {
2636 d_fprintf(stderr, "cli_open returned %s\n", nt_errstr(status));
2637 return false;
2640 /* Ensure the child has the lock. */
2641 status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2642 if (NT_STATUS_IS_OK(status)) {
2643 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2644 goto fail;
2645 } else {
2646 d_printf("Child has the lock.\n");
2649 /* Tell the child to wait 5 seconds then exit. */
2650 ret = write(pipe_out[1], &c, 1);
2651 if (ret != 1) {
2652 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2653 strerror(errno));
2654 goto fail;
2657 /* Wait 20 seconds for the lock. */
2658 alarm_fd = cli1->fd;
2659 CatchSignal(SIGALRM, alarm_handler_parent);
2660 alarm(20);
2662 start = timeval_current();
2664 status = cli_lock32(cli1, fnum, 0, 4, -1, WRITE_LOCK);
2665 if (!NT_STATUS_IS_OK(status)) {
2666 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2667 "%s\n", nt_errstr(status));
2668 goto fail_nofd;
2670 alarm(0);
2672 seconds = timeval_elapsed(&start);
2674 printf("Parent got the lock after %.2f seconds.\n",
2675 seconds);
2677 status = cli_close(cli1, fnum);
2678 if (!NT_STATUS_IS_OK(status)) {
2679 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2680 goto fail;
2683 correct = true;
2685 fail:
2686 cli_close(cli1, fnum);
2687 torture_close_connection(cli1);
2689 fail_nofd:
2691 printf("finished locktest9\n");
2692 return correct;
2696 test whether fnums and tids open on one VC are available on another (a major
2697 security hole)
2699 static bool run_fdpasstest(int dummy)
2701 struct cli_state *cli1, *cli2;
2702 const char *fname = "\\fdpass.tst";
2703 uint16_t fnum1;
2704 char buf[1024];
2705 NTSTATUS status;
2707 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2708 return False;
2710 cli_sockopt(cli1, sockops);
2711 cli_sockopt(cli2, sockops);
2713 printf("starting fdpasstest\n");
2715 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2717 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
2718 &fnum1);
2719 if (!NT_STATUS_IS_OK(status)) {
2720 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2721 return False;
2724 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
2725 13, NULL);
2726 if (!NT_STATUS_IS_OK(status)) {
2727 printf("write failed (%s)\n", nt_errstr(status));
2728 return False;
2731 cli2->vuid = cli1->vuid;
2732 cli_state_set_tid(cli2, cli_state_get_tid(cli1));
2733 cli_setpid(cli2, cli_getpid(cli1));
2735 if (cli_read_old(cli2, fnum1, buf, 0, 13) == 13) {
2736 printf("read succeeded! nasty security hole [%s]\n",
2737 buf);
2738 return False;
2741 cli_close(cli1, fnum1);
2742 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2744 torture_close_connection(cli1);
2745 torture_close_connection(cli2);
2747 printf("finished fdpasstest\n");
2748 return True;
2751 static bool run_fdsesstest(int dummy)
2753 struct cli_state *cli;
2754 uint16 new_vuid;
2755 uint16 saved_vuid;
2756 uint16 new_cnum;
2757 uint16 saved_cnum;
2758 const char *fname = "\\fdsess.tst";
2759 const char *fname1 = "\\fdsess1.tst";
2760 uint16_t fnum1;
2761 uint16_t fnum2;
2762 char buf[1024];
2763 bool ret = True;
2764 NTSTATUS status;
2766 if (!torture_open_connection(&cli, 0))
2767 return False;
2768 cli_sockopt(cli, sockops);
2770 if (!torture_cli_session_setup2(cli, &new_vuid))
2771 return False;
2773 saved_cnum = cli_state_get_tid(cli);
2774 if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, share, "?????", "", 1)))
2775 return False;
2776 new_cnum = cli_state_get_tid(cli);
2777 cli_state_set_tid(cli, saved_cnum);
2779 printf("starting fdsesstest\n");
2781 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2782 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2784 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2785 if (!NT_STATUS_IS_OK(status)) {
2786 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2787 return False;
2790 status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
2791 NULL);
2792 if (!NT_STATUS_IS_OK(status)) {
2793 printf("write failed (%s)\n", nt_errstr(status));
2794 return False;
2797 saved_vuid = cli->vuid;
2798 cli->vuid = new_vuid;
2800 if (cli_read_old(cli, fnum1, buf, 0, 13) == 13) {
2801 printf("read succeeded with different vuid! nasty security hole [%s]\n",
2802 buf);
2803 ret = False;
2805 /* Try to open a file with different vuid, samba cnum. */
2806 if (NT_STATUS_IS_OK(cli_open(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
2807 printf("create with different vuid, same cnum succeeded.\n");
2808 cli_close(cli, fnum2);
2809 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2810 } else {
2811 printf("create with different vuid, same cnum failed.\n");
2812 printf("This will cause problems with service clients.\n");
2813 ret = False;
2816 cli->vuid = saved_vuid;
2818 /* Try with same vuid, different cnum. */
2819 cli_state_set_tid(cli, new_cnum);
2821 if (cli_read_old(cli, fnum1, buf, 0, 13) == 13) {
2822 printf("read succeeded with different cnum![%s]\n",
2823 buf);
2824 ret = False;
2827 cli_state_set_tid(cli, saved_cnum);
2828 cli_close(cli, fnum1);
2829 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2831 torture_close_connection(cli);
2833 printf("finished fdsesstest\n");
2834 return ret;
2838 This test checks that
2840 1) the server does not allow an unlink on a file that is open
2842 static bool run_unlinktest(int dummy)
2844 struct cli_state *cli;
2845 const char *fname = "\\unlink.tst";
2846 uint16_t fnum;
2847 bool correct = True;
2848 NTSTATUS status;
2850 if (!torture_open_connection(&cli, 0)) {
2851 return False;
2854 cli_sockopt(cli, sockops);
2856 printf("starting unlink test\n");
2858 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2860 cli_setpid(cli, 1);
2862 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2863 if (!NT_STATUS_IS_OK(status)) {
2864 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2865 return False;
2868 status = cli_unlink(cli, fname,
2869 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2870 if (NT_STATUS_IS_OK(status)) {
2871 printf("error: server allowed unlink on an open file\n");
2872 correct = False;
2873 } else {
2874 correct = check_error(__LINE__, cli, ERRDOS, ERRbadshare,
2875 NT_STATUS_SHARING_VIOLATION);
2878 cli_close(cli, fnum);
2879 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2881 if (!torture_close_connection(cli)) {
2882 correct = False;
2885 printf("unlink test finished\n");
2887 return correct;
2892 test how many open files this server supports on the one socket
2894 static bool run_maxfidtest(int dummy)
2896 struct cli_state *cli;
2897 fstring fname;
2898 uint16_t fnums[0x11000];
2899 int i;
2900 int retries=4;
2901 bool correct = True;
2902 NTSTATUS status;
2904 cli = current_cli;
2906 if (retries <= 0) {
2907 printf("failed to connect\n");
2908 return False;
2911 cli_sockopt(cli, sockops);
2913 for (i=0; i<0x11000; i++) {
2914 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2915 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
2916 &fnums[i]);
2917 if (!NT_STATUS_IS_OK(status)) {
2918 printf("open of %s failed (%s)\n",
2919 fname, nt_errstr(status));
2920 printf("maximum fnum is %d\n", i);
2921 break;
2923 printf("%6d\r", i);
2925 printf("%6d\n", i);
2926 i--;
2928 printf("cleaning up\n");
2929 for (;i>=0;i--) {
2930 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2931 cli_close(cli, fnums[i]);
2933 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2934 if (!NT_STATUS_IS_OK(status)) {
2935 printf("unlink of %s failed (%s)\n",
2936 fname, nt_errstr(status));
2937 correct = False;
2939 printf("%6d\r", i);
2941 printf("%6d\n", 0);
2943 printf("maxfid test finished\n");
2944 if (!torture_close_connection(cli)) {
2945 correct = False;
2947 return correct;
2950 /* generate a random buffer */
2951 static void rand_buf(char *buf, int len)
2953 while (len--) {
2954 *buf = (char)sys_random();
2955 buf++;
2959 /* send smb negprot commands, not reading the response */
2960 static bool run_negprot_nowait(int dummy)
2962 struct tevent_context *ev;
2963 int i;
2964 struct cli_state *cli;
2965 bool correct = True;
2967 printf("starting negprot nowait test\n");
2969 ev = tevent_context_init(talloc_tos());
2970 if (ev == NULL) {
2971 return false;
2974 if (!(cli = open_nbt_connection())) {
2975 TALLOC_FREE(ev);
2976 return False;
2979 for (i=0;i<50000;i++) {
2980 struct tevent_req *req;
2982 req = cli_negprot_send(ev, ev, cli);
2983 if (req == NULL) {
2984 TALLOC_FREE(ev);
2985 return false;
2987 if (!tevent_req_poll(req, ev)) {
2988 d_fprintf(stderr, "tevent_req_poll failed: %s\n",
2989 strerror(errno));
2990 TALLOC_FREE(ev);
2991 return false;
2993 TALLOC_FREE(req);
2996 if (torture_close_connection(cli)) {
2997 correct = False;
3000 printf("finished negprot nowait test\n");
3002 return correct;
3005 /* send smb negprot commands, not reading the response */
3006 static bool run_bad_nbt_session(int dummy)
3008 struct nmb_name called, calling;
3009 struct sockaddr_storage ss;
3010 NTSTATUS status;
3011 int fd;
3012 bool ret;
3014 printf("starting bad nbt session test\n");
3016 make_nmb_name(&calling, myname, 0x0);
3017 make_nmb_name(&called , host, 0x20);
3019 if (!resolve_name(host, &ss, 0x20, true)) {
3020 d_fprintf(stderr, "Could not resolve name %s\n", host);
3021 return false;
3024 status = open_socket_out(&ss, 139, 10000, &fd);
3025 if (!NT_STATUS_IS_OK(status)) {
3026 d_fprintf(stderr, "open_socket_out failed: %s\n",
3027 nt_errstr(status));
3028 return false;
3031 ret = cli_bad_session_request(fd, &calling, &called);
3032 close(fd);
3033 if (!ret) {
3034 d_fprintf(stderr, "open_socket_out failed: %s\n",
3035 nt_errstr(status));
3036 return false;
3039 printf("finished bad nbt session test\n");
3040 return true;
3043 /* send random IPC commands */
3044 static bool run_randomipc(int dummy)
3046 char *rparam = NULL;
3047 char *rdata = NULL;
3048 unsigned int rdrcnt,rprcnt;
3049 char param[1024];
3050 int api, param_len, i;
3051 struct cli_state *cli;
3052 bool correct = True;
3053 int count = 50000;
3055 printf("starting random ipc test\n");
3057 if (!torture_open_connection(&cli, 0)) {
3058 return False;
3061 for (i=0;i<count;i++) {
3062 api = sys_random() % 500;
3063 param_len = (sys_random() % 64);
3065 rand_buf(param, param_len);
3067 SSVAL(param,0,api);
3069 cli_api(cli,
3070 param, param_len, 8,
3071 NULL, 0, BUFFER_SIZE,
3072 &rparam, &rprcnt,
3073 &rdata, &rdrcnt);
3074 if (i % 100 == 0) {
3075 printf("%d/%d\r", i,count);
3078 printf("%d/%d\n", i, count);
3080 if (!torture_close_connection(cli)) {
3081 correct = False;
3084 printf("finished random ipc test\n");
3086 return correct;
3091 static void browse_callback(const char *sname, uint32 stype,
3092 const char *comment, void *state)
3094 printf("\t%20.20s %08x %s\n", sname, stype, comment);
3100 This test checks the browse list code
3103 static bool run_browsetest(int dummy)
3105 static struct cli_state *cli;
3106 bool correct = True;
3108 printf("starting browse test\n");
3110 if (!torture_open_connection(&cli, 0)) {
3111 return False;
3114 printf("domain list:\n");
3115 cli_NetServerEnum(cli, cli->server_domain,
3116 SV_TYPE_DOMAIN_ENUM,
3117 browse_callback, NULL);
3119 printf("machine list:\n");
3120 cli_NetServerEnum(cli, cli->server_domain,
3121 SV_TYPE_ALL,
3122 browse_callback, NULL);
3124 if (!torture_close_connection(cli)) {
3125 correct = False;
3128 printf("browse test finished\n");
3130 return correct;
3136 This checks how the getatr calls works
3138 static bool run_attrtest(int dummy)
3140 struct cli_state *cli;
3141 uint16_t fnum;
3142 time_t t, t2;
3143 const char *fname = "\\attrib123456789.tst";
3144 bool correct = True;
3145 NTSTATUS status;
3147 printf("starting attrib test\n");
3149 if (!torture_open_connection(&cli, 0)) {
3150 return False;
3153 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3154 cli_open(cli, fname,
3155 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3156 cli_close(cli, fnum);
3158 status = cli_getatr(cli, fname, NULL, NULL, &t);
3159 if (!NT_STATUS_IS_OK(status)) {
3160 printf("getatr failed (%s)\n", nt_errstr(status));
3161 correct = False;
3164 if (abs(t - time(NULL)) > 60*60*24*10) {
3165 printf("ERROR: SMBgetatr bug. time is %s",
3166 ctime(&t));
3167 t = time(NULL);
3168 correct = True;
3171 t2 = t-60*60*24; /* 1 day ago */
3173 status = cli_setatr(cli, fname, 0, t2);
3174 if (!NT_STATUS_IS_OK(status)) {
3175 printf("setatr failed (%s)\n", nt_errstr(status));
3176 correct = True;
3179 status = cli_getatr(cli, fname, NULL, NULL, &t);
3180 if (!NT_STATUS_IS_OK(status)) {
3181 printf("getatr failed (%s)\n", nt_errstr(status));
3182 correct = True;
3185 if (t != t2) {
3186 printf("ERROR: getatr/setatr bug. times are\n%s",
3187 ctime(&t));
3188 printf("%s", ctime(&t2));
3189 correct = True;
3192 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3194 if (!torture_close_connection(cli)) {
3195 correct = False;
3198 printf("attrib test finished\n");
3200 return correct;
3205 This checks a couple of trans2 calls
3207 static bool run_trans2test(int dummy)
3209 struct cli_state *cli;
3210 uint16_t fnum;
3211 SMB_OFF_T size;
3212 time_t c_time, a_time, m_time;
3213 struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
3214 const char *fname = "\\trans2.tst";
3215 const char *dname = "\\trans2";
3216 const char *fname2 = "\\trans2\\trans2.tst";
3217 char *pname;
3218 bool correct = True;
3219 NTSTATUS status;
3220 uint32_t fs_attr;
3222 printf("starting trans2 test\n");
3224 if (!torture_open_connection(&cli, 0)) {
3225 return False;
3228 status = cli_get_fs_attr_info(cli, &fs_attr);
3229 if (!NT_STATUS_IS_OK(status)) {
3230 printf("ERROR: cli_get_fs_attr_info returned %s\n",
3231 nt_errstr(status));
3232 correct = false;
3235 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3236 cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3237 status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
3238 &a_time_ts, &w_time_ts, &m_time_ts, NULL);
3239 if (!NT_STATUS_IS_OK(status)) {
3240 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
3241 correct = False;
3244 status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
3245 if (!NT_STATUS_IS_OK(status)) {
3246 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
3247 correct = False;
3250 if (strcmp(pname, fname)) {
3251 printf("qfilename gave different name? [%s] [%s]\n",
3252 fname, pname);
3253 correct = False;
3256 cli_close(cli, fnum);
3258 sleep(2);
3260 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3261 status = cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
3262 &fnum);
3263 if (!NT_STATUS_IS_OK(status)) {
3264 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3265 return False;
3267 cli_close(cli, fnum);
3269 status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
3270 NULL);
3271 if (!NT_STATUS_IS_OK(status)) {
3272 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
3273 correct = False;
3274 } else {
3275 if (c_time != m_time) {
3276 printf("create time=%s", ctime(&c_time));
3277 printf("modify time=%s", ctime(&m_time));
3278 printf("This system appears to have sticky create times\n");
3280 if (a_time % (60*60) == 0) {
3281 printf("access time=%s", ctime(&a_time));
3282 printf("This system appears to set a midnight access time\n");
3283 correct = False;
3286 if (abs(m_time - time(NULL)) > 60*60*24*7) {
3287 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
3288 correct = False;
3293 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3294 cli_open(cli, fname,
3295 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3296 cli_close(cli, fnum);
3297 status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
3298 &m_time_ts, &size, NULL, NULL);
3299 if (!NT_STATUS_IS_OK(status)) {
3300 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3301 correct = False;
3302 } else {
3303 if (w_time_ts.tv_sec < 60*60*24*2) {
3304 printf("write time=%s", ctime(&w_time_ts.tv_sec));
3305 printf("This system appears to set a initial 0 write time\n");
3306 correct = False;
3310 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3313 /* check if the server updates the directory modification time
3314 when creating a new file */
3315 status = cli_mkdir(cli, dname);
3316 if (!NT_STATUS_IS_OK(status)) {
3317 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
3318 correct = False;
3320 sleep(3);
3321 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3322 &w_time_ts, &m_time_ts, &size, NULL, NULL);
3323 if (!NT_STATUS_IS_OK(status)) {
3324 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3325 correct = False;
3328 cli_open(cli, fname2,
3329 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3330 cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
3331 cli_close(cli, fnum);
3332 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3333 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
3334 if (!NT_STATUS_IS_OK(status)) {
3335 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3336 correct = False;
3337 } else {
3338 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
3339 == 0) {
3340 printf("This system does not update directory modification times\n");
3341 correct = False;
3344 cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3345 cli_rmdir(cli, dname);
3347 if (!torture_close_connection(cli)) {
3348 correct = False;
3351 printf("trans2 test finished\n");
3353 return correct;
3357 This checks new W2K calls.
3360 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
3362 uint8_t *buf = NULL;
3363 uint32 len;
3364 NTSTATUS status;
3366 status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
3367 pcli->max_xmit, NULL, &buf, &len);
3368 if (!NT_STATUS_IS_OK(status)) {
3369 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
3370 nt_errstr(status));
3371 } else {
3372 printf("qfileinfo: level %d, len = %u\n", level, len);
3373 dump_data(0, (uint8 *)buf, len);
3374 printf("\n");
3376 TALLOC_FREE(buf);
3377 return status;
3380 static bool run_w2ktest(int dummy)
3382 struct cli_state *cli;
3383 uint16_t fnum;
3384 const char *fname = "\\w2ktest\\w2k.tst";
3385 int level;
3386 bool correct = True;
3388 printf("starting w2k test\n");
3390 if (!torture_open_connection(&cli, 0)) {
3391 return False;
3394 cli_open(cli, fname,
3395 O_RDWR | O_CREAT , DENY_NONE, &fnum);
3397 for (level = 1004; level < 1040; level++) {
3398 new_trans(cli, fnum, level);
3401 cli_close(cli, fnum);
3403 if (!torture_close_connection(cli)) {
3404 correct = False;
3407 printf("w2k test finished\n");
3409 return correct;
3414 this is a harness for some oplock tests
3416 static bool run_oplock1(int dummy)
3418 struct cli_state *cli1;
3419 const char *fname = "\\lockt1.lck";
3420 uint16_t fnum1;
3421 bool correct = True;
3422 NTSTATUS status;
3424 printf("starting oplock test 1\n");
3426 if (!torture_open_connection(&cli1, 0)) {
3427 return False;
3430 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3432 cli_sockopt(cli1, sockops);
3434 cli1->use_oplocks = True;
3436 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3437 &fnum1);
3438 if (!NT_STATUS_IS_OK(status)) {
3439 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3440 return False;
3443 cli1->use_oplocks = False;
3445 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3446 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3448 status = cli_close(cli1, fnum1);
3449 if (!NT_STATUS_IS_OK(status)) {
3450 printf("close2 failed (%s)\n", nt_errstr(status));
3451 return False;
3454 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3455 if (!NT_STATUS_IS_OK(status)) {
3456 printf("unlink failed (%s)\n", nt_errstr(status));
3457 return False;
3460 if (!torture_close_connection(cli1)) {
3461 correct = False;
3464 printf("finished oplock test 1\n");
3466 return correct;
3469 static bool run_oplock2(int dummy)
3471 struct cli_state *cli1, *cli2;
3472 const char *fname = "\\lockt2.lck";
3473 uint16_t fnum1, fnum2;
3474 int saved_use_oplocks = use_oplocks;
3475 char buf[4];
3476 bool correct = True;
3477 volatile bool *shared_correct;
3478 NTSTATUS status;
3480 shared_correct = (volatile bool *)shm_setup(sizeof(bool));
3481 *shared_correct = True;
3483 use_level_II_oplocks = True;
3484 use_oplocks = True;
3486 printf("starting oplock test 2\n");
3488 if (!torture_open_connection(&cli1, 0)) {
3489 use_level_II_oplocks = False;
3490 use_oplocks = saved_use_oplocks;
3491 return False;
3494 cli1->use_oplocks = True;
3495 cli1->use_level_II_oplocks = True;
3497 if (!torture_open_connection(&cli2, 1)) {
3498 use_level_II_oplocks = False;
3499 use_oplocks = saved_use_oplocks;
3500 return False;
3503 cli2->use_oplocks = True;
3504 cli2->use_level_II_oplocks = True;
3506 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3508 cli_sockopt(cli1, sockops);
3509 cli_sockopt(cli2, sockops);
3511 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3512 &fnum1);
3513 if (!NT_STATUS_IS_OK(status)) {
3514 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3515 return False;
3518 /* Don't need the globals any more. */
3519 use_level_II_oplocks = False;
3520 use_oplocks = saved_use_oplocks;
3522 if (fork() == 0) {
3523 /* Child code */
3524 status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
3525 if (!NT_STATUS_IS_OK(status)) {
3526 printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
3527 *shared_correct = False;
3528 exit(0);
3531 sleep(2);
3533 status = cli_close(cli2, fnum2);
3534 if (!NT_STATUS_IS_OK(status)) {
3535 printf("close2 failed (%s)\n", nt_errstr(status));
3536 *shared_correct = False;
3539 exit(0);
3542 sleep(2);
3544 /* Ensure cli1 processes the break. Empty file should always return 0
3545 * bytes. */
3547 if (cli_read_old(cli1, fnum1, buf, 0, 4) != 0) {
3548 printf("read on fnum1 failed (%s)\n", cli_errstr(cli1));
3549 correct = False;
3552 /* Should now be at level II. */
3553 /* Test if sending a write locks causes a break to none. */
3554 status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
3555 if (!NT_STATUS_IS_OK(status)) {
3556 printf("lock failed (%s)\n", nt_errstr(status));
3557 correct = False;
3560 cli_unlock(cli1, fnum1, 0, 4);
3562 sleep(2);
3564 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
3565 if (!NT_STATUS_IS_OK(status)) {
3566 printf("lock failed (%s)\n", nt_errstr(status));
3567 correct = False;
3570 cli_unlock(cli1, fnum1, 0, 4);
3572 sleep(2);
3574 cli_read_old(cli1, fnum1, buf, 0, 4);
3576 status = cli_close(cli1, fnum1);
3577 if (!NT_STATUS_IS_OK(status)) {
3578 printf("close1 failed (%s)\n", nt_errstr(status));
3579 correct = False;
3582 sleep(4);
3584 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3585 if (!NT_STATUS_IS_OK(status)) {
3586 printf("unlink failed (%s)\n", nt_errstr(status));
3587 correct = False;
3590 if (!torture_close_connection(cli1)) {
3591 correct = False;
3594 if (!*shared_correct) {
3595 correct = False;
3598 printf("finished oplock test 2\n");
3600 return correct;
3603 struct oplock4_state {
3604 struct tevent_context *ev;
3605 struct cli_state *cli;
3606 bool *got_break;
3607 uint16_t *fnum2;
3610 static void oplock4_got_break(struct tevent_req *req);
3611 static void oplock4_got_open(struct tevent_req *req);
3613 static bool run_oplock4(int dummy)
3615 struct tevent_context *ev;
3616 struct cli_state *cli1, *cli2;
3617 struct tevent_req *oplock_req, *open_req;
3618 const char *fname = "\\lockt4.lck";
3619 const char *fname_ln = "\\lockt4_ln.lck";
3620 uint16_t fnum1, fnum2;
3621 int saved_use_oplocks = use_oplocks;
3622 NTSTATUS status;
3623 bool correct = true;
3625 bool got_break;
3627 struct oplock4_state *state;
3629 printf("starting oplock test 4\n");
3631 if (!torture_open_connection(&cli1, 0)) {
3632 use_level_II_oplocks = false;
3633 use_oplocks = saved_use_oplocks;
3634 return false;
3637 if (!torture_open_connection(&cli2, 1)) {
3638 use_level_II_oplocks = false;
3639 use_oplocks = saved_use_oplocks;
3640 return false;
3643 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3644 cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3646 cli_sockopt(cli1, sockops);
3647 cli_sockopt(cli2, sockops);
3649 /* Create the file. */
3650 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3651 &fnum1);
3652 if (!NT_STATUS_IS_OK(status)) {
3653 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3654 return false;
3657 status = cli_close(cli1, fnum1);
3658 if (!NT_STATUS_IS_OK(status)) {
3659 printf("close1 failed (%s)\n", nt_errstr(status));
3660 return false;
3663 /* Now create a hardlink. */
3664 status = cli_nt_hardlink(cli1, fname, fname_ln);
3665 if (!NT_STATUS_IS_OK(status)) {
3666 printf("nt hardlink failed (%s)\n", nt_errstr(status));
3667 return false;
3670 /* Prove that opening hardlinks cause deny modes to conflict. */
3671 status = cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
3672 if (!NT_STATUS_IS_OK(status)) {
3673 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3674 return false;
3677 status = cli_open(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
3678 if (NT_STATUS_IS_OK(status)) {
3679 printf("open of %s succeeded - should fail with sharing violation.\n",
3680 fname_ln);
3681 return false;
3684 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3685 printf("open of %s should fail with sharing violation. Got %s\n",
3686 fname_ln, nt_errstr(status));
3687 return false;
3690 status = cli_close(cli1, fnum1);
3691 if (!NT_STATUS_IS_OK(status)) {
3692 printf("close1 failed (%s)\n", nt_errstr(status));
3693 return false;
3696 cli1->use_oplocks = true;
3697 cli1->use_level_II_oplocks = true;
3699 cli2->use_oplocks = true;
3700 cli2->use_level_II_oplocks = true;
3702 status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3703 if (!NT_STATUS_IS_OK(status)) {
3704 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3705 return false;
3708 ev = tevent_context_init(talloc_tos());
3709 if (ev == NULL) {
3710 printf("tevent_req_create failed\n");
3711 return false;
3714 state = talloc(ev, struct oplock4_state);
3715 if (state == NULL) {
3716 printf("talloc failed\n");
3717 return false;
3719 state->ev = ev;
3720 state->cli = cli1;
3721 state->got_break = &got_break;
3722 state->fnum2 = &fnum2;
3724 oplock_req = cli_smb_oplock_break_waiter_send(
3725 talloc_tos(), ev, cli1);
3726 if (oplock_req == NULL) {
3727 printf("cli_smb_oplock_break_waiter_send failed\n");
3728 return false;
3730 tevent_req_set_callback(oplock_req, oplock4_got_break, state);
3732 open_req = cli_open_send(
3733 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
3734 if (oplock_req == NULL) {
3735 printf("cli_open_send failed\n");
3736 return false;
3738 tevent_req_set_callback(open_req, oplock4_got_open, state);
3740 got_break = false;
3741 fnum2 = 0xffff;
3743 while (!got_break || fnum2 == 0xffff) {
3744 int ret;
3745 ret = tevent_loop_once(ev);
3746 if (ret == -1) {
3747 printf("tevent_loop_once failed: %s\n",
3748 strerror(errno));
3749 return false;
3753 status = cli_close(cli2, fnum2);
3754 if (!NT_STATUS_IS_OK(status)) {
3755 printf("close2 failed (%s)\n", nt_errstr(status));
3756 correct = false;
3759 status = cli_close(cli1, fnum1);
3760 if (!NT_STATUS_IS_OK(status)) {
3761 printf("close1 failed (%s)\n", nt_errstr(status));
3762 correct = false;
3765 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3766 if (!NT_STATUS_IS_OK(status)) {
3767 printf("unlink failed (%s)\n", nt_errstr(status));
3768 correct = false;
3771 status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3772 if (!NT_STATUS_IS_OK(status)) {
3773 printf("unlink failed (%s)\n", nt_errstr(status));
3774 correct = false;
3777 if (!torture_close_connection(cli1)) {
3778 correct = false;
3781 if (!got_break) {
3782 correct = false;
3785 printf("finished oplock test 4\n");
3787 return correct;
3790 static void oplock4_got_break(struct tevent_req *req)
3792 struct oplock4_state *state = tevent_req_callback_data(
3793 req, struct oplock4_state);
3794 uint16_t fnum;
3795 uint8_t level;
3796 NTSTATUS status;
3798 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
3799 TALLOC_FREE(req);
3800 if (!NT_STATUS_IS_OK(status)) {
3801 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
3802 nt_errstr(status));
3803 return;
3805 *state->got_break = true;
3807 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
3808 NO_OPLOCK);
3809 if (req == NULL) {
3810 printf("cli_oplock_ack_send failed\n");
3811 return;
3815 static void oplock4_got_open(struct tevent_req *req)
3817 struct oplock4_state *state = tevent_req_callback_data(
3818 req, struct oplock4_state);
3819 NTSTATUS status;
3821 status = cli_open_recv(req, state->fnum2);
3822 if (!NT_STATUS_IS_OK(status)) {
3823 printf("cli_open_recv returned %s\n", nt_errstr(status));
3824 *state->fnum2 = 0xffff;
3829 Test delete on close semantics.
3831 static bool run_deletetest(int dummy)
3833 struct cli_state *cli1 = NULL;
3834 struct cli_state *cli2 = NULL;
3835 const char *fname = "\\delete.file";
3836 uint16_t fnum1 = (uint16_t)-1;
3837 uint16_t fnum2 = (uint16_t)-1;
3838 bool correct = True;
3839 NTSTATUS status;
3841 printf("starting delete test\n");
3843 if (!torture_open_connection(&cli1, 0)) {
3844 return False;
3847 cli_sockopt(cli1, sockops);
3849 /* Test 1 - this should delete the file on close. */
3851 cli_setatr(cli1, fname, 0, 0);
3852 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3854 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
3855 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
3856 FILE_DELETE_ON_CLOSE, 0, &fnum1);
3857 if (!NT_STATUS_IS_OK(status)) {
3858 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
3859 correct = False;
3860 goto fail;
3863 status = cli_close(cli1, fnum1);
3864 if (!NT_STATUS_IS_OK(status)) {
3865 printf("[1] close failed (%s)\n", nt_errstr(status));
3866 correct = False;
3867 goto fail;
3870 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1))) {
3871 printf("[1] open of %s succeeded (should fail)\n", fname);
3872 correct = False;
3873 goto fail;
3876 printf("first delete on close test succeeded.\n");
3878 /* Test 2 - this should delete the file on close. */
3880 cli_setatr(cli1, fname, 0, 0);
3881 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3883 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3884 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
3885 FILE_OVERWRITE_IF, 0, 0, &fnum1);
3886 if (!NT_STATUS_IS_OK(status)) {
3887 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
3888 correct = False;
3889 goto fail;
3892 status = cli_nt_delete_on_close(cli1, fnum1, true);
3893 if (!NT_STATUS_IS_OK(status)) {
3894 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
3895 correct = False;
3896 goto fail;
3899 status = cli_close(cli1, fnum1);
3900 if (!NT_STATUS_IS_OK(status)) {
3901 printf("[2] close failed (%s)\n", nt_errstr(status));
3902 correct = False;
3903 goto fail;
3906 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3907 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
3908 status = cli_close(cli1, fnum1);
3909 if (!NT_STATUS_IS_OK(status)) {
3910 printf("[2] close failed (%s)\n", nt_errstr(status));
3911 correct = False;
3912 goto fail;
3914 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3915 } else
3916 printf("second delete on close test succeeded.\n");
3918 /* Test 3 - ... */
3919 cli_setatr(cli1, fname, 0, 0);
3920 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3922 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3923 FILE_ATTRIBUTE_NORMAL,
3924 FILE_SHARE_READ|FILE_SHARE_WRITE,
3925 FILE_OVERWRITE_IF, 0, 0, &fnum1);
3926 if (!NT_STATUS_IS_OK(status)) {
3927 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
3928 correct = False;
3929 goto fail;
3932 /* This should fail with a sharing violation - open for delete is only compatible
3933 with SHARE_DELETE. */
3935 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
3936 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, 0, &fnum2))) {
3937 printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
3938 correct = False;
3939 goto fail;
3942 /* This should succeed. */
3943 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3944 FILE_ATTRIBUTE_NORMAL,
3945 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3946 FILE_OPEN, 0, 0, &fnum2);
3947 if (!NT_STATUS_IS_OK(status)) {
3948 printf("[3] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
3949 correct = False;
3950 goto fail;
3953 status = cli_nt_delete_on_close(cli1, fnum1, true);
3954 if (!NT_STATUS_IS_OK(status)) {
3955 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
3956 correct = False;
3957 goto fail;
3960 status = cli_close(cli1, fnum1);
3961 if (!NT_STATUS_IS_OK(status)) {
3962 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
3963 correct = False;
3964 goto fail;
3967 status = cli_close(cli1, fnum2);
3968 if (!NT_STATUS_IS_OK(status)) {
3969 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
3970 correct = False;
3971 goto fail;
3974 /* This should fail - file should no longer be there. */
3976 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3977 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
3978 status = cli_close(cli1, fnum1);
3979 if (!NT_STATUS_IS_OK(status)) {
3980 printf("[3] close failed (%s)\n", nt_errstr(status));
3982 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3983 correct = False;
3984 goto fail;
3985 } else
3986 printf("third delete on close test succeeded.\n");
3988 /* Test 4 ... */
3989 cli_setatr(cli1, fname, 0, 0);
3990 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3992 status = cli_ntcreate(cli1, fname, 0,
3993 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
3994 FILE_ATTRIBUTE_NORMAL,
3995 FILE_SHARE_READ|FILE_SHARE_WRITE,
3996 FILE_OVERWRITE_IF, 0, 0, &fnum1);
3997 if (!NT_STATUS_IS_OK(status)) {
3998 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
3999 correct = False;
4000 goto fail;
4003 /* This should succeed. */
4004 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4005 FILE_ATTRIBUTE_NORMAL,
4006 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4007 FILE_OPEN, 0, 0, &fnum2);
4008 if (!NT_STATUS_IS_OK(status)) {
4009 printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
4010 correct = False;
4011 goto fail;
4014 status = cli_close(cli1, fnum2);
4015 if (!NT_STATUS_IS_OK(status)) {
4016 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
4017 correct = False;
4018 goto fail;
4021 status = cli_nt_delete_on_close(cli1, fnum1, true);
4022 if (!NT_STATUS_IS_OK(status)) {
4023 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
4024 correct = False;
4025 goto fail;
4028 /* This should fail - no more opens once delete on close set. */
4029 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4030 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4031 FILE_OPEN, 0, 0, &fnum2))) {
4032 printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
4033 correct = False;
4034 goto fail;
4035 } else
4036 printf("fourth delete on close test succeeded.\n");
4038 status = cli_close(cli1, fnum1);
4039 if (!NT_STATUS_IS_OK(status)) {
4040 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
4041 correct = False;
4042 goto fail;
4045 /* Test 5 ... */
4046 cli_setatr(cli1, fname, 0, 0);
4047 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4049 status = cli_open(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
4050 if (!NT_STATUS_IS_OK(status)) {
4051 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4052 correct = False;
4053 goto fail;
4056 /* This should fail - only allowed on NT opens with DELETE access. */
4058 if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4059 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
4060 correct = False;
4061 goto fail;
4064 status = cli_close(cli1, fnum1);
4065 if (!NT_STATUS_IS_OK(status)) {
4066 printf("[5] close - 2 failed (%s)\n", nt_errstr(status));
4067 correct = False;
4068 goto fail;
4071 printf("fifth delete on close test succeeded.\n");
4073 /* Test 6 ... */
4074 cli_setatr(cli1, fname, 0, 0);
4075 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4077 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4078 FILE_ATTRIBUTE_NORMAL,
4079 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4080 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4081 if (!NT_STATUS_IS_OK(status)) {
4082 printf("[6] open of %s failed (%s)\n", fname,
4083 nt_errstr(status));
4084 correct = False;
4085 goto fail;
4088 /* This should fail - only allowed on NT opens with DELETE access. */
4090 if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4091 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
4092 correct = False;
4093 goto fail;
4096 status = cli_close(cli1, fnum1);
4097 if (!NT_STATUS_IS_OK(status)) {
4098 printf("[6] close - 2 failed (%s)\n", nt_errstr(status));
4099 correct = False;
4100 goto fail;
4103 printf("sixth delete on close test succeeded.\n");
4105 /* Test 7 ... */
4106 cli_setatr(cli1, fname, 0, 0);
4107 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4109 status = cli_ntcreate(cli1, fname, 0,
4110 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4111 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
4112 0, 0, &fnum1);
4113 if (!NT_STATUS_IS_OK(status)) {
4114 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4115 correct = False;
4116 goto fail;
4119 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4120 printf("[7] setting delete_on_close on file failed !\n");
4121 correct = False;
4122 goto fail;
4125 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, false))) {
4126 printf("[7] unsetting delete_on_close on file failed !\n");
4127 correct = False;
4128 goto fail;
4131 status = cli_close(cli1, fnum1);
4132 if (!NT_STATUS_IS_OK(status)) {
4133 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4134 correct = False;
4135 goto fail;
4138 /* This next open should succeed - we reset the flag. */
4139 status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4140 if (!NT_STATUS_IS_OK(status)) {
4141 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4142 correct = False;
4143 goto fail;
4146 status = cli_close(cli1, fnum1);
4147 if (!NT_STATUS_IS_OK(status)) {
4148 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4149 correct = False;
4150 goto fail;
4153 printf("seventh delete on close test succeeded.\n");
4155 /* Test 7 ... */
4156 cli_setatr(cli1, fname, 0, 0);
4157 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4159 if (!torture_open_connection(&cli2, 1)) {
4160 printf("[8] failed to open second connection.\n");
4161 correct = False;
4162 goto fail;
4165 cli_sockopt(cli1, sockops);
4167 status = cli_ntcreate(cli1, fname, 0,
4168 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4169 FILE_ATTRIBUTE_NORMAL,
4170 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4171 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4172 if (!NT_STATUS_IS_OK(status)) {
4173 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4174 correct = False;
4175 goto fail;
4178 status = cli_ntcreate(cli2, fname, 0,
4179 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4180 FILE_ATTRIBUTE_NORMAL,
4181 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4182 FILE_OPEN, 0, 0, &fnum2);
4183 if (!NT_STATUS_IS_OK(status)) {
4184 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4185 correct = False;
4186 goto fail;
4189 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4190 printf("[8] setting delete_on_close on file failed !\n");
4191 correct = False;
4192 goto fail;
4195 status = cli_close(cli1, fnum1);
4196 if (!NT_STATUS_IS_OK(status)) {
4197 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
4198 correct = False;
4199 goto fail;
4202 status = cli_close(cli2, fnum2);
4203 if (!NT_STATUS_IS_OK(status)) {
4204 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
4205 correct = False;
4206 goto fail;
4209 /* This should fail.. */
4210 status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4211 if (NT_STATUS_IS_OK(status)) {
4212 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
4213 goto fail;
4214 correct = False;
4215 } else
4216 printf("eighth delete on close test succeeded.\n");
4218 /* This should fail - we need to set DELETE_ACCESS. */
4219 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0,FILE_READ_DATA|FILE_WRITE_DATA,
4220 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE, 0, &fnum1))) {
4221 printf("[9] open of %s succeeded should have failed!\n", fname);
4222 correct = False;
4223 goto fail;
4226 printf("ninth delete on close test succeeded.\n");
4228 status = cli_ntcreate(cli1, fname, 0,
4229 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4230 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4231 FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
4232 0, &fnum1);
4233 if (!NT_STATUS_IS_OK(status)) {
4234 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
4235 correct = False;
4236 goto fail;
4239 /* This should delete the file. */
4240 status = cli_close(cli1, fnum1);
4241 if (!NT_STATUS_IS_OK(status)) {
4242 printf("[10] close failed (%s)\n", nt_errstr(status));
4243 correct = False;
4244 goto fail;
4247 /* This should fail.. */
4248 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
4249 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
4250 goto fail;
4251 correct = False;
4252 } else
4253 printf("tenth delete on close test succeeded.\n");
4255 cli_setatr(cli1, fname, 0, 0);
4256 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4258 /* What error do we get when attempting to open a read-only file with
4259 delete access ? */
4261 /* Create a readonly file. */
4262 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4263 FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
4264 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4265 if (!NT_STATUS_IS_OK(status)) {
4266 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
4267 correct = False;
4268 goto fail;
4271 status = cli_close(cli1, fnum1);
4272 if (!NT_STATUS_IS_OK(status)) {
4273 printf("[11] close failed (%s)\n", nt_errstr(status));
4274 correct = False;
4275 goto fail;
4278 /* Now try open for delete access. */
4279 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES|DELETE_ACCESS,
4280 0, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4281 FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4282 printf("[11] open of %s succeeded should have been denied with ACCESS_DENIED!\n", fname);
4283 cli_close(cli1, fnum1);
4284 goto fail;
4285 correct = False;
4286 } else {
4287 NTSTATUS nterr = cli_nt_error(cli1);
4288 if (!NT_STATUS_EQUAL(nterr,NT_STATUS_ACCESS_DENIED)) {
4289 printf("[11] open of %s should have been denied with ACCESS_DENIED! Got error %s\n", fname, nt_errstr(nterr));
4290 goto fail;
4291 correct = False;
4292 } else {
4293 printf("eleventh delete on close test succeeded.\n");
4297 printf("finished delete test\n");
4299 fail:
4300 /* FIXME: This will crash if we aborted before cli2 got
4301 * intialized, because these functions don't handle
4302 * uninitialized connections. */
4304 if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
4305 if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
4306 cli_setatr(cli1, fname, 0, 0);
4307 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4309 if (cli1 && !torture_close_connection(cli1)) {
4310 correct = False;
4312 if (cli2 && !torture_close_connection(cli2)) {
4313 correct = False;
4315 return correct;
4318 static bool run_deletetest_ln(int dummy)
4320 struct cli_state *cli;
4321 const char *fname = "\\delete1";
4322 const char *fname_ln = "\\delete1_ln";
4323 uint16_t fnum;
4324 uint16_t fnum1;
4325 NTSTATUS status;
4326 bool correct = true;
4327 time_t t;
4329 printf("starting deletetest-ln\n");
4331 if (!torture_open_connection(&cli, 0)) {
4332 return false;
4335 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4336 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4338 cli_sockopt(cli, sockops);
4340 /* Create the file. */
4341 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
4342 if (!NT_STATUS_IS_OK(status)) {
4343 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4344 return false;
4347 status = cli_close(cli, fnum);
4348 if (!NT_STATUS_IS_OK(status)) {
4349 printf("close1 failed (%s)\n", nt_errstr(status));
4350 return false;
4353 /* Now create a hardlink. */
4354 status = cli_nt_hardlink(cli, fname, fname_ln);
4355 if (!NT_STATUS_IS_OK(status)) {
4356 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4357 return false;
4360 /* Open the original file. */
4361 status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
4362 FILE_ATTRIBUTE_NORMAL,
4363 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4364 FILE_OPEN_IF, 0, 0, &fnum);
4365 if (!NT_STATUS_IS_OK(status)) {
4366 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
4367 return false;
4370 /* Unlink the hard link path. */
4371 status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
4372 FILE_ATTRIBUTE_NORMAL,
4373 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4374 FILE_OPEN_IF, 0, 0, &fnum1);
4375 if (!NT_STATUS_IS_OK(status)) {
4376 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
4377 return false;
4379 status = cli_nt_delete_on_close(cli, fnum1, true);
4380 if (!NT_STATUS_IS_OK(status)) {
4381 d_printf("(%s) failed to set delete_on_close %s: %s\n",
4382 __location__, fname_ln, nt_errstr(status));
4383 return false;
4386 status = cli_close(cli, fnum1);
4387 if (!NT_STATUS_IS_OK(status)) {
4388 printf("close %s failed (%s)\n",
4389 fname_ln, nt_errstr(status));
4390 return false;
4393 status = cli_close(cli, fnum);
4394 if (!NT_STATUS_IS_OK(status)) {
4395 printf("close %s failed (%s)\n",
4396 fname, nt_errstr(status));
4397 return false;
4400 /* Ensure the original file is still there. */
4401 status = cli_getatr(cli, fname, NULL, NULL, &t);
4402 if (!NT_STATUS_IS_OK(status)) {
4403 printf("%s getatr on file %s failed (%s)\n",
4404 __location__,
4405 fname,
4406 nt_errstr(status));
4407 correct = False;
4410 /* Ensure the link path is gone. */
4411 status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
4412 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4413 printf("%s, getatr for file %s returned wrong error code %s "
4414 "- should have been deleted\n",
4415 __location__,
4416 fname_ln, nt_errstr(status));
4417 correct = False;
4420 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4421 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4423 if (!torture_close_connection(cli)) {
4424 correct = false;
4427 printf("finished deletetest-ln\n");
4429 return correct;
4433 print out server properties
4435 static bool run_properties(int dummy)
4437 struct cli_state *cli;
4438 bool correct = True;
4440 printf("starting properties test\n");
4442 ZERO_STRUCT(cli);
4444 if (!torture_open_connection(&cli, 0)) {
4445 return False;
4448 cli_sockopt(cli, sockops);
4450 d_printf("Capabilities 0x%08x\n", cli->capabilities);
4452 if (!torture_close_connection(cli)) {
4453 correct = False;
4456 return correct;
4461 /* FIRST_DESIRED_ACCESS 0xf019f */
4462 #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
4463 FILE_READ_EA| /* 0xf */ \
4464 FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
4465 FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
4466 DELETE_ACCESS|READ_CONTROL_ACCESS|\
4467 WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
4468 /* SECOND_DESIRED_ACCESS 0xe0080 */
4469 #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
4470 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4471 WRITE_OWNER_ACCESS /* 0xe0000 */
4473 #if 0
4474 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
4475 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4476 FILE_READ_DATA|\
4477 WRITE_OWNER_ACCESS /* */
4478 #endif
4481 Test ntcreate calls made by xcopy
4483 static bool run_xcopy(int dummy)
4485 static struct cli_state *cli1;
4486 const char *fname = "\\test.txt";
4487 bool correct = True;
4488 uint16_t fnum1, fnum2;
4489 NTSTATUS status;
4491 printf("starting xcopy test\n");
4493 if (!torture_open_connection(&cli1, 0)) {
4494 return False;
4497 status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
4498 FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
4499 FILE_OVERWRITE_IF, 0x4044, 0, &fnum1);
4500 if (!NT_STATUS_IS_OK(status)) {
4501 printf("First open failed - %s\n", nt_errstr(status));
4502 return False;
4505 status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
4506 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4507 FILE_OPEN, 0x200000, 0, &fnum2);
4508 if (!NT_STATUS_IS_OK(status)) {
4509 printf("second open failed - %s\n", nt_errstr(status));
4510 return False;
4513 if (!torture_close_connection(cli1)) {
4514 correct = False;
4517 return correct;
4521 Test rename on files open with share delete and no share delete.
4523 static bool run_rename(int dummy)
4525 static struct cli_state *cli1;
4526 const char *fname = "\\test.txt";
4527 const char *fname1 = "\\test1.txt";
4528 bool correct = True;
4529 uint16_t fnum1;
4530 uint16_t attr;
4531 NTSTATUS status;
4533 printf("starting rename test\n");
4535 if (!torture_open_connection(&cli1, 0)) {
4536 return False;
4539 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4540 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4542 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4543 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
4544 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4545 if (!NT_STATUS_IS_OK(status)) {
4546 printf("First open failed - %s\n", nt_errstr(status));
4547 return False;
4550 status = cli_rename(cli1, fname, fname1);
4551 if (!NT_STATUS_IS_OK(status)) {
4552 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
4553 } else {
4554 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
4555 correct = False;
4558 status = cli_close(cli1, fnum1);
4559 if (!NT_STATUS_IS_OK(status)) {
4560 printf("close - 1 failed (%s)\n", nt_errstr(status));
4561 return False;
4564 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4565 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4566 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4567 #if 0
4568 FILE_SHARE_DELETE|FILE_SHARE_NONE,
4569 #else
4570 FILE_SHARE_DELETE|FILE_SHARE_READ,
4571 #endif
4572 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4573 if (!NT_STATUS_IS_OK(status)) {
4574 printf("Second open failed - %s\n", nt_errstr(status));
4575 return False;
4578 status = cli_rename(cli1, fname, fname1);
4579 if (!NT_STATUS_IS_OK(status)) {
4580 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
4581 correct = False;
4582 } else {
4583 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
4586 status = cli_close(cli1, fnum1);
4587 if (!NT_STATUS_IS_OK(status)) {
4588 printf("close - 2 failed (%s)\n", nt_errstr(status));
4589 return False;
4592 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4593 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4595 status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
4596 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4597 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4598 if (!NT_STATUS_IS_OK(status)) {
4599 printf("Third open failed - %s\n", nt_errstr(status));
4600 return False;
4604 #if 0
4606 uint16_t fnum2;
4608 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
4609 FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4610 printf("Fourth open failed - %s\n", cli_errstr(cli1));
4611 return False;
4613 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum2, true))) {
4614 printf("[8] setting delete_on_close on file failed !\n");
4615 return False;
4618 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
4619 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
4620 return False;
4623 #endif
4625 status = cli_rename(cli1, fname, fname1);
4626 if (!NT_STATUS_IS_OK(status)) {
4627 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
4628 correct = False;
4629 } else {
4630 printf("Third rename succeeded (SHARE_NONE)\n");
4633 status = cli_close(cli1, fnum1);
4634 if (!NT_STATUS_IS_OK(status)) {
4635 printf("close - 3 failed (%s)\n", nt_errstr(status));
4636 return False;
4639 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4640 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4642 /*----*/
4644 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4645 FILE_ATTRIBUTE_NORMAL,
4646 FILE_SHARE_READ | FILE_SHARE_WRITE,
4647 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4648 if (!NT_STATUS_IS_OK(status)) {
4649 printf("Fourth open failed - %s\n", nt_errstr(status));
4650 return False;
4653 status = cli_rename(cli1, fname, fname1);
4654 if (!NT_STATUS_IS_OK(status)) {
4655 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
4656 } else {
4657 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
4658 correct = False;
4661 status = cli_close(cli1, fnum1);
4662 if (!NT_STATUS_IS_OK(status)) {
4663 printf("close - 4 failed (%s)\n", nt_errstr(status));
4664 return False;
4667 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4668 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4670 /*--*/
4672 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4673 FILE_ATTRIBUTE_NORMAL,
4674 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4675 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4676 if (!NT_STATUS_IS_OK(status)) {
4677 printf("Fifth open failed - %s\n", nt_errstr(status));
4678 return False;
4681 status = cli_rename(cli1, fname, fname1);
4682 if (!NT_STATUS_IS_OK(status)) {
4683 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
4684 correct = False;
4685 } else {
4686 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
4690 * Now check if the first name still exists ...
4693 /* if (!NT_STATUS_OP(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4694 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4695 printf("Opening original file after rename of open file fails: %s\n",
4696 cli_errstr(cli1));
4698 else {
4699 printf("Opening original file after rename of open file works ...\n");
4700 (void)cli_close(cli1, fnum2);
4701 } */
4703 /*--*/
4704 status = cli_close(cli1, fnum1);
4705 if (!NT_STATUS_IS_OK(status)) {
4706 printf("close - 5 failed (%s)\n", nt_errstr(status));
4707 return False;
4710 /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
4711 status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
4712 if (!NT_STATUS_IS_OK(status)) {
4713 printf("getatr on file %s failed - %s ! \n",
4714 fname1, nt_errstr(status));
4715 correct = False;
4716 } else {
4717 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
4718 printf("Renamed file %s has wrong attr 0x%x "
4719 "(should be 0x%x)\n",
4720 fname1,
4721 attr,
4722 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
4723 correct = False;
4724 } else {
4725 printf("Renamed file %s has archive bit set\n", fname1);
4729 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4730 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4732 if (!torture_close_connection(cli1)) {
4733 correct = False;
4736 return correct;
4739 static bool run_pipe_number(int dummy)
4741 struct cli_state *cli1;
4742 const char *pipe_name = "\\SPOOLSS";
4743 uint16_t fnum;
4744 int num_pipes = 0;
4745 NTSTATUS status;
4747 printf("starting pipenumber test\n");
4748 if (!torture_open_connection(&cli1, 0)) {
4749 return False;
4752 cli_sockopt(cli1, sockops);
4753 while(1) {
4754 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
4755 FILE_ATTRIBUTE_NORMAL,
4756 FILE_SHARE_READ|FILE_SHARE_WRITE,
4757 FILE_OPEN_IF, 0, 0, &fnum);
4758 if (!NT_STATUS_IS_OK(status)) {
4759 printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
4760 break;
4762 num_pipes++;
4763 printf("\r%6d", num_pipes);
4766 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
4767 torture_close_connection(cli1);
4768 return True;
4772 Test open mode returns on read-only files.
4774 static bool run_opentest(int dummy)
4776 static struct cli_state *cli1;
4777 static struct cli_state *cli2;
4778 const char *fname = "\\readonly.file";
4779 uint16_t fnum1, fnum2;
4780 char buf[20];
4781 SMB_OFF_T fsize;
4782 bool correct = True;
4783 char *tmp_path;
4784 NTSTATUS status;
4786 printf("starting open test\n");
4788 if (!torture_open_connection(&cli1, 0)) {
4789 return False;
4792 cli_setatr(cli1, fname, 0, 0);
4793 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4795 cli_sockopt(cli1, sockops);
4797 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4798 if (!NT_STATUS_IS_OK(status)) {
4799 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4800 return False;
4803 status = cli_close(cli1, fnum1);
4804 if (!NT_STATUS_IS_OK(status)) {
4805 printf("close2 failed (%s)\n", nt_errstr(status));
4806 return False;
4809 status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
4810 if (!NT_STATUS_IS_OK(status)) {
4811 printf("cli_setatr failed (%s)\n", nt_errstr(status));
4812 return False;
4815 status = cli_open(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4816 if (!NT_STATUS_IS_OK(status)) {
4817 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4818 return False;
4821 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
4822 cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4824 if (check_error(__LINE__, cli1, ERRDOS, ERRnoaccess,
4825 NT_STATUS_ACCESS_DENIED)) {
4826 printf("correct error code ERRDOS/ERRnoaccess returned\n");
4829 printf("finished open test 1\n");
4831 cli_close(cli1, fnum1);
4833 /* Now try not readonly and ensure ERRbadshare is returned. */
4835 cli_setatr(cli1, fname, 0, 0);
4837 status = cli_open(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4838 if (!NT_STATUS_IS_OK(status)) {
4839 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4840 return False;
4843 /* This will fail - but the error should be ERRshare. */
4844 cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4846 if (check_error(__LINE__, cli1, ERRDOS, ERRbadshare,
4847 NT_STATUS_SHARING_VIOLATION)) {
4848 printf("correct error code ERRDOS/ERRbadshare returned\n");
4851 status = cli_close(cli1, fnum1);
4852 if (!NT_STATUS_IS_OK(status)) {
4853 printf("close2 failed (%s)\n", nt_errstr(status));
4854 return False;
4857 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4859 printf("finished open test 2\n");
4861 /* Test truncate open disposition on file opened for read. */
4862 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4863 if (!NT_STATUS_IS_OK(status)) {
4864 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
4865 return False;
4868 /* write 20 bytes. */
4870 memset(buf, '\0', 20);
4872 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
4873 if (!NT_STATUS_IS_OK(status)) {
4874 printf("write failed (%s)\n", nt_errstr(status));
4875 correct = False;
4878 status = cli_close(cli1, fnum1);
4879 if (!NT_STATUS_IS_OK(status)) {
4880 printf("(3) close1 failed (%s)\n", nt_errstr(status));
4881 return False;
4884 /* Ensure size == 20. */
4885 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
4886 if (!NT_STATUS_IS_OK(status)) {
4887 printf("(3) getatr failed (%s)\n", nt_errstr(status));
4888 return False;
4891 if (fsize != 20) {
4892 printf("(3) file size != 20\n");
4893 return False;
4896 /* Now test if we can truncate a file opened for readonly. */
4897 status = cli_open(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
4898 if (!NT_STATUS_IS_OK(status)) {
4899 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
4900 return False;
4903 status = cli_close(cli1, fnum1);
4904 if (!NT_STATUS_IS_OK(status)) {
4905 printf("close2 failed (%s)\n", nt_errstr(status));
4906 return False;
4909 /* Ensure size == 0. */
4910 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
4911 if (!NT_STATUS_IS_OK(status)) {
4912 printf("(3) getatr failed (%s)\n", nt_errstr(status));
4913 return False;
4916 if (fsize != 0) {
4917 printf("(3) file size != 0\n");
4918 return False;
4920 printf("finished open test 3\n");
4922 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4924 printf("Do ctemp tests\n");
4925 status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
4926 if (!NT_STATUS_IS_OK(status)) {
4927 printf("ctemp failed (%s)\n", nt_errstr(status));
4928 return False;
4931 printf("ctemp gave path %s\n", tmp_path);
4932 status = cli_close(cli1, fnum1);
4933 if (!NT_STATUS_IS_OK(status)) {
4934 printf("close of temp failed (%s)\n", nt_errstr(status));
4937 status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4938 if (!NT_STATUS_IS_OK(status)) {
4939 printf("unlink of temp failed (%s)\n", nt_errstr(status));
4942 /* Test the non-io opens... */
4944 if (!torture_open_connection(&cli2, 1)) {
4945 return False;
4948 cli_setatr(cli2, fname, 0, 0);
4949 cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4951 cli_sockopt(cli2, sockops);
4953 printf("TEST #1 testing 2 non-io opens (no delete)\n");
4954 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
4955 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4956 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4957 if (!NT_STATUS_IS_OK(status)) {
4958 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4959 return False;
4962 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
4963 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4964 FILE_OPEN_IF, 0, 0, &fnum2);
4965 if (!NT_STATUS_IS_OK(status)) {
4966 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4967 return False;
4970 status = cli_close(cli1, fnum1);
4971 if (!NT_STATUS_IS_OK(status)) {
4972 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
4973 return False;
4976 status = cli_close(cli2, fnum2);
4977 if (!NT_STATUS_IS_OK(status)) {
4978 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
4979 return False;
4982 printf("non-io open test #1 passed.\n");
4984 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4986 printf("TEST #2 testing 2 non-io opens (first with delete)\n");
4988 status = cli_ntcreate(cli1, fname, 0,
4989 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
4990 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4991 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4992 if (!NT_STATUS_IS_OK(status)) {
4993 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4994 return False;
4997 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
4998 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4999 FILE_OPEN_IF, 0, 0, &fnum2);
5000 if (!NT_STATUS_IS_OK(status)) {
5001 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5002 return False;
5005 status = cli_close(cli1, fnum1);
5006 if (!NT_STATUS_IS_OK(status)) {
5007 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5008 return False;
5011 status = cli_close(cli2, fnum2);
5012 if (!NT_STATUS_IS_OK(status)) {
5013 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5014 return False;
5017 printf("non-io open test #2 passed.\n");
5019 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5021 printf("TEST #3 testing 2 non-io opens (second with delete)\n");
5023 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5024 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5025 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5026 if (!NT_STATUS_IS_OK(status)) {
5027 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5028 return False;
5031 status = cli_ntcreate(cli2, fname, 0,
5032 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5033 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5034 FILE_OPEN_IF, 0, 0, &fnum2);
5035 if (!NT_STATUS_IS_OK(status)) {
5036 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5037 return False;
5040 status = cli_close(cli1, fnum1);
5041 if (!NT_STATUS_IS_OK(status)) {
5042 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5043 return False;
5046 status = cli_close(cli2, fnum2);
5047 if (!NT_STATUS_IS_OK(status)) {
5048 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5049 return False;
5052 printf("non-io open test #3 passed.\n");
5054 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5056 printf("TEST #4 testing 2 non-io opens (both with delete)\n");
5058 status = cli_ntcreate(cli1, fname, 0,
5059 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5060 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5061 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5062 if (!NT_STATUS_IS_OK(status)) {
5063 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5064 return False;
5067 status = cli_ntcreate(cli2, fname, 0,
5068 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5069 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5070 FILE_OPEN_IF, 0, 0, &fnum2);
5071 if (NT_STATUS_IS_OK(status)) {
5072 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5073 return False;
5076 printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5078 status = cli_close(cli1, fnum1);
5079 if (!NT_STATUS_IS_OK(status)) {
5080 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5081 return False;
5084 printf("non-io open test #4 passed.\n");
5086 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5088 printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
5090 status = cli_ntcreate(cli1, fname, 0,
5091 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5092 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5093 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5094 if (!NT_STATUS_IS_OK(status)) {
5095 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5096 return False;
5099 status = cli_ntcreate(cli2, fname, 0,
5100 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5101 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5102 FILE_OPEN_IF, 0, 0, &fnum2);
5103 if (!NT_STATUS_IS_OK(status)) {
5104 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5105 return False;
5108 status = cli_close(cli1, fnum1);
5109 if (!NT_STATUS_IS_OK(status)) {
5110 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5111 return False;
5114 status = cli_close(cli2, fnum2);
5115 if (!NT_STATUS_IS_OK(status)) {
5116 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5117 return False;
5120 printf("non-io open test #5 passed.\n");
5122 printf("TEST #6 testing 1 non-io open, one io open\n");
5124 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5126 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5127 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5128 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5129 if (!NT_STATUS_IS_OK(status)) {
5130 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5131 return False;
5134 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5135 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
5136 FILE_OPEN_IF, 0, 0, &fnum2);
5137 if (!NT_STATUS_IS_OK(status)) {
5138 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5139 return False;
5142 status = cli_close(cli1, fnum1);
5143 if (!NT_STATUS_IS_OK(status)) {
5144 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5145 return False;
5148 status = cli_close(cli2, fnum2);
5149 if (!NT_STATUS_IS_OK(status)) {
5150 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5151 return False;
5154 printf("non-io open test #6 passed.\n");
5156 printf("TEST #7 testing 1 non-io open, one io open with delete\n");
5158 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5160 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5161 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5162 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5163 if (!NT_STATUS_IS_OK(status)) {
5164 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5165 return False;
5168 status = cli_ntcreate(cli2, fname, 0,
5169 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5170 FILE_ATTRIBUTE_NORMAL,
5171 FILE_SHARE_READ|FILE_SHARE_DELETE,
5172 FILE_OPEN_IF, 0, 0, &fnum2);
5173 if (NT_STATUS_IS_OK(status)) {
5174 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5175 return False;
5178 printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5180 status = cli_close(cli1, fnum1);
5181 if (!NT_STATUS_IS_OK(status)) {
5182 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5183 return False;
5186 printf("non-io open test #7 passed.\n");
5188 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5190 printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
5191 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
5192 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5193 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5194 if (!NT_STATUS_IS_OK(status)) {
5195 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
5196 correct = false;
5197 goto out;
5200 /* Write to ensure we have to update the file time. */
5201 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5202 NULL);
5203 if (!NT_STATUS_IS_OK(status)) {
5204 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
5205 correct = false;
5206 goto out;
5209 status = cli_close(cli1, fnum1);
5210 if (!NT_STATUS_IS_OK(status)) {
5211 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
5212 correct = false;
5215 out:
5217 if (!torture_close_connection(cli1)) {
5218 correct = False;
5220 if (!torture_close_connection(cli2)) {
5221 correct = False;
5224 return correct;
5227 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
5229 uint16 major, minor;
5230 uint32 caplow, caphigh;
5231 NTSTATUS status;
5233 if (!SERVER_HAS_UNIX_CIFS(cli)) {
5234 printf("Server doesn't support UNIX CIFS extensions.\n");
5235 return NT_STATUS_NOT_SUPPORTED;
5238 status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
5239 &caphigh);
5240 if (!NT_STATUS_IS_OK(status)) {
5241 printf("Server didn't return UNIX CIFS extensions: %s\n",
5242 nt_errstr(status));
5243 return status;
5246 status = cli_set_unix_extensions_capabilities(cli, major, minor,
5247 caplow, caphigh);
5248 if (!NT_STATUS_IS_OK(status)) {
5249 printf("Server doesn't support setting UNIX CIFS extensions: "
5250 "%s.\n", nt_errstr(status));
5251 return status;
5254 return NT_STATUS_OK;
5258 Test POSIX open /mkdir calls.
5260 static bool run_simple_posix_open_test(int dummy)
5262 static struct cli_state *cli1;
5263 const char *fname = "posix:file";
5264 const char *hname = "posix:hlink";
5265 const char *sname = "posix:symlink";
5266 const char *dname = "posix:dir";
5267 char buf[10];
5268 char namebuf[11];
5269 uint16_t fnum1 = (uint16_t)-1;
5270 SMB_STRUCT_STAT sbuf;
5271 bool correct = false;
5272 NTSTATUS status;
5274 printf("Starting simple POSIX open test\n");
5276 if (!torture_open_connection(&cli1, 0)) {
5277 return false;
5280 cli_sockopt(cli1, sockops);
5282 status = torture_setup_unix_extensions(cli1);
5283 if (!NT_STATUS_IS_OK(status)) {
5284 return false;
5287 cli_setatr(cli1, fname, 0, 0);
5288 cli_posix_unlink(cli1, fname);
5289 cli_setatr(cli1, dname, 0, 0);
5290 cli_posix_rmdir(cli1, dname);
5291 cli_setatr(cli1, hname, 0, 0);
5292 cli_posix_unlink(cli1, hname);
5293 cli_setatr(cli1, sname, 0, 0);
5294 cli_posix_unlink(cli1, sname);
5296 /* Create a directory. */
5297 status = cli_posix_mkdir(cli1, dname, 0777);
5298 if (!NT_STATUS_IS_OK(status)) {
5299 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
5300 goto out;
5303 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5304 0600, &fnum1);
5305 if (!NT_STATUS_IS_OK(status)) {
5306 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5307 goto out;
5310 /* Test ftruncate - set file size. */
5311 status = cli_ftruncate(cli1, fnum1, 1000);
5312 if (!NT_STATUS_IS_OK(status)) {
5313 printf("ftruncate failed (%s)\n", nt_errstr(status));
5314 goto out;
5317 /* Ensure st_size == 1000 */
5318 status = cli_posix_stat(cli1, fname, &sbuf);
5319 if (!NT_STATUS_IS_OK(status)) {
5320 printf("stat failed (%s)\n", nt_errstr(status));
5321 goto out;
5324 if (sbuf.st_ex_size != 1000) {
5325 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5326 goto out;
5329 /* Test ftruncate - set file size back to zero. */
5330 status = cli_ftruncate(cli1, fnum1, 0);
5331 if (!NT_STATUS_IS_OK(status)) {
5332 printf("ftruncate failed (%s)\n", nt_errstr(status));
5333 goto out;
5336 status = cli_close(cli1, fnum1);
5337 if (!NT_STATUS_IS_OK(status)) {
5338 printf("close failed (%s)\n", nt_errstr(status));
5339 goto out;
5342 /* Now open the file again for read only. */
5343 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5344 if (!NT_STATUS_IS_OK(status)) {
5345 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
5346 goto out;
5349 /* Now unlink while open. */
5350 status = cli_posix_unlink(cli1, fname);
5351 if (!NT_STATUS_IS_OK(status)) {
5352 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5353 goto out;
5356 status = cli_close(cli1, fnum1);
5357 if (!NT_STATUS_IS_OK(status)) {
5358 printf("close(2) failed (%s)\n", nt_errstr(status));
5359 goto out;
5362 /* Ensure the file has gone. */
5363 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5364 if (NT_STATUS_IS_OK(status)) {
5365 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
5366 goto out;
5369 /* Create again to test open with O_TRUNC. */
5370 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
5371 if (!NT_STATUS_IS_OK(status)) {
5372 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5373 goto out;
5376 /* Test ftruncate - set file size. */
5377 status = cli_ftruncate(cli1, fnum1, 1000);
5378 if (!NT_STATUS_IS_OK(status)) {
5379 printf("ftruncate failed (%s)\n", nt_errstr(status));
5380 goto out;
5383 /* Ensure st_size == 1000 */
5384 status = cli_posix_stat(cli1, fname, &sbuf);
5385 if (!NT_STATUS_IS_OK(status)) {
5386 printf("stat failed (%s)\n", nt_errstr(status));
5387 goto out;
5390 if (sbuf.st_ex_size != 1000) {
5391 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5392 goto out;
5395 status = cli_close(cli1, fnum1);
5396 if (!NT_STATUS_IS_OK(status)) {
5397 printf("close(2) failed (%s)\n", nt_errstr(status));
5398 goto out;
5401 /* Re-open with O_TRUNC. */
5402 status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
5403 if (!NT_STATUS_IS_OK(status)) {
5404 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5405 goto out;
5408 /* Ensure st_size == 0 */
5409 status = cli_posix_stat(cli1, fname, &sbuf);
5410 if (!NT_STATUS_IS_OK(status)) {
5411 printf("stat failed (%s)\n", nt_errstr(status));
5412 goto out;
5415 if (sbuf.st_ex_size != 0) {
5416 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
5417 goto out;
5420 status = cli_close(cli1, fnum1);
5421 if (!NT_STATUS_IS_OK(status)) {
5422 printf("close failed (%s)\n", nt_errstr(status));
5423 goto out;
5426 status = cli_posix_unlink(cli1, fname);
5427 if (!NT_STATUS_IS_OK(status)) {
5428 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5429 goto out;
5432 status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
5433 if (!NT_STATUS_IS_OK(status)) {
5434 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
5435 dname, nt_errstr(status));
5436 goto out;
5439 cli_close(cli1, fnum1);
5441 /* What happens when we try and POSIX open a directory for write ? */
5442 status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
5443 if (NT_STATUS_IS_OK(status)) {
5444 printf("POSIX open of directory %s succeeded, should have failed.\n", fname);
5445 goto out;
5446 } else {
5447 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
5448 NT_STATUS_FILE_IS_A_DIRECTORY)) {
5449 goto out;
5453 /* Create the file. */
5454 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5455 0600, &fnum1);
5456 if (!NT_STATUS_IS_OK(status)) {
5457 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5458 goto out;
5461 /* Write some data into it. */
5462 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5463 NULL);
5464 if (!NT_STATUS_IS_OK(status)) {
5465 printf("cli_write failed: %s\n", nt_errstr(status));
5466 goto out;
5469 cli_close(cli1, fnum1);
5471 /* Now create a hardlink. */
5472 status = cli_posix_hardlink(cli1, fname, hname);
5473 if (!NT_STATUS_IS_OK(status)) {
5474 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
5475 goto out;
5478 /* Now create a symlink. */
5479 status = cli_posix_symlink(cli1, fname, sname);
5480 if (!NT_STATUS_IS_OK(status)) {
5481 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
5482 goto out;
5485 /* Open the hardlink for read. */
5486 status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
5487 if (!NT_STATUS_IS_OK(status)) {
5488 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
5489 goto out;
5492 if (cli_read_old(cli1, fnum1, buf, 0, 10) != 10) {
5493 printf("POSIX read of %s failed (%s)\n", hname, cli_errstr(cli1));
5494 goto out;
5497 if (memcmp(buf, "TEST DATA\n", 10)) {
5498 printf("invalid data read from hardlink\n");
5499 goto out;
5502 /* Do a POSIX lock/unlock. */
5503 status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
5504 if (!NT_STATUS_IS_OK(status)) {
5505 printf("POSIX lock failed %s\n", nt_errstr(status));
5506 goto out;
5509 /* Punch a hole in the locked area. */
5510 status = cli_posix_unlock(cli1, fnum1, 10, 80);
5511 if (!NT_STATUS_IS_OK(status)) {
5512 printf("POSIX unlock failed %s\n", nt_errstr(status));
5513 goto out;
5516 cli_close(cli1, fnum1);
5518 /* Open the symlink for read - this should fail. A POSIX
5519 client should not be doing opens on a symlink. */
5520 status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
5521 if (NT_STATUS_IS_OK(status)) {
5522 printf("POSIX open of %s succeeded (should have failed)\n", sname);
5523 goto out;
5524 } else {
5525 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
5526 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
5527 printf("POSIX open of %s should have failed "
5528 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
5529 "failed with %s instead.\n",
5530 sname, nt_errstr(status));
5531 goto out;
5535 status = cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf));
5536 if (!NT_STATUS_IS_OK(status)) {
5537 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
5538 goto out;
5541 if (strcmp(namebuf, fname) != 0) {
5542 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
5543 sname, fname, namebuf);
5544 goto out;
5547 status = cli_posix_rmdir(cli1, dname);
5548 if (!NT_STATUS_IS_OK(status)) {
5549 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
5550 goto out;
5553 printf("Simple POSIX open test passed\n");
5554 correct = true;
5556 out:
5558 if (fnum1 != (uint16_t)-1) {
5559 cli_close(cli1, fnum1);
5560 fnum1 = (uint16_t)-1;
5563 cli_setatr(cli1, sname, 0, 0);
5564 cli_posix_unlink(cli1, sname);
5565 cli_setatr(cli1, hname, 0, 0);
5566 cli_posix_unlink(cli1, hname);
5567 cli_setatr(cli1, fname, 0, 0);
5568 cli_posix_unlink(cli1, fname);
5569 cli_setatr(cli1, dname, 0, 0);
5570 cli_posix_rmdir(cli1, dname);
5572 if (!torture_close_connection(cli1)) {
5573 correct = false;
5576 return correct;
5580 static uint32 open_attrs_table[] = {
5581 FILE_ATTRIBUTE_NORMAL,
5582 FILE_ATTRIBUTE_ARCHIVE,
5583 FILE_ATTRIBUTE_READONLY,
5584 FILE_ATTRIBUTE_HIDDEN,
5585 FILE_ATTRIBUTE_SYSTEM,
5587 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
5588 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
5589 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
5590 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5591 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5592 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5594 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5595 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5596 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5597 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
5600 struct trunc_open_results {
5601 unsigned int num;
5602 uint32 init_attr;
5603 uint32 trunc_attr;
5604 uint32 result_attr;
5607 static struct trunc_open_results attr_results[] = {
5608 { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5609 { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5610 { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5611 { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5612 { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5613 { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5614 { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5615 { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5616 { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5617 { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5618 { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5619 { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
5620 { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5621 { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5622 { 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 },
5623 { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5624 { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5625 { 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 },
5626 { 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 },
5627 { 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 },
5628 { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5629 { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5630 { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5631 { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5632 { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5633 { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
5636 static bool run_openattrtest(int dummy)
5638 static struct cli_state *cli1;
5639 const char *fname = "\\openattr.file";
5640 uint16_t fnum1;
5641 bool correct = True;
5642 uint16 attr;
5643 unsigned int i, j, k, l;
5644 NTSTATUS status;
5646 printf("starting open attr test\n");
5648 if (!torture_open_connection(&cli1, 0)) {
5649 return False;
5652 cli_sockopt(cli1, sockops);
5654 for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32); i++) {
5655 cli_setatr(cli1, fname, 0, 0);
5656 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5658 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
5659 open_attrs_table[i], FILE_SHARE_NONE,
5660 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5661 if (!NT_STATUS_IS_OK(status)) {
5662 printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5663 return False;
5666 status = cli_close(cli1, fnum1);
5667 if (!NT_STATUS_IS_OK(status)) {
5668 printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5669 return False;
5672 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32); j++) {
5673 status = cli_ntcreate(cli1, fname, 0,
5674 FILE_READ_DATA|FILE_WRITE_DATA,
5675 open_attrs_table[j],
5676 FILE_SHARE_NONE, FILE_OVERWRITE,
5677 0, 0, &fnum1);
5678 if (!NT_STATUS_IS_OK(status)) {
5679 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5680 if (attr_results[l].num == k) {
5681 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
5682 k, open_attrs_table[i],
5683 open_attrs_table[j],
5684 fname, NT_STATUS_V(status), nt_errstr(status));
5685 correct = False;
5689 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5690 printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
5691 k, open_attrs_table[i], open_attrs_table[j],
5692 nt_errstr(status));
5693 correct = False;
5695 #if 0
5696 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
5697 #endif
5698 k++;
5699 continue;
5702 status = cli_close(cli1, fnum1);
5703 if (!NT_STATUS_IS_OK(status)) {
5704 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
5705 return False;
5708 status = cli_getatr(cli1, fname, &attr, NULL, NULL);
5709 if (!NT_STATUS_IS_OK(status)) {
5710 printf("getatr(2) failed (%s)\n", nt_errstr(status));
5711 return False;
5714 #if 0
5715 printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
5716 k, open_attrs_table[i], open_attrs_table[j], attr );
5717 #endif
5719 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5720 if (attr_results[l].num == k) {
5721 if (attr != attr_results[l].result_attr ||
5722 open_attrs_table[i] != attr_results[l].init_attr ||
5723 open_attrs_table[j] != attr_results[l].trunc_attr) {
5724 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
5725 open_attrs_table[i],
5726 open_attrs_table[j],
5727 (unsigned int)attr,
5728 attr_results[l].result_attr);
5729 correct = False;
5731 break;
5734 k++;
5738 cli_setatr(cli1, fname, 0, 0);
5739 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5741 printf("open attr test %s.\n", correct ? "passed" : "failed");
5743 if (!torture_close_connection(cli1)) {
5744 correct = False;
5746 return correct;
5749 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
5750 const char *name, void *state)
5752 int *matched = (int *)state;
5753 if (matched != NULL) {
5754 *matched += 1;
5756 return NT_STATUS_OK;
5760 test directory listing speed
5762 static bool run_dirtest(int dummy)
5764 int i;
5765 static struct cli_state *cli;
5766 uint16_t fnum;
5767 struct timeval core_start;
5768 bool correct = True;
5769 int matched;
5771 printf("starting directory test\n");
5773 if (!torture_open_connection(&cli, 0)) {
5774 return False;
5777 cli_sockopt(cli, sockops);
5779 srandom(0);
5780 for (i=0;i<torture_numops;i++) {
5781 fstring fname;
5782 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5783 if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
5784 fprintf(stderr,"Failed to open %s\n", fname);
5785 return False;
5787 cli_close(cli, fnum);
5790 core_start = timeval_current();
5792 matched = 0;
5793 cli_list(cli, "a*.*", 0, list_fn, &matched);
5794 printf("Matched %d\n", matched);
5796 matched = 0;
5797 cli_list(cli, "b*.*", 0, list_fn, &matched);
5798 printf("Matched %d\n", matched);
5800 matched = 0;
5801 cli_list(cli, "xyzabc", 0, list_fn, &matched);
5802 printf("Matched %d\n", matched);
5804 printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
5806 srandom(0);
5807 for (i=0;i<torture_numops;i++) {
5808 fstring fname;
5809 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5810 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5813 if (!torture_close_connection(cli)) {
5814 correct = False;
5817 printf("finished dirtest\n");
5819 return correct;
5822 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
5823 void *state)
5825 struct cli_state *pcli = (struct cli_state *)state;
5826 fstring fname;
5827 slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
5829 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
5830 return NT_STATUS_OK;
5832 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
5833 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
5834 printf("del_fn: failed to rmdir %s\n,", fname );
5835 } else {
5836 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
5837 printf("del_fn: failed to unlink %s\n,", fname );
5839 return NT_STATUS_OK;
5844 sees what IOCTLs are supported
5846 bool torture_ioctl_test(int dummy)
5848 static struct cli_state *cli;
5849 uint16_t device, function;
5850 uint16_t fnum;
5851 const char *fname = "\\ioctl.dat";
5852 DATA_BLOB blob;
5853 NTSTATUS status;
5855 if (!torture_open_connection(&cli, 0)) {
5856 return False;
5859 printf("starting ioctl test\n");
5861 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5863 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5864 if (!NT_STATUS_IS_OK(status)) {
5865 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5866 return False;
5869 status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
5870 printf("ioctl device info: %s\n", nt_errstr(status));
5872 status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
5873 printf("ioctl job info: %s\n", nt_errstr(status));
5875 for (device=0;device<0x100;device++) {
5876 printf("ioctl test with device = 0x%x\n", device);
5877 for (function=0;function<0x100;function++) {
5878 uint32 code = (device<<16) | function;
5880 status = cli_raw_ioctl(cli, fnum, code, &blob);
5882 if (NT_STATUS_IS_OK(status)) {
5883 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
5884 (int)blob.length);
5885 data_blob_free(&blob);
5890 if (!torture_close_connection(cli)) {
5891 return False;
5894 return True;
5899 tries varients of chkpath
5901 bool torture_chkpath_test(int dummy)
5903 static struct cli_state *cli;
5904 uint16_t fnum;
5905 bool ret;
5906 NTSTATUS status;
5908 if (!torture_open_connection(&cli, 0)) {
5909 return False;
5912 printf("starting chkpath test\n");
5914 /* cleanup from an old run */
5915 cli_rmdir(cli, "\\chkpath.dir\\dir2");
5916 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5917 cli_rmdir(cli, "\\chkpath.dir");
5919 status = cli_mkdir(cli, "\\chkpath.dir");
5920 if (!NT_STATUS_IS_OK(status)) {
5921 printf("mkdir1 failed : %s\n", nt_errstr(status));
5922 return False;
5925 status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
5926 if (!NT_STATUS_IS_OK(status)) {
5927 printf("mkdir2 failed : %s\n", nt_errstr(status));
5928 return False;
5931 status = cli_open(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
5932 DENY_NONE, &fnum);
5933 if (!NT_STATUS_IS_OK(status)) {
5934 printf("open1 failed (%s)\n", nt_errstr(status));
5935 return False;
5937 cli_close(cli, fnum);
5939 status = cli_chkpath(cli, "\\chkpath.dir");
5940 if (!NT_STATUS_IS_OK(status)) {
5941 printf("chkpath1 failed: %s\n", nt_errstr(status));
5942 ret = False;
5945 status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
5946 if (!NT_STATUS_IS_OK(status)) {
5947 printf("chkpath2 failed: %s\n", nt_errstr(status));
5948 ret = False;
5951 status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
5952 if (!NT_STATUS_IS_OK(status)) {
5953 ret = check_error(__LINE__, cli, ERRDOS, ERRbadpath,
5954 NT_STATUS_NOT_A_DIRECTORY);
5955 } else {
5956 printf("* chkpath on a file should fail\n");
5957 ret = False;
5960 if (!NT_STATUS_IS_OK(cli_chkpath(cli, "\\chkpath.dir\\bar.txt"))) {
5961 ret = check_error(__LINE__, cli, ERRDOS, ERRbadfile,
5962 NT_STATUS_OBJECT_NAME_NOT_FOUND);
5963 } else {
5964 printf("* chkpath on a non existant file should fail\n");
5965 ret = False;
5968 if (!NT_STATUS_IS_OK(cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt"))) {
5969 ret = check_error(__LINE__, cli, ERRDOS, ERRbadpath,
5970 NT_STATUS_OBJECT_PATH_NOT_FOUND);
5971 } else {
5972 printf("* chkpath on a non existent component should fail\n");
5973 ret = False;
5976 cli_rmdir(cli, "\\chkpath.dir\\dir2");
5977 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5978 cli_rmdir(cli, "\\chkpath.dir");
5980 if (!torture_close_connection(cli)) {
5981 return False;
5984 return ret;
5987 static bool run_eatest(int dummy)
5989 static struct cli_state *cli;
5990 const char *fname = "\\eatest.txt";
5991 bool correct = True;
5992 uint16_t fnum;
5993 int i;
5994 size_t num_eas;
5995 struct ea_struct *ea_list = NULL;
5996 TALLOC_CTX *mem_ctx = talloc_init("eatest");
5997 NTSTATUS status;
5999 printf("starting eatest\n");
6001 if (!torture_open_connection(&cli, 0)) {
6002 talloc_destroy(mem_ctx);
6003 return False;
6006 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6008 status = cli_ntcreate(cli, fname, 0,
6009 FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6010 FILE_SHARE_NONE, FILE_OVERWRITE_IF,
6011 0x4044, 0, &fnum);
6012 if (!NT_STATUS_IS_OK(status)) {
6013 printf("open failed - %s\n", nt_errstr(status));
6014 talloc_destroy(mem_ctx);
6015 return False;
6018 for (i = 0; i < 10; i++) {
6019 fstring ea_name, ea_val;
6021 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
6022 memset(ea_val, (char)i+1, i+1);
6023 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
6024 if (!NT_STATUS_IS_OK(status)) {
6025 printf("ea_set of name %s failed - %s\n", ea_name,
6026 nt_errstr(status));
6027 talloc_destroy(mem_ctx);
6028 return False;
6032 cli_close(cli, fnum);
6033 for (i = 0; i < 10; i++) {
6034 fstring ea_name, ea_val;
6036 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
6037 memset(ea_val, (char)i+1, i+1);
6038 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
6039 if (!NT_STATUS_IS_OK(status)) {
6040 printf("ea_set of name %s failed - %s\n", ea_name,
6041 nt_errstr(status));
6042 talloc_destroy(mem_ctx);
6043 return False;
6047 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6048 if (!NT_STATUS_IS_OK(status)) {
6049 printf("ea_get list failed - %s\n", nt_errstr(status));
6050 correct = False;
6053 printf("num_eas = %d\n", (int)num_eas);
6055 if (num_eas != 20) {
6056 printf("Should be 20 EA's stored... failing.\n");
6057 correct = False;
6060 for (i = 0; i < num_eas; i++) {
6061 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6062 dump_data(0, ea_list[i].value.data,
6063 ea_list[i].value.length);
6066 /* Setting EA's to zero length deletes them. Test this */
6067 printf("Now deleting all EA's - case indepenent....\n");
6069 #if 1
6070 cli_set_ea_path(cli, fname, "", "", 0);
6071 #else
6072 for (i = 0; i < 20; i++) {
6073 fstring ea_name;
6074 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
6075 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
6076 if (!NT_STATUS_IS_OK(status)) {
6077 printf("ea_set of name %s failed - %s\n", ea_name,
6078 nt_errstr(status));
6079 talloc_destroy(mem_ctx);
6080 return False;
6083 #endif
6085 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6086 if (!NT_STATUS_IS_OK(status)) {
6087 printf("ea_get list failed - %s\n", nt_errstr(status));
6088 correct = False;
6091 printf("num_eas = %d\n", (int)num_eas);
6092 for (i = 0; i < num_eas; i++) {
6093 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6094 dump_data(0, ea_list[i].value.data,
6095 ea_list[i].value.length);
6098 if (num_eas != 0) {
6099 printf("deleting EA's failed.\n");
6100 correct = False;
6103 /* Try and delete a non existant EA. */
6104 status = cli_set_ea_path(cli, fname, "foo", "", 0);
6105 if (!NT_STATUS_IS_OK(status)) {
6106 printf("deleting non-existant EA 'foo' should succeed. %s\n",
6107 nt_errstr(status));
6108 correct = False;
6111 talloc_destroy(mem_ctx);
6112 if (!torture_close_connection(cli)) {
6113 correct = False;
6116 return correct;
6119 static bool run_dirtest1(int dummy)
6121 int i;
6122 static struct cli_state *cli;
6123 uint16_t fnum;
6124 int num_seen;
6125 bool correct = True;
6127 printf("starting directory test\n");
6129 if (!torture_open_connection(&cli, 0)) {
6130 return False;
6133 cli_sockopt(cli, sockops);
6135 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6136 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6137 cli_rmdir(cli, "\\LISTDIR");
6138 cli_mkdir(cli, "\\LISTDIR");
6140 /* Create 1000 files and 1000 directories. */
6141 for (i=0;i<1000;i++) {
6142 fstring fname;
6143 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
6144 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6145 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum))) {
6146 fprintf(stderr,"Failed to open %s\n", fname);
6147 return False;
6149 cli_close(cli, fnum);
6151 for (i=0;i<1000;i++) {
6152 fstring fname;
6153 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
6154 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
6155 fprintf(stderr,"Failed to open %s\n", fname);
6156 return False;
6160 /* Now ensure that doing an old list sees both files and directories. */
6161 num_seen = 0;
6162 cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6163 printf("num_seen = %d\n", num_seen );
6164 /* We should see 100 files + 1000 directories + . and .. */
6165 if (num_seen != 2002)
6166 correct = False;
6168 /* Ensure if we have the "must have" bits we only see the
6169 * relevent entries.
6171 num_seen = 0;
6172 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6173 printf("num_seen = %d\n", num_seen );
6174 if (num_seen != 1002)
6175 correct = False;
6177 num_seen = 0;
6178 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6179 printf("num_seen = %d\n", num_seen );
6180 if (num_seen != 1000)
6181 correct = False;
6183 /* Delete everything. */
6184 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6185 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6186 cli_rmdir(cli, "\\LISTDIR");
6188 #if 0
6189 printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
6190 printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
6191 printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
6192 #endif
6194 if (!torture_close_connection(cli)) {
6195 correct = False;
6198 printf("finished dirtest1\n");
6200 return correct;
6203 static bool run_error_map_extract(int dummy) {
6205 static struct cli_state *c_dos;
6206 static struct cli_state *c_nt;
6207 NTSTATUS status;
6209 uint32 error;
6211 uint32 errnum;
6212 uint8 errclass;
6214 NTSTATUS nt_status;
6216 fstring user;
6218 /* NT-Error connection */
6220 if (!(c_nt = open_nbt_connection())) {
6221 return False;
6224 c_nt->use_spnego = False;
6226 status = cli_negprot(c_nt);
6228 if (!NT_STATUS_IS_OK(status)) {
6229 printf("%s rejected the NT-error negprot (%s)\n", host,
6230 nt_errstr(status));
6231 cli_shutdown(c_nt);
6232 return False;
6235 status = cli_session_setup(c_nt, "", "", 0, "", 0, workgroup);
6236 if (!NT_STATUS_IS_OK(status)) {
6237 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
6238 return False;
6241 /* DOS-Error connection */
6243 if (!(c_dos = open_nbt_connection())) {
6244 return False;
6247 c_dos->use_spnego = False;
6248 c_dos->force_dos_errors = True;
6250 status = cli_negprot(c_dos);
6251 if (!NT_STATUS_IS_OK(status)) {
6252 printf("%s rejected the DOS-error negprot (%s)\n", host,
6253 nt_errstr(status));
6254 cli_shutdown(c_dos);
6255 return False;
6258 status = cli_session_setup(c_dos, "", "", 0, "", 0, workgroup);
6259 if (!NT_STATUS_IS_OK(status)) {
6260 printf("%s rejected the DOS-error initial session setup (%s)\n",
6261 host, nt_errstr(status));
6262 return False;
6265 for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
6266 fstr_sprintf(user, "%X", error);
6268 status = cli_session_setup(c_nt, user,
6269 password, strlen(password),
6270 password, strlen(password),
6271 workgroup);
6272 if (NT_STATUS_IS_OK(status)) {
6273 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
6276 /* Case #1: 32-bit NT errors */
6277 if (cli_is_nt_error(c_nt)) {
6278 nt_status = cli_nt_error(c_nt);
6279 } else {
6280 printf("/** Dos error on NT connection! (%s) */\n",
6281 cli_errstr(c_nt));
6282 nt_status = NT_STATUS(0xc0000000);
6285 status = cli_session_setup(c_dos, user,
6286 password, strlen(password),
6287 password, strlen(password),
6288 workgroup);
6289 if (NT_STATUS_IS_OK(status)) {
6290 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
6293 /* Case #1: 32-bit NT errors */
6294 if (!cli_is_dos_error(c_dos)) {
6295 printf("/** NT error on DOS connection! (%s) */\n",
6296 cli_errstr(c_dos));
6297 errnum = errclass = 0;
6298 } else {
6299 cli_dos_error(c_dos, &errclass, &errnum);
6302 if (NT_STATUS_V(nt_status) != error) {
6303 printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
6304 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
6305 get_nt_error_c_code(talloc_tos(), nt_status));
6308 printf("\t{%s,\t%s,\t%s},\n",
6309 smb_dos_err_class(errclass),
6310 smb_dos_err_name(errclass, errnum),
6311 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
6313 return True;
6316 static bool run_sesssetup_bench(int dummy)
6318 static struct cli_state *c;
6319 const char *fname = "\\file.dat";
6320 uint16_t fnum;
6321 NTSTATUS status;
6322 int i;
6324 if (!torture_open_connection(&c, 0)) {
6325 return false;
6328 status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6329 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6330 FILE_DELETE_ON_CLOSE, 0, &fnum);
6331 if (!NT_STATUS_IS_OK(status)) {
6332 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
6333 return false;
6336 for (i=0; i<torture_numops; i++) {
6337 status = cli_session_setup(
6338 c, username,
6339 password, strlen(password),
6340 password, strlen(password),
6341 workgroup);
6342 if (!NT_STATUS_IS_OK(status)) {
6343 d_printf("(%s) cli_session_setup failed: %s\n",
6344 __location__, nt_errstr(status));
6345 return false;
6348 d_printf("\r%d ", (int)c->vuid);
6350 status = cli_ulogoff(c);
6351 if (!NT_STATUS_IS_OK(status)) {
6352 d_printf("(%s) cli_ulogoff failed: %s\n",
6353 __location__, nt_errstr(status));
6354 return false;
6356 c->vuid = 0;
6359 return true;
6362 static bool subst_test(const char *str, const char *user, const char *domain,
6363 uid_t uid, gid_t gid, const char *expected)
6365 char *subst;
6366 bool result = true;
6368 subst = talloc_sub_specified(talloc_tos(), str, user, domain, uid, gid);
6370 if (strcmp(subst, expected) != 0) {
6371 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
6372 "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
6373 expected);
6374 result = false;
6377 TALLOC_FREE(subst);
6378 return result;
6381 static void chain1_open_completion(struct tevent_req *req)
6383 uint16_t fnum;
6384 NTSTATUS status;
6385 status = cli_open_recv(req, &fnum);
6386 TALLOC_FREE(req);
6388 d_printf("cli_open_recv returned %s: %d\n",
6389 nt_errstr(status),
6390 NT_STATUS_IS_OK(status) ? fnum : -1);
6393 static void chain1_write_completion(struct tevent_req *req)
6395 size_t written;
6396 NTSTATUS status;
6397 status = cli_write_andx_recv(req, &written);
6398 TALLOC_FREE(req);
6400 d_printf("cli_write_andx_recv returned %s: %d\n",
6401 nt_errstr(status),
6402 NT_STATUS_IS_OK(status) ? (int)written : -1);
6405 static void chain1_close_completion(struct tevent_req *req)
6407 NTSTATUS status;
6408 bool *done = (bool *)tevent_req_callback_data_void(req);
6410 status = cli_close_recv(req);
6411 *done = true;
6413 TALLOC_FREE(req);
6415 d_printf("cli_close returned %s\n", nt_errstr(status));
6418 static bool run_chain1(int dummy)
6420 struct cli_state *cli1;
6421 struct event_context *evt = event_context_init(NULL);
6422 struct tevent_req *reqs[3], *smbreqs[3];
6423 bool done = false;
6424 const char *str = "foobar";
6425 NTSTATUS status;
6427 printf("starting chain1 test\n");
6428 if (!torture_open_connection(&cli1, 0)) {
6429 return False;
6432 cli_sockopt(cli1, sockops);
6434 reqs[0] = cli_open_create(talloc_tos(), evt, cli1, "\\test",
6435 O_CREAT|O_RDWR, 0, &smbreqs[0]);
6436 if (reqs[0] == NULL) return false;
6437 tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
6440 reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
6441 (const uint8_t *)str, 0, strlen(str)+1,
6442 smbreqs, 1, &smbreqs[1]);
6443 if (reqs[1] == NULL) return false;
6444 tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
6446 reqs[2] = cli_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
6447 if (reqs[2] == NULL) return false;
6448 tevent_req_set_callback(reqs[2], chain1_close_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;
6463 static void chain2_sesssetup_completion(struct tevent_req *req)
6465 NTSTATUS status;
6466 status = cli_session_setup_guest_recv(req);
6467 d_printf("sesssetup returned %s\n", nt_errstr(status));
6470 static void chain2_tcon_completion(struct tevent_req *req)
6472 bool *done = (bool *)tevent_req_callback_data_void(req);
6473 NTSTATUS status;
6474 status = cli_tcon_andx_recv(req);
6475 d_printf("tcon_and_x returned %s\n", nt_errstr(status));
6476 *done = true;
6479 static bool run_chain2(int dummy)
6481 struct cli_state *cli1;
6482 struct event_context *evt = event_context_init(NULL);
6483 struct tevent_req *reqs[2], *smbreqs[2];
6484 bool done = false;
6485 NTSTATUS status;
6487 printf("starting chain2 test\n");
6488 status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
6489 port_to_use, Undefined, 0);
6490 if (!NT_STATUS_IS_OK(status)) {
6491 return False;
6494 cli_sockopt(cli1, sockops);
6496 reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
6497 &smbreqs[0]);
6498 if (reqs[0] == NULL) return false;
6499 tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
6501 reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
6502 "?????", NULL, 0, &smbreqs[1]);
6503 if (reqs[1] == NULL) return false;
6504 tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
6506 status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
6507 if (!NT_STATUS_IS_OK(status)) {
6508 return false;
6511 while (!done) {
6512 event_loop_once(evt);
6515 torture_close_connection(cli1);
6516 return True;
6520 struct torture_createdel_state {
6521 struct tevent_context *ev;
6522 struct cli_state *cli;
6525 static void torture_createdel_created(struct tevent_req *subreq);
6526 static void torture_createdel_closed(struct tevent_req *subreq);
6528 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
6529 struct tevent_context *ev,
6530 struct cli_state *cli,
6531 const char *name)
6533 struct tevent_req *req, *subreq;
6534 struct torture_createdel_state *state;
6536 req = tevent_req_create(mem_ctx, &state,
6537 struct torture_createdel_state);
6538 if (req == NULL) {
6539 return NULL;
6541 state->ev = ev;
6542 state->cli = cli;
6544 subreq = cli_ntcreate_send(
6545 state, ev, cli, name, 0,
6546 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
6547 FILE_ATTRIBUTE_NORMAL,
6548 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6549 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
6551 if (tevent_req_nomem(subreq, req)) {
6552 return tevent_req_post(req, ev);
6554 tevent_req_set_callback(subreq, torture_createdel_created, req);
6555 return req;
6558 static void torture_createdel_created(struct tevent_req *subreq)
6560 struct tevent_req *req = tevent_req_callback_data(
6561 subreq, struct tevent_req);
6562 struct torture_createdel_state *state = tevent_req_data(
6563 req, struct torture_createdel_state);
6564 NTSTATUS status;
6565 uint16_t fnum;
6567 status = cli_ntcreate_recv(subreq, &fnum);
6568 TALLOC_FREE(subreq);
6569 if (!NT_STATUS_IS_OK(status)) {
6570 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
6571 nt_errstr(status)));
6572 tevent_req_nterror(req, status);
6573 return;
6576 subreq = cli_close_send(state, state->ev, state->cli, fnum);
6577 if (tevent_req_nomem(subreq, req)) {
6578 return;
6580 tevent_req_set_callback(subreq, torture_createdel_closed, req);
6583 static void torture_createdel_closed(struct tevent_req *subreq)
6585 struct tevent_req *req = tevent_req_callback_data(
6586 subreq, struct tevent_req);
6587 NTSTATUS status;
6589 status = cli_close_recv(subreq);
6590 if (!NT_STATUS_IS_OK(status)) {
6591 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
6592 tevent_req_nterror(req, status);
6593 return;
6595 tevent_req_done(req);
6598 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
6600 return tevent_req_simple_recv_ntstatus(req);
6603 struct torture_createdels_state {
6604 struct tevent_context *ev;
6605 struct cli_state *cli;
6606 const char *base_name;
6607 int sent;
6608 int received;
6609 int num_files;
6610 struct tevent_req **reqs;
6613 static void torture_createdels_done(struct tevent_req *subreq);
6615 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
6616 struct tevent_context *ev,
6617 struct cli_state *cli,
6618 const char *base_name,
6619 int num_parallel,
6620 int num_files)
6622 struct tevent_req *req;
6623 struct torture_createdels_state *state;
6624 int i;
6626 req = tevent_req_create(mem_ctx, &state,
6627 struct torture_createdels_state);
6628 if (req == NULL) {
6629 return NULL;
6631 state->ev = ev;
6632 state->cli = cli;
6633 state->base_name = talloc_strdup(state, base_name);
6634 if (tevent_req_nomem(state->base_name, req)) {
6635 return tevent_req_post(req, ev);
6637 state->num_files = MAX(num_parallel, num_files);
6638 state->sent = 0;
6639 state->received = 0;
6641 state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
6642 if (tevent_req_nomem(state->reqs, req)) {
6643 return tevent_req_post(req, ev);
6646 for (i=0; i<num_parallel; i++) {
6647 char *name;
6649 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6650 state->sent);
6651 if (tevent_req_nomem(name, req)) {
6652 return tevent_req_post(req, ev);
6654 state->reqs[i] = torture_createdel_send(
6655 state->reqs, state->ev, state->cli, name);
6656 if (tevent_req_nomem(state->reqs[i], req)) {
6657 return tevent_req_post(req, ev);
6659 name = talloc_move(state->reqs[i], &name);
6660 tevent_req_set_callback(state->reqs[i],
6661 torture_createdels_done, req);
6662 state->sent += 1;
6664 return req;
6667 static void torture_createdels_done(struct tevent_req *subreq)
6669 struct tevent_req *req = tevent_req_callback_data(
6670 subreq, struct tevent_req);
6671 struct torture_createdels_state *state = tevent_req_data(
6672 req, struct torture_createdels_state);
6673 size_t num_parallel = talloc_array_length(state->reqs);
6674 NTSTATUS status;
6675 char *name;
6676 int i;
6678 status = torture_createdel_recv(subreq);
6679 if (!NT_STATUS_IS_OK(status)){
6680 DEBUG(10, ("torture_createdel_recv returned %s\n",
6681 nt_errstr(status)));
6682 TALLOC_FREE(subreq);
6683 tevent_req_nterror(req, status);
6684 return;
6687 for (i=0; i<num_parallel; i++) {
6688 if (subreq == state->reqs[i]) {
6689 break;
6692 if (i == num_parallel) {
6693 DEBUG(10, ("received something we did not send\n"));
6694 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
6695 return;
6697 TALLOC_FREE(state->reqs[i]);
6699 if (state->sent >= state->num_files) {
6700 tevent_req_done(req);
6701 return;
6704 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6705 state->sent);
6706 if (tevent_req_nomem(name, req)) {
6707 return;
6709 state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
6710 state->cli, name);
6711 if (tevent_req_nomem(state->reqs[i], req)) {
6712 return;
6714 name = talloc_move(state->reqs[i], &name);
6715 tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
6716 state->sent += 1;
6719 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
6721 return tevent_req_simple_recv_ntstatus(req);
6724 struct swallow_notify_state {
6725 struct tevent_context *ev;
6726 struct cli_state *cli;
6727 uint16_t fnum;
6728 uint32_t completion_filter;
6729 bool recursive;
6730 bool (*fn)(uint32_t action, const char *name, void *priv);
6731 void *priv;
6734 static void swallow_notify_done(struct tevent_req *subreq);
6736 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
6737 struct tevent_context *ev,
6738 struct cli_state *cli,
6739 uint16_t fnum,
6740 uint32_t completion_filter,
6741 bool recursive,
6742 bool (*fn)(uint32_t action,
6743 const char *name,
6744 void *priv),
6745 void *priv)
6747 struct tevent_req *req, *subreq;
6748 struct swallow_notify_state *state;
6750 req = tevent_req_create(mem_ctx, &state,
6751 struct swallow_notify_state);
6752 if (req == NULL) {
6753 return NULL;
6755 state->ev = ev;
6756 state->cli = cli;
6757 state->fnum = fnum;
6758 state->completion_filter = completion_filter;
6759 state->recursive = recursive;
6760 state->fn = fn;
6761 state->priv = priv;
6763 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6764 0xffff, state->completion_filter,
6765 state->recursive);
6766 if (tevent_req_nomem(subreq, req)) {
6767 return tevent_req_post(req, ev);
6769 tevent_req_set_callback(subreq, swallow_notify_done, req);
6770 return req;
6773 static void swallow_notify_done(struct tevent_req *subreq)
6775 struct tevent_req *req = tevent_req_callback_data(
6776 subreq, struct tevent_req);
6777 struct swallow_notify_state *state = tevent_req_data(
6778 req, struct swallow_notify_state);
6779 NTSTATUS status;
6780 uint32_t i, num_changes;
6781 struct notify_change *changes;
6783 status = cli_notify_recv(subreq, state, &num_changes, &changes);
6784 TALLOC_FREE(subreq);
6785 if (!NT_STATUS_IS_OK(status)) {
6786 DEBUG(10, ("cli_notify_recv returned %s\n",
6787 nt_errstr(status)));
6788 tevent_req_nterror(req, status);
6789 return;
6792 for (i=0; i<num_changes; i++) {
6793 state->fn(changes[i].action, changes[i].name, state->priv);
6795 TALLOC_FREE(changes);
6797 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6798 0xffff, state->completion_filter,
6799 state->recursive);
6800 if (tevent_req_nomem(subreq, req)) {
6801 return;
6803 tevent_req_set_callback(subreq, swallow_notify_done, req);
6806 static bool print_notifies(uint32_t action, const char *name, void *priv)
6808 if (DEBUGLEVEL > 5) {
6809 d_printf("%d %s\n", (int)action, name);
6811 return true;
6814 static void notify_bench_done(struct tevent_req *req)
6816 int *num_finished = (int *)tevent_req_callback_data_void(req);
6817 *num_finished += 1;
6820 static bool run_notify_bench(int dummy)
6822 const char *dname = "\\notify-bench";
6823 struct tevent_context *ev;
6824 NTSTATUS status;
6825 uint16_t dnum;
6826 struct tevent_req *req1;
6827 struct tevent_req *req2 = NULL;
6828 int i, num_unc_names;
6829 int num_finished = 0;
6831 printf("starting notify-bench test\n");
6833 if (use_multishare_conn) {
6834 char **unc_list;
6835 unc_list = file_lines_load(multishare_conn_fname,
6836 &num_unc_names, 0, NULL);
6837 if (!unc_list || num_unc_names <= 0) {
6838 d_printf("Failed to load unc names list from '%s'\n",
6839 multishare_conn_fname);
6840 return false;
6842 TALLOC_FREE(unc_list);
6843 } else {
6844 num_unc_names = 1;
6847 ev = tevent_context_init(talloc_tos());
6848 if (ev == NULL) {
6849 d_printf("tevent_context_init failed\n");
6850 return false;
6853 for (i=0; i<num_unc_names; i++) {
6854 struct cli_state *cli;
6855 char *base_fname;
6857 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
6858 dname, i);
6859 if (base_fname == NULL) {
6860 return false;
6863 if (!torture_open_connection(&cli, i)) {
6864 return false;
6867 status = cli_ntcreate(cli, dname, 0,
6868 MAXIMUM_ALLOWED_ACCESS,
6869 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
6870 FILE_SHARE_DELETE,
6871 FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
6872 &dnum);
6874 if (!NT_STATUS_IS_OK(status)) {
6875 d_printf("Could not create %s: %s\n", dname,
6876 nt_errstr(status));
6877 return false;
6880 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
6881 FILE_NOTIFY_CHANGE_FILE_NAME |
6882 FILE_NOTIFY_CHANGE_DIR_NAME |
6883 FILE_NOTIFY_CHANGE_ATTRIBUTES |
6884 FILE_NOTIFY_CHANGE_LAST_WRITE,
6885 false, print_notifies, NULL);
6886 if (req1 == NULL) {
6887 d_printf("Could not create notify request\n");
6888 return false;
6891 req2 = torture_createdels_send(talloc_tos(), ev, cli,
6892 base_fname, 10, torture_numops);
6893 if (req2 == NULL) {
6894 d_printf("Could not create createdels request\n");
6895 return false;
6897 TALLOC_FREE(base_fname);
6899 tevent_req_set_callback(req2, notify_bench_done,
6900 &num_finished);
6903 while (num_finished < num_unc_names) {
6904 int ret;
6905 ret = tevent_loop_once(ev);
6906 if (ret != 0) {
6907 d_printf("tevent_loop_once failed\n");
6908 return false;
6912 if (!tevent_req_poll(req2, ev)) {
6913 d_printf("tevent_req_poll failed\n");
6916 status = torture_createdels_recv(req2);
6917 d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
6919 return true;
6922 static bool run_mangle1(int dummy)
6924 struct cli_state *cli;
6925 const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
6926 uint16_t fnum;
6927 fstring alt_name;
6928 NTSTATUS status;
6929 time_t change_time, access_time, write_time;
6930 SMB_OFF_T size;
6931 uint16_t mode;
6933 printf("starting mangle1 test\n");
6934 if (!torture_open_connection(&cli, 0)) {
6935 return False;
6938 cli_sockopt(cli, sockops);
6940 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6941 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6942 0, 0, &fnum);
6943 if (!NT_STATUS_IS_OK(status)) {
6944 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
6945 return false;
6947 cli_close(cli, fnum);
6949 status = cli_qpathinfo_alt_name(cli, fname, alt_name);
6950 if (!NT_STATUS_IS_OK(status)) {
6951 d_printf("cli_qpathinfo_alt_name failed: %s\n",
6952 nt_errstr(status));
6953 return false;
6955 d_printf("alt_name: %s\n", alt_name);
6957 status = cli_open(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
6958 if (!NT_STATUS_IS_OK(status)) {
6959 d_printf("cli_open(%s) failed: %s\n", alt_name,
6960 nt_errstr(status));
6961 return false;
6963 cli_close(cli, fnum);
6965 status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
6966 &write_time, &size, &mode);
6967 if (!NT_STATUS_IS_OK(status)) {
6968 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
6969 nt_errstr(status));
6970 return false;
6973 return true;
6976 static size_t null_source(uint8_t *buf, size_t n, void *priv)
6978 size_t *to_pull = (size_t *)priv;
6979 size_t thistime = *to_pull;
6981 thistime = MIN(thistime, n);
6982 if (thistime == 0) {
6983 return 0;
6986 memset(buf, 0, thistime);
6987 *to_pull -= thistime;
6988 return thistime;
6991 static bool run_windows_write(int dummy)
6993 struct cli_state *cli1;
6994 uint16_t fnum;
6995 int i;
6996 bool ret = false;
6997 const char *fname = "\\writetest.txt";
6998 struct timeval start_time;
6999 double seconds;
7000 double kbytes;
7001 NTSTATUS status;
7003 printf("starting windows_write test\n");
7004 if (!torture_open_connection(&cli1, 0)) {
7005 return False;
7008 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
7009 if (!NT_STATUS_IS_OK(status)) {
7010 printf("open failed (%s)\n", nt_errstr(status));
7011 return False;
7014 cli_sockopt(cli1, sockops);
7016 start_time = timeval_current();
7018 for (i=0; i<torture_numops; i++) {
7019 uint8_t c = 0;
7020 off_t start = i * torture_blocksize;
7021 size_t to_pull = torture_blocksize - 1;
7023 status = cli_writeall(cli1, fnum, 0, &c,
7024 start + torture_blocksize - 1, 1, NULL);
7025 if (!NT_STATUS_IS_OK(status)) {
7026 printf("cli_write failed: %s\n", nt_errstr(status));
7027 goto fail;
7030 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
7031 null_source, &to_pull);
7032 if (!NT_STATUS_IS_OK(status)) {
7033 printf("cli_push returned: %s\n", nt_errstr(status));
7034 goto fail;
7038 seconds = timeval_elapsed(&start_time);
7039 kbytes = (double)torture_blocksize * torture_numops;
7040 kbytes /= 1024;
7042 printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
7043 (double)seconds, (int)(kbytes/seconds));
7045 ret = true;
7046 fail:
7047 cli_close(cli1, fnum);
7048 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7049 torture_close_connection(cli1);
7050 return ret;
7053 static bool run_cli_echo(int dummy)
7055 struct cli_state *cli;
7056 NTSTATUS status;
7058 printf("starting cli_echo test\n");
7059 if (!torture_open_connection(&cli, 0)) {
7060 return false;
7062 cli_sockopt(cli, sockops);
7064 status = cli_echo(cli, 5, data_blob_const("hello", 5));
7066 d_printf("cli_echo returned %s\n", nt_errstr(status));
7068 torture_close_connection(cli);
7069 return NT_STATUS_IS_OK(status);
7072 static bool run_uid_regression_test(int dummy)
7074 static struct cli_state *cli;
7075 int16_t old_vuid;
7076 int16_t old_cnum;
7077 bool correct = True;
7078 NTSTATUS status;
7080 printf("starting uid regression test\n");
7082 if (!torture_open_connection(&cli, 0)) {
7083 return False;
7086 cli_sockopt(cli, sockops);
7088 /* Ok - now save then logoff our current user. */
7089 old_vuid = cli->vuid;
7091 status = cli_ulogoff(cli);
7092 if (!NT_STATUS_IS_OK(status)) {
7093 d_printf("(%s) cli_ulogoff failed: %s\n",
7094 __location__, nt_errstr(status));
7095 correct = false;
7096 goto out;
7099 cli->vuid = old_vuid;
7101 /* Try an operation. */
7102 status = cli_mkdir(cli, "\\uid_reg_test");
7103 if (NT_STATUS_IS_OK(status)) {
7104 d_printf("(%s) cli_mkdir succeeded\n",
7105 __location__);
7106 correct = false;
7107 goto out;
7108 } else {
7109 /* Should be bad uid. */
7110 if (!check_error(__LINE__, cli, ERRSRV, ERRbaduid,
7111 NT_STATUS_USER_SESSION_DELETED)) {
7112 correct = false;
7113 goto out;
7117 old_cnum = cli_state_get_tid(cli);
7119 /* Now try a SMBtdis with the invald vuid set to zero. */
7120 cli->vuid = 0;
7122 /* This should succeed. */
7123 status = cli_tdis(cli);
7125 if (NT_STATUS_IS_OK(status)) {
7126 d_printf("First tdis with invalid vuid should succeed.\n");
7127 } else {
7128 d_printf("First tdis failed (%s)\n", nt_errstr(status));
7129 correct = false;
7130 goto out;
7133 cli->vuid = old_vuid;
7134 cli_state_set_tid(cli, old_cnum);
7136 /* This should fail. */
7137 status = cli_tdis(cli);
7138 if (NT_STATUS_IS_OK(status)) {
7139 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
7140 correct = false;
7141 goto out;
7142 } else {
7143 /* Should be bad tid. */
7144 if (!check_error(__LINE__, cli, ERRSRV, ERRinvnid,
7145 NT_STATUS_NETWORK_NAME_DELETED)) {
7146 correct = false;
7147 goto out;
7151 cli_rmdir(cli, "\\uid_reg_test");
7153 out:
7155 cli_shutdown(cli);
7156 return correct;
7160 static const char *illegal_chars = "*\\/?<>|\":";
7161 static char force_shortname_chars[] = " +,.[];=\177";
7163 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
7164 const char *mask, void *state)
7166 struct cli_state *pcli = (struct cli_state *)state;
7167 fstring fname;
7168 NTSTATUS status = NT_STATUS_OK;
7170 slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
7172 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
7173 return NT_STATUS_OK;
7175 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
7176 status = cli_rmdir(pcli, fname);
7177 if (!NT_STATUS_IS_OK(status)) {
7178 printf("del_fn: failed to rmdir %s\n,", fname );
7180 } else {
7181 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7182 if (!NT_STATUS_IS_OK(status)) {
7183 printf("del_fn: failed to unlink %s\n,", fname );
7186 return status;
7189 struct sn_state {
7190 int matched;
7191 int i;
7192 bool val;
7195 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
7196 const char *name, void *state)
7198 struct sn_state *s = (struct sn_state *)state;
7199 int i = s->i;
7201 #if 0
7202 printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
7203 i, finfo->name, finfo->short_name);
7204 #endif
7206 if (strchr(force_shortname_chars, i)) {
7207 if (!finfo->short_name) {
7208 /* Shortname not created when it should be. */
7209 d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
7210 __location__, finfo->name, i);
7211 s->val = true;
7213 } else if (finfo->short_name){
7214 /* Shortname created when it should not be. */
7215 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
7216 __location__, finfo->short_name, finfo->name);
7217 s->val = true;
7219 s->matched += 1;
7220 return NT_STATUS_OK;
7223 static bool run_shortname_test(int dummy)
7225 static struct cli_state *cli;
7226 bool correct = True;
7227 int i;
7228 struct sn_state s;
7229 char fname[20];
7230 NTSTATUS status;
7232 printf("starting shortname test\n");
7234 if (!torture_open_connection(&cli, 0)) {
7235 return False;
7238 cli_sockopt(cli, sockops);
7240 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7241 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7242 cli_rmdir(cli, "\\shortname");
7244 status = cli_mkdir(cli, "\\shortname");
7245 if (!NT_STATUS_IS_OK(status)) {
7246 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
7247 __location__, nt_errstr(status));
7248 correct = false;
7249 goto out;
7252 strlcpy(fname, "\\shortname\\", sizeof(fname));
7253 strlcat(fname, "test .txt", sizeof(fname));
7255 s.val = false;
7257 for (i = 32; i < 128; i++) {
7258 uint16_t fnum = (uint16_t)-1;
7260 s.i = i;
7262 if (strchr(illegal_chars, i)) {
7263 continue;
7265 fname[15] = i;
7267 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
7268 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum);
7269 if (!NT_STATUS_IS_OK(status)) {
7270 d_printf("(%s) cli_nt_create of %s failed: %s\n",
7271 __location__, fname, nt_errstr(status));
7272 correct = false;
7273 goto out;
7275 cli_close(cli, fnum);
7277 s.matched = 0;
7278 status = cli_list(cli, "\\shortname\\test*.*", 0,
7279 shortname_list_fn, &s);
7280 if (s.matched != 1) {
7281 d_printf("(%s) failed to list %s: %s\n",
7282 __location__, fname, nt_errstr(status));
7283 correct = false;
7284 goto out;
7287 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7288 if (!NT_STATUS_IS_OK(status)) {
7289 d_printf("(%s) failed to delete %s: %s\n",
7290 __location__, fname, nt_errstr(status));
7291 correct = false;
7292 goto out;
7295 if (s.val) {
7296 correct = false;
7297 goto out;
7301 out:
7303 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7304 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7305 cli_rmdir(cli, "\\shortname");
7306 torture_close_connection(cli);
7307 return correct;
7310 static void pagedsearch_cb(struct tevent_req *req)
7312 int rc;
7313 struct tldap_message *msg;
7314 char *dn;
7316 rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
7317 if (rc != TLDAP_SUCCESS) {
7318 d_printf("tldap_search_paged_recv failed: %s\n",
7319 tldap_err2string(rc));
7320 return;
7322 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
7323 TALLOC_FREE(msg);
7324 return;
7326 if (!tldap_entry_dn(msg, &dn)) {
7327 d_printf("tldap_entry_dn failed\n");
7328 return;
7330 d_printf("%s\n", dn);
7331 TALLOC_FREE(msg);
7334 static bool run_tldap(int dummy)
7336 struct tldap_context *ld;
7337 int fd, rc;
7338 NTSTATUS status;
7339 struct sockaddr_storage addr;
7340 struct tevent_context *ev;
7341 struct tevent_req *req;
7342 char *basedn;
7343 const char *filter;
7345 if (!resolve_name(host, &addr, 0, false)) {
7346 d_printf("could not find host %s\n", host);
7347 return false;
7349 status = open_socket_out(&addr, 389, 9999, &fd);
7350 if (!NT_STATUS_IS_OK(status)) {
7351 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
7352 return false;
7355 ld = tldap_context_create(talloc_tos(), fd);
7356 if (ld == NULL) {
7357 close(fd);
7358 d_printf("tldap_context_create failed\n");
7359 return false;
7362 rc = tldap_fetch_rootdse(ld);
7363 if (rc != TLDAP_SUCCESS) {
7364 d_printf("tldap_fetch_rootdse failed: %s\n",
7365 tldap_errstr(talloc_tos(), ld, rc));
7366 return false;
7369 basedn = tldap_talloc_single_attribute(
7370 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
7371 if (basedn == NULL) {
7372 d_printf("no defaultNamingContext\n");
7373 return false;
7375 d_printf("defaultNamingContext: %s\n", basedn);
7377 ev = tevent_context_init(talloc_tos());
7378 if (ev == NULL) {
7379 d_printf("tevent_context_init failed\n");
7380 return false;
7383 req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
7384 TLDAP_SCOPE_SUB, "(objectclass=*)",
7385 NULL, 0, 0,
7386 NULL, 0, NULL, 0, 0, 0, 0, 5);
7387 if (req == NULL) {
7388 d_printf("tldap_search_paged_send failed\n");
7389 return false;
7391 tevent_req_set_callback(req, pagedsearch_cb, NULL);
7393 tevent_req_poll(req, ev);
7395 TALLOC_FREE(req);
7397 /* test search filters against rootDSE */
7398 filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
7399 "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
7401 rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
7402 NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
7403 talloc_tos(), NULL, NULL);
7404 if (rc != TLDAP_SUCCESS) {
7405 d_printf("tldap_search with complex filter failed: %s\n",
7406 tldap_errstr(talloc_tos(), ld, rc));
7407 return false;
7410 TALLOC_FREE(ld);
7411 return true;
7414 /* Torture test to ensure no regression of :
7415 https://bugzilla.samba.org/show_bug.cgi?id=7084
7418 static bool run_dir_createtime(int dummy)
7420 struct cli_state *cli;
7421 const char *dname = "\\testdir";
7422 const char *fname = "\\testdir\\testfile";
7423 NTSTATUS status;
7424 struct timespec create_time;
7425 struct timespec create_time1;
7426 uint16_t fnum;
7427 bool ret = false;
7429 if (!torture_open_connection(&cli, 0)) {
7430 return false;
7433 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7434 cli_rmdir(cli, dname);
7436 status = cli_mkdir(cli, dname);
7437 if (!NT_STATUS_IS_OK(status)) {
7438 printf("mkdir failed: %s\n", nt_errstr(status));
7439 goto out;
7442 status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
7443 NULL, NULL, NULL);
7444 if (!NT_STATUS_IS_OK(status)) {
7445 printf("cli_qpathinfo2 returned %s\n",
7446 nt_errstr(status));
7447 goto out;
7450 /* Sleep 3 seconds, then create a file. */
7451 sleep(3);
7453 status = cli_open(cli, fname, O_RDWR | O_CREAT | O_EXCL,
7454 DENY_NONE, &fnum);
7455 if (!NT_STATUS_IS_OK(status)) {
7456 printf("cli_open failed: %s\n", nt_errstr(status));
7457 goto out;
7460 status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
7461 NULL, NULL, NULL);
7462 if (!NT_STATUS_IS_OK(status)) {
7463 printf("cli_qpathinfo2 (2) returned %s\n",
7464 nt_errstr(status));
7465 goto out;
7468 if (timespec_compare(&create_time1, &create_time)) {
7469 printf("run_dir_createtime: create time was updated (error)\n");
7470 } else {
7471 printf("run_dir_createtime: create time was not updated (correct)\n");
7472 ret = true;
7475 out:
7477 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7478 cli_rmdir(cli, dname);
7479 if (!torture_close_connection(cli)) {
7480 ret = false;
7482 return ret;
7486 static bool run_streamerror(int dummy)
7488 struct cli_state *cli;
7489 const char *dname = "\\testdir";
7490 const char *streamname =
7491 "testdir:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
7492 NTSTATUS status;
7493 time_t change_time, access_time, write_time;
7494 SMB_OFF_T size;
7495 uint16_t mode, fnum;
7496 bool ret = true;
7498 if (!torture_open_connection(&cli, 0)) {
7499 return false;
7502 cli_unlink(cli, "\\testdir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7503 cli_rmdir(cli, dname);
7505 status = cli_mkdir(cli, dname);
7506 if (!NT_STATUS_IS_OK(status)) {
7507 printf("mkdir failed: %s\n", nt_errstr(status));
7508 return false;
7511 cli_qpathinfo1(cli, streamname, &change_time, &access_time, &write_time,
7512 &size, &mode);
7513 status = cli_nt_error(cli);
7515 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7516 printf("pathinfo returned %s, expected "
7517 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
7518 nt_errstr(status));
7519 ret = false;
7522 status = cli_ntcreate(cli, streamname, 0x16,
7523 FILE_READ_DATA|FILE_READ_EA|
7524 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
7525 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7526 FILE_OPEN, 0, 0, &fnum);
7528 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7529 printf("ntcreate returned %s, expected "
7530 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
7531 nt_errstr(status));
7532 ret = false;
7536 cli_rmdir(cli, dname);
7537 return ret;
7540 static bool run_local_substitute(int dummy)
7542 bool ok = true;
7544 ok &= subst_test("%U", "bla", "", -1, -1, "bla");
7545 ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
7546 ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
7547 ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
7548 ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
7549 ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
7550 ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
7551 ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
7553 /* Different captialization rules in sub_basic... */
7555 ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
7556 "blaDOM") == 0);
7558 return ok;
7561 static bool run_local_base64(int dummy)
7563 int i;
7564 bool ret = true;
7566 for (i=1; i<2000; i++) {
7567 DATA_BLOB blob1, blob2;
7568 char *b64;
7570 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
7571 blob1.length = i;
7572 generate_random_buffer(blob1.data, blob1.length);
7574 b64 = base64_encode_data_blob(talloc_tos(), blob1);
7575 if (b64 == NULL) {
7576 d_fprintf(stderr, "base64_encode_data_blob failed "
7577 "for %d bytes\n", i);
7578 ret = false;
7580 blob2 = base64_decode_data_blob(b64);
7581 TALLOC_FREE(b64);
7583 if (data_blob_cmp(&blob1, &blob2)) {
7584 d_fprintf(stderr, "data_blob_cmp failed for %d "
7585 "bytes\n", i);
7586 ret = false;
7588 TALLOC_FREE(blob1.data);
7589 data_blob_free(&blob2);
7591 return ret;
7594 static bool run_local_gencache(int dummy)
7596 char *val;
7597 time_t tm;
7598 DATA_BLOB blob;
7600 if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
7601 d_printf("%s: gencache_set() failed\n", __location__);
7602 return False;
7605 if (!gencache_get("foo", NULL, NULL)) {
7606 d_printf("%s: gencache_get() failed\n", __location__);
7607 return False;
7610 if (!gencache_get("foo", &val, &tm)) {
7611 d_printf("%s: gencache_get() failed\n", __location__);
7612 return False;
7615 if (strcmp(val, "bar") != 0) {
7616 d_printf("%s: gencache_get() returned %s, expected %s\n",
7617 __location__, val, "bar");
7618 SAFE_FREE(val);
7619 return False;
7622 SAFE_FREE(val);
7624 if (!gencache_del("foo")) {
7625 d_printf("%s: gencache_del() failed\n", __location__);
7626 return False;
7628 if (gencache_del("foo")) {
7629 d_printf("%s: second gencache_del() succeeded\n",
7630 __location__);
7631 return False;
7634 if (gencache_get("foo", &val, &tm)) {
7635 d_printf("%s: gencache_get() on deleted entry "
7636 "succeeded\n", __location__);
7637 return False;
7640 blob = data_blob_string_const_null("bar");
7641 tm = time(NULL) + 60;
7643 if (!gencache_set_data_blob("foo", &blob, tm)) {
7644 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
7645 return False;
7648 if (!gencache_get_data_blob("foo", &blob, NULL, NULL)) {
7649 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
7650 return False;
7653 if (strcmp((const char *)blob.data, "bar") != 0) {
7654 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
7655 __location__, (const char *)blob.data, "bar");
7656 data_blob_free(&blob);
7657 return False;
7660 data_blob_free(&blob);
7662 if (!gencache_del("foo")) {
7663 d_printf("%s: gencache_del() failed\n", __location__);
7664 return False;
7666 if (gencache_del("foo")) {
7667 d_printf("%s: second gencache_del() succeeded\n",
7668 __location__);
7669 return False;
7672 if (gencache_get_data_blob("foo", &blob, NULL, NULL)) {
7673 d_printf("%s: gencache_get_data_blob() on deleted entry "
7674 "succeeded\n", __location__);
7675 return False;
7678 return True;
7681 static bool rbt_testval(struct db_context *db, const char *key,
7682 const char *value)
7684 struct db_record *rec;
7685 TDB_DATA data = string_tdb_data(value);
7686 bool ret = false;
7687 NTSTATUS status;
7689 rec = db->fetch_locked(db, db, string_tdb_data(key));
7690 if (rec == NULL) {
7691 d_fprintf(stderr, "fetch_locked failed\n");
7692 goto done;
7694 status = rec->store(rec, data, 0);
7695 if (!NT_STATUS_IS_OK(status)) {
7696 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
7697 goto done;
7699 TALLOC_FREE(rec);
7701 rec = db->fetch_locked(db, db, string_tdb_data(key));
7702 if (rec == NULL) {
7703 d_fprintf(stderr, "second fetch_locked failed\n");
7704 goto done;
7706 if ((rec->value.dsize != data.dsize)
7707 || (memcmp(rec->value.dptr, data.dptr, data.dsize) != 0)) {
7708 d_fprintf(stderr, "Got wrong data back\n");
7709 goto done;
7712 ret = true;
7713 done:
7714 TALLOC_FREE(rec);
7715 return ret;
7718 static bool run_local_rbtree(int dummy)
7720 struct db_context *db;
7721 bool ret = false;
7722 int i;
7724 db = db_open_rbt(NULL);
7726 if (db == NULL) {
7727 d_fprintf(stderr, "db_open_rbt failed\n");
7728 return false;
7731 for (i=0; i<1000; i++) {
7732 char *key, *value;
7734 if (asprintf(&key, "key%ld", random()) == -1) {
7735 goto done;
7737 if (asprintf(&value, "value%ld", random()) == -1) {
7738 SAFE_FREE(key);
7739 goto done;
7742 if (!rbt_testval(db, key, value)) {
7743 SAFE_FREE(key);
7744 SAFE_FREE(value);
7745 goto done;
7748 SAFE_FREE(value);
7749 if (asprintf(&value, "value%ld", random()) == -1) {
7750 SAFE_FREE(key);
7751 goto done;
7754 if (!rbt_testval(db, key, value)) {
7755 SAFE_FREE(key);
7756 SAFE_FREE(value);
7757 goto done;
7760 SAFE_FREE(key);
7761 SAFE_FREE(value);
7764 ret = true;
7766 done:
7767 TALLOC_FREE(db);
7768 return ret;
7773 local test for character set functions
7775 This is a very simple test for the functionality in convert_string_error()
7777 static bool run_local_convert_string(int dummy)
7779 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
7780 const char *test_strings[2] = { "March", "M\303\244rz" };
7781 char dst[7];
7782 int i;
7784 for (i=0; i<2; i++) {
7785 const char *str = test_strings[i];
7786 int len = strlen(str);
7787 size_t converted_size;
7788 bool ret;
7790 memset(dst, 'X', sizeof(dst));
7792 /* first try with real source length */
7793 ret = convert_string_error(CH_UNIX, CH_UTF8,
7794 str, len,
7795 dst, sizeof(dst),
7796 &converted_size);
7797 if (ret != true) {
7798 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
7799 goto failed;
7802 if (converted_size != len) {
7803 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
7804 str, len, (int)converted_size);
7805 goto failed;
7808 if (strncmp(str, dst, converted_size) != 0) {
7809 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
7810 goto failed;
7813 if (strlen(str) != converted_size) {
7814 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
7815 (int)strlen(str), (int)converted_size);
7816 goto failed;
7819 if (dst[converted_size] != 'X') {
7820 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
7821 goto failed;
7824 /* now with srclen==-1, this causes the nul to be
7825 * converted too */
7826 ret = convert_string_error(CH_UNIX, CH_UTF8,
7827 str, -1,
7828 dst, sizeof(dst),
7829 &converted_size);
7830 if (ret != true) {
7831 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
7832 goto failed;
7835 if (converted_size != len+1) {
7836 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
7837 str, len, (int)converted_size);
7838 goto failed;
7841 if (strncmp(str, dst, converted_size) != 0) {
7842 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
7843 goto failed;
7846 if (len+1 != converted_size) {
7847 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
7848 len+1, (int)converted_size);
7849 goto failed;
7852 if (dst[converted_size] != 'X') {
7853 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
7854 goto failed;
7860 TALLOC_FREE(tmp_ctx);
7861 return true;
7862 failed:
7863 TALLOC_FREE(tmp_ctx);
7864 return false;
7868 struct talloc_dict_test {
7869 int content;
7872 static int talloc_dict_traverse_fn(DATA_BLOB key, void *data, void *priv)
7874 int *count = (int *)priv;
7875 *count += 1;
7876 return 0;
7879 static bool run_local_talloc_dict(int dummy)
7881 struct talloc_dict *dict;
7882 struct talloc_dict_test *t;
7883 int key, count;
7885 dict = talloc_dict_init(talloc_tos());
7886 if (dict == NULL) {
7887 return false;
7890 t = talloc(talloc_tos(), struct talloc_dict_test);
7891 if (t == NULL) {
7892 return false;
7895 key = 1;
7896 t->content = 1;
7897 if (!talloc_dict_set(dict, data_blob_const(&key, sizeof(key)), t)) {
7898 return false;
7901 count = 0;
7902 if (talloc_dict_traverse(dict, talloc_dict_traverse_fn, &count) != 0) {
7903 return false;
7906 if (count != 1) {
7907 return false;
7910 TALLOC_FREE(dict);
7912 return true;
7915 static bool run_local_string_to_sid(int dummy) {
7916 struct dom_sid sid;
7918 if (string_to_sid(&sid, "S--1-5-32-545")) {
7919 printf("allowing S--1-5-32-545\n");
7920 return false;
7922 if (string_to_sid(&sid, "S-1-5-32-+545")) {
7923 printf("allowing S-1-5-32-+545\n");
7924 return false;
7926 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")) {
7927 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
7928 return false;
7930 if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
7931 printf("allowing S-1-5-32-545-abc\n");
7932 return false;
7934 if (!string_to_sid(&sid, "S-1-5-32-545")) {
7935 printf("could not parse S-1-5-32-545\n");
7936 return false;
7938 if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
7939 printf("mis-parsed S-1-5-32-545 as %s\n",
7940 sid_string_tos(&sid));
7941 return false;
7943 return true;
7946 static bool run_local_binary_to_sid(int dummy) {
7947 struct dom_sid *sid = talloc(NULL, struct dom_sid);
7948 static const char good_binary_sid[] = {
7949 0x1, /* revision number */
7950 15, /* num auths */
7951 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
7952 0x1, 0x1, 0x1, 0x1, /* auth[0] */
7953 0x1, 0x1, 0x1, 0x1, /* auth[1] */
7954 0x1, 0x1, 0x1, 0x1, /* auth[2] */
7955 0x1, 0x1, 0x1, 0x1, /* auth[3] */
7956 0x1, 0x1, 0x1, 0x1, /* auth[4] */
7957 0x1, 0x1, 0x1, 0x1, /* auth[5] */
7958 0x1, 0x1, 0x1, 0x1, /* auth[6] */
7959 0x1, 0x1, 0x1, 0x1, /* auth[7] */
7960 0x1, 0x1, 0x1, 0x1, /* auth[8] */
7961 0x1, 0x1, 0x1, 0x1, /* auth[9] */
7962 0x1, 0x1, 0x1, 0x1, /* auth[10] */
7963 0x1, 0x1, 0x1, 0x1, /* auth[11] */
7964 0x1, 0x1, 0x1, 0x1, /* auth[12] */
7965 0x1, 0x1, 0x1, 0x1, /* auth[13] */
7966 0x1, 0x1, 0x1, 0x1, /* auth[14] */
7969 static const char long_binary_sid[] = {
7970 0x1, /* revision number */
7971 15, /* num auths */
7972 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
7973 0x1, 0x1, 0x1, 0x1, /* auth[0] */
7974 0x1, 0x1, 0x1, 0x1, /* auth[1] */
7975 0x1, 0x1, 0x1, 0x1, /* auth[2] */
7976 0x1, 0x1, 0x1, 0x1, /* auth[3] */
7977 0x1, 0x1, 0x1, 0x1, /* auth[4] */
7978 0x1, 0x1, 0x1, 0x1, /* auth[5] */
7979 0x1, 0x1, 0x1, 0x1, /* auth[6] */
7980 0x1, 0x1, 0x1, 0x1, /* auth[7] */
7981 0x1, 0x1, 0x1, 0x1, /* auth[8] */
7982 0x1, 0x1, 0x1, 0x1, /* auth[9] */
7983 0x1, 0x1, 0x1, 0x1, /* auth[10] */
7984 0x1, 0x1, 0x1, 0x1, /* auth[11] */
7985 0x1, 0x1, 0x1, 0x1, /* auth[12] */
7986 0x1, 0x1, 0x1, 0x1, /* auth[13] */
7987 0x1, 0x1, 0x1, 0x1, /* auth[14] */
7988 0x1, 0x1, 0x1, 0x1, /* auth[15] */
7989 0x1, 0x1, 0x1, 0x1, /* auth[16] */
7990 0x1, 0x1, 0x1, 0x1, /* auth[17] */
7993 static const char long_binary_sid2[] = {
7994 0x1, /* revision number */
7995 32, /* num auths */
7996 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
7997 0x1, 0x1, 0x1, 0x1, /* auth[0] */
7998 0x1, 0x1, 0x1, 0x1, /* auth[1] */
7999 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8000 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8001 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8002 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8003 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8004 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8005 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8006 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8007 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8008 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8009 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8010 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8011 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8012 0x1, 0x1, 0x1, 0x1, /* auth[15] */
8013 0x1, 0x1, 0x1, 0x1, /* auth[16] */
8014 0x1, 0x1, 0x1, 0x1, /* auth[17] */
8015 0x1, 0x1, 0x1, 0x1, /* auth[18] */
8016 0x1, 0x1, 0x1, 0x1, /* auth[19] */
8017 0x1, 0x1, 0x1, 0x1, /* auth[20] */
8018 0x1, 0x1, 0x1, 0x1, /* auth[21] */
8019 0x1, 0x1, 0x1, 0x1, /* auth[22] */
8020 0x1, 0x1, 0x1, 0x1, /* auth[23] */
8021 0x1, 0x1, 0x1, 0x1, /* auth[24] */
8022 0x1, 0x1, 0x1, 0x1, /* auth[25] */
8023 0x1, 0x1, 0x1, 0x1, /* auth[26] */
8024 0x1, 0x1, 0x1, 0x1, /* auth[27] */
8025 0x1, 0x1, 0x1, 0x1, /* auth[28] */
8026 0x1, 0x1, 0x1, 0x1, /* auth[29] */
8027 0x1, 0x1, 0x1, 0x1, /* auth[30] */
8028 0x1, 0x1, 0x1, 0x1, /* auth[31] */
8031 if (!sid_parse(good_binary_sid, sizeof(good_binary_sid), sid)) {
8032 return false;
8034 if (sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid)) {
8035 return false;
8037 if (sid_parse(long_binary_sid, sizeof(long_binary_sid), sid)) {
8038 return false;
8040 return true;
8043 /* Split a path name into filename and stream name components. Canonicalise
8044 * such that an implicit $DATA token is always explicit.
8046 * The "specification" of this function can be found in the
8047 * run_local_stream_name() function in torture.c, I've tried those
8048 * combinations against a W2k3 server.
8051 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
8052 char **pbase, char **pstream)
8054 char *base = NULL;
8055 char *stream = NULL;
8056 char *sname; /* stream name */
8057 const char *stype; /* stream type */
8059 DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
8061 sname = strchr_m(fname, ':');
8063 if (lp_posix_pathnames() || (sname == NULL)) {
8064 if (pbase != NULL) {
8065 base = talloc_strdup(mem_ctx, fname);
8066 NT_STATUS_HAVE_NO_MEMORY(base);
8068 goto done;
8071 if (pbase != NULL) {
8072 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
8073 NT_STATUS_HAVE_NO_MEMORY(base);
8076 sname += 1;
8078 stype = strchr_m(sname, ':');
8080 if (stype == NULL) {
8081 sname = talloc_strdup(mem_ctx, sname);
8082 stype = "$DATA";
8084 else {
8085 if (strcasecmp_m(stype, ":$DATA") != 0) {
8087 * If there is an explicit stream type, so far we only
8088 * allow $DATA. Is there anything else allowed? -- vl
8090 DEBUG(10, ("[%s] is an invalid stream type\n", stype));
8091 TALLOC_FREE(base);
8092 return NT_STATUS_OBJECT_NAME_INVALID;
8094 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
8095 stype += 1;
8098 if (sname == NULL) {
8099 TALLOC_FREE(base);
8100 return NT_STATUS_NO_MEMORY;
8103 if (sname[0] == '\0') {
8105 * no stream name, so no stream
8107 goto done;
8110 if (pstream != NULL) {
8111 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
8112 if (stream == NULL) {
8113 TALLOC_FREE(sname);
8114 TALLOC_FREE(base);
8115 return NT_STATUS_NO_MEMORY;
8118 * upper-case the type field
8120 strupper_m(strchr_m(stream, ':')+1);
8123 done:
8124 if (pbase != NULL) {
8125 *pbase = base;
8127 if (pstream != NULL) {
8128 *pstream = stream;
8130 return NT_STATUS_OK;
8133 static bool test_stream_name(const char *fname, const char *expected_base,
8134 const char *expected_stream,
8135 NTSTATUS expected_status)
8137 NTSTATUS status;
8138 char *base = NULL;
8139 char *stream = NULL;
8141 status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
8142 if (!NT_STATUS_EQUAL(status, expected_status)) {
8143 goto error;
8146 if (!NT_STATUS_IS_OK(status)) {
8147 return true;
8150 if (base == NULL) goto error;
8152 if (strcmp(expected_base, base) != 0) goto error;
8154 if ((expected_stream != NULL) && (stream == NULL)) goto error;
8155 if ((expected_stream == NULL) && (stream != NULL)) goto error;
8157 if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
8158 goto error;
8160 TALLOC_FREE(base);
8161 TALLOC_FREE(stream);
8162 return true;
8164 error:
8165 d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
8166 fname, expected_base ? expected_base : "<NULL>",
8167 expected_stream ? expected_stream : "<NULL>",
8168 nt_errstr(expected_status));
8169 d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
8170 base ? base : "<NULL>", stream ? stream : "<NULL>",
8171 nt_errstr(status));
8172 TALLOC_FREE(base);
8173 TALLOC_FREE(stream);
8174 return false;
8177 static bool run_local_stream_name(int dummy)
8179 bool ret = true;
8181 ret &= test_stream_name(
8182 "bla", "bla", NULL, NT_STATUS_OK);
8183 ret &= test_stream_name(
8184 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
8185 ret &= test_stream_name(
8186 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8187 ret &= test_stream_name(
8188 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
8189 ret &= test_stream_name(
8190 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8191 ret &= test_stream_name(
8192 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
8193 ret &= test_stream_name(
8194 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
8195 ret &= test_stream_name(
8196 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
8198 return ret;
8201 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
8203 if (a.length != b.length) {
8204 printf("a.length=%d != b.length=%d\n",
8205 (int)a.length, (int)b.length);
8206 return false;
8208 if (memcmp(a.data, b.data, a.length) != 0) {
8209 printf("a.data and b.data differ\n");
8210 return false;
8212 return true;
8215 static bool run_local_memcache(int dummy)
8217 struct memcache *cache;
8218 DATA_BLOB k1, k2;
8219 DATA_BLOB d1, d2, d3;
8220 DATA_BLOB v1, v2, v3;
8222 TALLOC_CTX *mem_ctx;
8223 char *str1, *str2;
8224 size_t size1, size2;
8225 bool ret = false;
8227 cache = memcache_init(NULL, 100);
8229 if (cache == NULL) {
8230 printf("memcache_init failed\n");
8231 return false;
8234 d1 = data_blob_const("d1", 2);
8235 d2 = data_blob_const("d2", 2);
8236 d3 = data_blob_const("d3", 2);
8238 k1 = data_blob_const("d1", 2);
8239 k2 = data_blob_const("d2", 2);
8241 memcache_add(cache, STAT_CACHE, k1, d1);
8242 memcache_add(cache, GETWD_CACHE, k2, d2);
8244 if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
8245 printf("could not find k1\n");
8246 return false;
8248 if (!data_blob_equal(d1, v1)) {
8249 return false;
8252 if (!memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8253 printf("could not find k2\n");
8254 return false;
8256 if (!data_blob_equal(d2, v2)) {
8257 return false;
8260 memcache_add(cache, STAT_CACHE, k1, d3);
8262 if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
8263 printf("could not find replaced k1\n");
8264 return false;
8266 if (!data_blob_equal(d3, v3)) {
8267 return false;
8270 memcache_add(cache, GETWD_CACHE, k1, d1);
8272 if (memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8273 printf("Did find k2, should have been purged\n");
8274 return false;
8277 TALLOC_FREE(cache);
8279 cache = memcache_init(NULL, 0);
8281 mem_ctx = talloc_init("foo");
8283 str1 = talloc_strdup(mem_ctx, "string1");
8284 str2 = talloc_strdup(mem_ctx, "string2");
8286 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8287 data_blob_string_const("torture"), &str1);
8288 size1 = talloc_total_size(cache);
8290 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8291 data_blob_string_const("torture"), &str2);
8292 size2 = talloc_total_size(cache);
8294 printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
8296 if (size2 > size1) {
8297 printf("memcache leaks memory!\n");
8298 goto fail;
8301 ret = true;
8302 fail:
8303 TALLOC_FREE(cache);
8304 return ret;
8307 static void wbclient_done(struct tevent_req *req)
8309 wbcErr wbc_err;
8310 struct winbindd_response *wb_resp;
8311 int *i = (int *)tevent_req_callback_data_void(req);
8313 wbc_err = wb_trans_recv(req, req, &wb_resp);
8314 TALLOC_FREE(req);
8315 *i += 1;
8316 d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
8319 static bool run_local_wbclient(int dummy)
8321 struct event_context *ev;
8322 struct wb_context **wb_ctx;
8323 struct winbindd_request wb_req;
8324 bool result = false;
8325 int i, j;
8327 BlockSignals(True, SIGPIPE);
8329 ev = tevent_context_init_byname(talloc_tos(), "epoll");
8330 if (ev == NULL) {
8331 goto fail;
8334 wb_ctx = talloc_array(ev, struct wb_context *, nprocs);
8335 if (wb_ctx == NULL) {
8336 goto fail;
8339 ZERO_STRUCT(wb_req);
8340 wb_req.cmd = WINBINDD_PING;
8342 d_printf("nprocs=%d, numops=%d\n", (int)nprocs, (int)torture_numops);
8344 for (i=0; i<nprocs; i++) {
8345 wb_ctx[i] = wb_context_init(ev, NULL);
8346 if (wb_ctx[i] == NULL) {
8347 goto fail;
8349 for (j=0; j<torture_numops; j++) {
8350 struct tevent_req *req;
8351 req = wb_trans_send(ev, ev, wb_ctx[i],
8352 (j % 2) == 0, &wb_req);
8353 if (req == NULL) {
8354 goto fail;
8356 tevent_req_set_callback(req, wbclient_done, &i);
8360 i = 0;
8362 while (i < nprocs * torture_numops) {
8363 event_loop_once(ev);
8366 result = true;
8367 fail:
8368 TALLOC_FREE(ev);
8369 return result;
8372 static void getaddrinfo_finished(struct tevent_req *req)
8374 char *name = (char *)tevent_req_callback_data_void(req);
8375 struct addrinfo *ainfo;
8376 int res;
8378 res = getaddrinfo_recv(req, &ainfo);
8379 if (res != 0) {
8380 d_printf("gai(%s) returned %s\n", name, gai_strerror(res));
8381 return;
8383 d_printf("gai(%s) succeeded\n", name);
8384 freeaddrinfo(ainfo);
8387 static bool run_getaddrinfo_send(int dummy)
8389 TALLOC_CTX *frame = talloc_stackframe();
8390 struct fncall_context *ctx;
8391 struct tevent_context *ev;
8392 bool result = false;
8393 const char *names[4] = { "www.samba.org", "notfound.samba.org",
8394 "www.slashdot.org", "heise.de" };
8395 struct tevent_req *reqs[4];
8396 int i;
8398 ev = event_context_init(frame);
8399 if (ev == NULL) {
8400 goto fail;
8403 ctx = fncall_context_init(frame, 4);
8405 for (i=0; i<ARRAY_SIZE(names); i++) {
8406 reqs[i] = getaddrinfo_send(frame, ev, ctx, names[i], NULL,
8407 NULL);
8408 if (reqs[i] == NULL) {
8409 goto fail;
8411 tevent_req_set_callback(reqs[i], getaddrinfo_finished,
8412 discard_const_p(void, names[i]));
8415 for (i=0; i<ARRAY_SIZE(reqs); i++) {
8416 tevent_loop_once(ev);
8419 result = true;
8420 fail:
8421 TALLOC_FREE(frame);
8422 return result;
8425 static bool dbtrans_inc(struct db_context *db)
8427 struct db_record *rec;
8428 uint32_t *val;
8429 bool ret = false;
8430 NTSTATUS status;
8432 rec = db->fetch_locked(db, db, string_term_tdb_data("transtest"));
8433 if (rec == NULL) {
8434 printf(__location__ "fetch_lock failed\n");
8435 return false;
8438 if (rec->value.dsize != sizeof(uint32_t)) {
8439 printf(__location__ "value.dsize = %d\n",
8440 (int)rec->value.dsize);
8441 goto fail;
8444 val = (uint32_t *)rec->value.dptr;
8445 *val += 1;
8447 status = rec->store(rec, make_tdb_data((uint8_t *)val,
8448 sizeof(uint32_t)),
8450 if (!NT_STATUS_IS_OK(status)) {
8451 printf(__location__ "store failed: %s\n",
8452 nt_errstr(status));
8453 goto fail;
8456 ret = true;
8457 fail:
8458 TALLOC_FREE(rec);
8459 return ret;
8462 static bool run_local_dbtrans(int dummy)
8464 struct db_context *db;
8465 struct db_record *rec;
8466 NTSTATUS status;
8467 uint32_t initial;
8468 int res;
8470 db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
8471 O_RDWR|O_CREAT, 0600);
8472 if (db == NULL) {
8473 printf("Could not open transtest.db\n");
8474 return false;
8477 res = db->transaction_start(db);
8478 if (res != 0) {
8479 printf(__location__ "transaction_start failed\n");
8480 return false;
8483 rec = db->fetch_locked(db, db, string_term_tdb_data("transtest"));
8484 if (rec == NULL) {
8485 printf(__location__ "fetch_lock failed\n");
8486 return false;
8489 if (rec->value.dptr == NULL) {
8490 initial = 0;
8491 status = rec->store(
8492 rec, make_tdb_data((uint8_t *)&initial,
8493 sizeof(initial)),
8495 if (!NT_STATUS_IS_OK(status)) {
8496 printf(__location__ "store returned %s\n",
8497 nt_errstr(status));
8498 return false;
8502 TALLOC_FREE(rec);
8504 res = db->transaction_commit(db);
8505 if (res != 0) {
8506 printf(__location__ "transaction_commit failed\n");
8507 return false;
8510 while (true) {
8511 uint32_t val, val2;
8512 int i;
8514 res = db->transaction_start(db);
8515 if (res != 0) {
8516 printf(__location__ "transaction_start failed\n");
8517 break;
8520 if (!dbwrap_fetch_uint32(db, "transtest", &val)) {
8521 printf(__location__ "dbwrap_fetch_uint32 failed\n");
8522 break;
8525 for (i=0; i<10; i++) {
8526 if (!dbtrans_inc(db)) {
8527 return false;
8531 if (!dbwrap_fetch_uint32(db, "transtest", &val2)) {
8532 printf(__location__ "dbwrap_fetch_uint32 failed\n");
8533 break;
8536 if (val2 != val + 10) {
8537 printf(__location__ "val=%d, val2=%d\n",
8538 (int)val, (int)val2);
8539 break;
8542 printf("val2=%d\r", val2);
8544 res = db->transaction_commit(db);
8545 if (res != 0) {
8546 printf(__location__ "transaction_commit failed\n");
8547 break;
8551 TALLOC_FREE(db);
8552 return true;
8556 * Just a dummy test to be run under a debugger. There's no real way
8557 * to inspect the tevent_select specific function from outside of
8558 * tevent_select.c.
8561 static bool run_local_tevent_select(int dummy)
8563 struct tevent_context *ev;
8564 struct tevent_fd *fd1, *fd2;
8565 bool result = false;
8567 ev = tevent_context_init_byname(NULL, "select");
8568 if (ev == NULL) {
8569 d_fprintf(stderr, "tevent_context_init_byname failed\n");
8570 goto fail;
8573 fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
8574 if (fd1 == NULL) {
8575 d_fprintf(stderr, "tevent_add_fd failed\n");
8576 goto fail;
8578 fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
8579 if (fd2 == NULL) {
8580 d_fprintf(stderr, "tevent_add_fd failed\n");
8581 goto fail;
8583 TALLOC_FREE(fd2);
8585 fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
8586 if (fd2 == NULL) {
8587 d_fprintf(stderr, "tevent_add_fd failed\n");
8588 goto fail;
8591 result = true;
8592 fail:
8593 TALLOC_FREE(ev);
8594 return result;
8597 static double create_procs(bool (*fn)(int), bool *result)
8599 int i, status;
8600 volatile pid_t *child_status;
8601 volatile bool *child_status_out;
8602 int synccount;
8603 int tries = 8;
8604 struct timeval start;
8606 synccount = 0;
8608 child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*nprocs);
8609 if (!child_status) {
8610 printf("Failed to setup shared memory\n");
8611 return -1;
8614 child_status_out = (volatile bool *)shm_setup(sizeof(bool)*nprocs);
8615 if (!child_status_out) {
8616 printf("Failed to setup result status shared memory\n");
8617 return -1;
8620 for (i = 0; i < nprocs; i++) {
8621 child_status[i] = 0;
8622 child_status_out[i] = True;
8625 start = timeval_current();
8627 for (i=0;i<nprocs;i++) {
8628 procnum = i;
8629 if (fork() == 0) {
8630 pid_t mypid = getpid();
8631 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
8633 slprintf(myname,sizeof(myname),"CLIENT%d", i);
8635 while (1) {
8636 if (torture_open_connection(&current_cli, i)) break;
8637 if (tries-- == 0) {
8638 printf("pid %d failed to start\n", (int)getpid());
8639 _exit(1);
8641 smb_msleep(10);
8644 child_status[i] = getpid();
8646 while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
8648 child_status_out[i] = fn(i);
8649 _exit(0);
8653 do {
8654 synccount = 0;
8655 for (i=0;i<nprocs;i++) {
8656 if (child_status[i]) synccount++;
8658 if (synccount == nprocs) break;
8659 smb_msleep(10);
8660 } while (timeval_elapsed(&start) < 30);
8662 if (synccount != nprocs) {
8663 printf("FAILED TO START %d CLIENTS (started %d)\n", nprocs, synccount);
8664 *result = False;
8665 return timeval_elapsed(&start);
8668 /* start the client load */
8669 start = timeval_current();
8671 for (i=0;i<nprocs;i++) {
8672 child_status[i] = 0;
8675 printf("%d clients started\n", nprocs);
8677 for (i=0;i<nprocs;i++) {
8678 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
8681 printf("\n");
8683 for (i=0;i<nprocs;i++) {
8684 if (!child_status_out[i]) {
8685 *result = False;
8688 return timeval_elapsed(&start);
8691 #define FLAG_MULTIPROC 1
8693 static struct {
8694 const char *name;
8695 bool (*fn)(int);
8696 unsigned flags;
8697 } torture_ops[] = {
8698 {"FDPASS", run_fdpasstest, 0},
8699 {"LOCK1", run_locktest1, 0},
8700 {"LOCK2", run_locktest2, 0},
8701 {"LOCK3", run_locktest3, 0},
8702 {"LOCK4", run_locktest4, 0},
8703 {"LOCK5", run_locktest5, 0},
8704 {"LOCK6", run_locktest6, 0},
8705 {"LOCK7", run_locktest7, 0},
8706 {"LOCK8", run_locktest8, 0},
8707 {"LOCK9", run_locktest9, 0},
8708 {"UNLINK", run_unlinktest, 0},
8709 {"BROWSE", run_browsetest, 0},
8710 {"ATTR", run_attrtest, 0},
8711 {"TRANS2", run_trans2test, 0},
8712 {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
8713 {"TORTURE",run_torture, FLAG_MULTIPROC},
8714 {"RANDOMIPC", run_randomipc, 0},
8715 {"NEGNOWAIT", run_negprot_nowait, 0},
8716 {"NBENCH", run_nbench, 0},
8717 {"NBENCH2", run_nbench2, 0},
8718 {"OPLOCK1", run_oplock1, 0},
8719 {"OPLOCK2", run_oplock2, 0},
8720 {"OPLOCK4", run_oplock4, 0},
8721 {"DIR", run_dirtest, 0},
8722 {"DIR1", run_dirtest1, 0},
8723 {"DIR-CREATETIME", run_dir_createtime, 0},
8724 {"DENY1", torture_denytest1, 0},
8725 {"DENY2", torture_denytest2, 0},
8726 {"TCON", run_tcon_test, 0},
8727 {"TCONDEV", run_tcon_devtype_test, 0},
8728 {"RW1", run_readwritetest, 0},
8729 {"RW2", run_readwritemulti, FLAG_MULTIPROC},
8730 {"RW3", run_readwritelarge, 0},
8731 {"RW-SIGNING", run_readwritelarge_signtest, 0},
8732 {"OPEN", run_opentest, 0},
8733 {"POSIX", run_simple_posix_open_test, 0},
8734 {"POSIX-APPEND", run_posix_append, 0},
8735 {"CASE-INSENSITIVE-CREATE", run_case_insensitive_create, 0},
8736 {"ASYNC-ECHO", run_async_echo, 0},
8737 { "UID-REGRESSION-TEST", run_uid_regression_test, 0},
8738 { "SHORTNAME-TEST", run_shortname_test, 0},
8739 { "ADDRCHANGE", run_addrchange, 0},
8740 #if 1
8741 {"OPENATTR", run_openattrtest, 0},
8742 #endif
8743 {"XCOPY", run_xcopy, 0},
8744 {"RENAME", run_rename, 0},
8745 {"DELETE", run_deletetest, 0},
8746 {"DELETE-LN", run_deletetest_ln, 0},
8747 {"PROPERTIES", run_properties, 0},
8748 {"MANGLE", torture_mangle, 0},
8749 {"MANGLE1", run_mangle1, 0},
8750 {"W2K", run_w2ktest, 0},
8751 {"TRANS2SCAN", torture_trans2_scan, 0},
8752 {"NTTRANSSCAN", torture_nttrans_scan, 0},
8753 {"UTABLE", torture_utable, 0},
8754 {"CASETABLE", torture_casetable, 0},
8755 {"ERRMAPEXTRACT", run_error_map_extract, 0},
8756 {"PIPE_NUMBER", run_pipe_number, 0},
8757 {"TCON2", run_tcon2_test, 0},
8758 {"IOCTL", torture_ioctl_test, 0},
8759 {"CHKPATH", torture_chkpath_test, 0},
8760 {"FDSESS", run_fdsesstest, 0},
8761 { "EATEST", run_eatest, 0},
8762 { "SESSSETUP_BENCH", run_sesssetup_bench, 0},
8763 { "CHAIN1", run_chain1, 0},
8764 { "CHAIN2", run_chain2, 0},
8765 { "WINDOWS-WRITE", run_windows_write, 0},
8766 { "NTTRANS-CREATE", run_nttrans_create, 0},
8767 { "CLI_ECHO", run_cli_echo, 0},
8768 { "GETADDRINFO", run_getaddrinfo_send, 0},
8769 { "TLDAP", run_tldap },
8770 { "STREAMERROR", run_streamerror },
8771 { "NOTIFY-BENCH", run_notify_bench },
8772 { "BAD-NBT-SESSION", run_bad_nbt_session },
8773 { "SMB-ANY-CONNECT", run_smb_any_connect },
8774 { "NOTIFY-ONLINE", run_notify_online },
8775 { "SMB2-BASIC", run_smb2_basic },
8776 { "LOCAL-SUBSTITUTE", run_local_substitute, 0},
8777 { "LOCAL-GENCACHE", run_local_gencache, 0},
8778 { "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0},
8779 { "LOCAL-BASE64", run_local_base64, 0},
8780 { "LOCAL-RBTREE", run_local_rbtree, 0},
8781 { "LOCAL-MEMCACHE", run_local_memcache, 0},
8782 { "LOCAL-STREAM-NAME", run_local_stream_name, 0},
8783 { "LOCAL-WBCLIENT", run_local_wbclient, 0},
8784 { "LOCAL-string_to_sid", run_local_string_to_sid, 0},
8785 { "LOCAL-binary_to_sid", run_local_binary_to_sid, 0},
8786 { "LOCAL-DBTRANS", run_local_dbtrans, 0},
8787 { "LOCAL-TEVENT-SELECT", run_local_tevent_select, 0},
8788 { "LOCAL-CONVERT-STRING", run_local_convert_string, 0},
8789 {NULL, NULL, 0}};
8793 /****************************************************************************
8794 run a specified test or "ALL"
8795 ****************************************************************************/
8796 static bool run_test(const char *name)
8798 bool ret = True;
8799 bool result = True;
8800 bool found = False;
8801 int i;
8802 double t;
8803 if (strequal(name,"ALL")) {
8804 for (i=0;torture_ops[i].name;i++) {
8805 run_test(torture_ops[i].name);
8807 found = True;
8810 for (i=0;torture_ops[i].name;i++) {
8811 fstr_sprintf(randomfname, "\\XX%x",
8812 (unsigned)random());
8814 if (strequal(name, torture_ops[i].name)) {
8815 found = True;
8816 printf("Running %s\n", name);
8817 if (torture_ops[i].flags & FLAG_MULTIPROC) {
8818 t = create_procs(torture_ops[i].fn, &result);
8819 if (!result) {
8820 ret = False;
8821 printf("TEST %s FAILED!\n", name);
8823 } else {
8824 struct timeval start;
8825 start = timeval_current();
8826 if (!torture_ops[i].fn(0)) {
8827 ret = False;
8828 printf("TEST %s FAILED!\n", name);
8830 t = timeval_elapsed(&start);
8832 printf("%s took %g secs\n\n", name, t);
8836 if (!found) {
8837 printf("Did not find a test named %s\n", name);
8838 ret = False;
8841 return ret;
8845 static void usage(void)
8847 int i;
8849 printf("WARNING samba4 test suite is much more complete nowadays.\n");
8850 printf("Please use samba4 torture.\n\n");
8852 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
8854 printf("\t-d debuglevel\n");
8855 printf("\t-U user%%pass\n");
8856 printf("\t-k use kerberos\n");
8857 printf("\t-N numprocs\n");
8858 printf("\t-n my_netbios_name\n");
8859 printf("\t-W workgroup\n");
8860 printf("\t-o num_operations\n");
8861 printf("\t-O socket_options\n");
8862 printf("\t-m maximum protocol\n");
8863 printf("\t-L use oplocks\n");
8864 printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
8865 printf("\t-A showall\n");
8866 printf("\t-p port\n");
8867 printf("\t-s seed\n");
8868 printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
8869 printf("\t-f filename filename to test\n");
8870 printf("\n\n");
8872 printf("tests are:");
8873 for (i=0;torture_ops[i].name;i++) {
8874 printf(" %s", torture_ops[i].name);
8876 printf("\n");
8878 printf("default test is ALL\n");
8880 exit(1);
8883 /****************************************************************************
8884 main program
8885 ****************************************************************************/
8886 int main(int argc,char *argv[])
8888 int opt, i;
8889 char *p;
8890 int gotuser = 0;
8891 int gotpass = 0;
8892 bool correct = True;
8893 TALLOC_CTX *frame = talloc_stackframe();
8894 int seed = time(NULL);
8896 #ifdef HAVE_SETBUFFER
8897 setbuffer(stdout, NULL, 0);
8898 #endif
8900 setup_logging("smbtorture", DEBUG_STDOUT);
8902 load_case_tables();
8904 if (is_default_dyn_CONFIGFILE()) {
8905 if(getenv("SMB_CONF_PATH")) {
8906 set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
8909 lp_load(get_dyn_CONFIGFILE(),True,False,False,True);
8910 load_interfaces();
8912 if (argc < 2) {
8913 usage();
8916 for(p = argv[1]; *p; p++)
8917 if(*p == '\\')
8918 *p = '/';
8920 if (strncmp(argv[1], "//", 2)) {
8921 usage();
8924 fstrcpy(host, &argv[1][2]);
8925 p = strchr_m(&host[2],'/');
8926 if (!p) {
8927 usage();
8929 *p = 0;
8930 fstrcpy(share, p+1);
8932 fstrcpy(myname, get_myname(talloc_tos()));
8933 if (!*myname) {
8934 fprintf(stderr, "Failed to get my hostname.\n");
8935 return 1;
8938 if (*username == 0 && getenv("LOGNAME")) {
8939 fstrcpy(username,getenv("LOGNAME"));
8942 argc--;
8943 argv++;
8945 fstrcpy(workgroup, lp_workgroup());
8947 while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
8948 != EOF) {
8949 switch (opt) {
8950 case 'p':
8951 port_to_use = atoi(optarg);
8952 break;
8953 case 's':
8954 seed = atoi(optarg);
8955 break;
8956 case 'W':
8957 fstrcpy(workgroup,optarg);
8958 break;
8959 case 'm':
8960 max_protocol = interpret_protocol(optarg, max_protocol);
8961 break;
8962 case 'N':
8963 nprocs = atoi(optarg);
8964 break;
8965 case 'o':
8966 torture_numops = atoi(optarg);
8967 break;
8968 case 'd':
8969 lp_set_cmdline("log level", optarg);
8970 break;
8971 case 'O':
8972 sockops = optarg;
8973 break;
8974 case 'L':
8975 use_oplocks = True;
8976 break;
8977 case 'l':
8978 local_path = optarg;
8979 break;
8980 case 'A':
8981 torture_showall = True;
8982 break;
8983 case 'n':
8984 fstrcpy(myname, optarg);
8985 break;
8986 case 'c':
8987 client_txt = optarg;
8988 break;
8989 case 'e':
8990 do_encrypt = true;
8991 break;
8992 case 'k':
8993 #ifdef HAVE_KRB5
8994 use_kerberos = True;
8995 #else
8996 d_printf("No kerberos support compiled in\n");
8997 exit(1);
8998 #endif
8999 break;
9000 case 'U':
9001 gotuser = 1;
9002 fstrcpy(username,optarg);
9003 p = strchr_m(username,'%');
9004 if (p) {
9005 *p = 0;
9006 fstrcpy(password, p+1);
9007 gotpass = 1;
9009 break;
9010 case 'b':
9011 fstrcpy(multishare_conn_fname, optarg);
9012 use_multishare_conn = True;
9013 break;
9014 case 'B':
9015 torture_blocksize = atoi(optarg);
9016 break;
9017 case 'f':
9018 test_filename = SMB_STRDUP(optarg);
9019 break;
9020 default:
9021 printf("Unknown option %c (%d)\n", (char)opt, opt);
9022 usage();
9026 d_printf("using seed %d\n", seed);
9028 srandom(seed);
9030 if(use_kerberos && !gotuser) gotpass = True;
9032 while (!gotpass) {
9033 p = getpass("Password:");
9034 if (p) {
9035 fstrcpy(password, p);
9036 gotpass = 1;
9040 printf("host=%s share=%s user=%s myname=%s\n",
9041 host, share, username, myname);
9043 if (argc == optind) {
9044 correct = run_test("ALL");
9045 } else {
9046 for (i=optind;i<argc;i++) {
9047 if (!run_test(argv[i])) {
9048 correct = False;
9053 TALLOC_FREE(frame);
9055 if (correct) {
9056 return(0);
9057 } else {
9058 return(1);