s4-torture: remove unchecked read from smb2 create
[Samba/wip.git] / source3 / torture / torture.c
blob3eb6fec29482660b32614dfcb09a8108ac6ece4a
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/dbwrap.h"
32 #include "dbwrap/dbwrap_open.h"
33 #include "talloc_dict.h"
34 #include "async_smb.h"
35 #include "libsmb/libsmb.h"
36 #include "libsmb/clirap.h"
37 #include "trans2.h"
38 #include "libsmb/nmblib.h"
39 #include "../lib/util/tevent_ntstatus.h"
40 #include "util_tdb.h"
41 #include "libsmb/read_smb.h"
43 extern char *optarg;
44 extern int optind;
46 fstring host, workgroup, share, password, username, myname;
47 static int max_protocol = PROTOCOL_NT1;
48 static const char *sockops="TCP_NODELAY";
49 static int nprocs=1;
50 static int port_to_use=0;
51 int torture_numops=100;
52 int torture_blocksize=1024*1024;
53 static int procnum; /* records process count number when forking */
54 static struct cli_state *current_cli;
55 static fstring randomfname;
56 static bool use_oplocks;
57 static bool use_level_II_oplocks;
58 static const char *client_txt = "client_oplocks.txt";
59 static bool disable_spnego;
60 static bool use_kerberos;
61 static bool force_dos_errors;
62 static fstring multishare_conn_fname;
63 static bool use_multishare_conn = False;
64 static bool do_encrypt;
65 static const char *local_path = NULL;
66 static int signing_state = Undefined;
67 char *test_filename;
69 bool torture_showall = False;
71 static double create_procs(bool (*fn)(int), bool *result);
74 /* return a pointer to a anonymous shared memory segment of size "size"
75 which will persist across fork() but will disappear when all processes
76 exit
78 The memory is not zeroed
80 This function uses system5 shared memory. It takes advantage of a property
81 that the memory is not destroyed if it is attached when the id is removed
83 void *shm_setup(int size)
85 int shmid;
86 void *ret;
88 #ifdef __QNXNTO__
89 shmid = shm_open("private", O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
90 if (shmid == -1) {
91 printf("can't get shared memory\n");
92 exit(1);
94 shm_unlink("private");
95 if (ftruncate(shmid, size) == -1) {
96 printf("can't set shared memory size\n");
97 exit(1);
99 ret = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, shmid, 0);
100 if (ret == MAP_FAILED) {
101 printf("can't map shared memory\n");
102 exit(1);
104 #else
105 shmid = shmget(IPC_PRIVATE, size, S_IRUSR | S_IWUSR);
106 if (shmid == -1) {
107 printf("can't get shared memory\n");
108 exit(1);
110 ret = (void *)shmat(shmid, 0, 0);
111 if (!ret || ret == (void *)-1) {
112 printf("can't attach to shared memory\n");
113 return NULL;
115 /* the following releases the ipc, but note that this process
116 and all its children will still have access to the memory, its
117 just that the shmid is no longer valid for other shm calls. This
118 means we don't leave behind lots of shm segments after we exit
120 See Stevens "advanced programming in unix env" for details
122 shmctl(shmid, IPC_RMID, 0);
123 #endif
125 return ret;
128 /********************************************************************
129 Ensure a connection is encrypted.
130 ********************************************************************/
132 static bool force_cli_encryption(struct cli_state *c,
133 const char *sharename)
135 uint16 major, minor;
136 uint32 caplow, caphigh;
137 NTSTATUS status;
139 if (!SERVER_HAS_UNIX_CIFS(c)) {
140 d_printf("Encryption required and "
141 "server that doesn't support "
142 "UNIX extensions - failing connect\n");
143 return false;
146 status = cli_unix_extensions_version(c, &major, &minor, &caplow,
147 &caphigh);
148 if (!NT_STATUS_IS_OK(status)) {
149 d_printf("Encryption required and "
150 "can't get UNIX CIFS extensions "
151 "version from server: %s\n", nt_errstr(status));
152 return false;
155 if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
156 d_printf("Encryption required and "
157 "share %s doesn't support "
158 "encryption.\n", sharename);
159 return false;
162 if (c->use_kerberos) {
163 status = cli_gss_smb_encryption_start(c);
164 } else {
165 status = cli_raw_ntlm_smb_encryption_start(c,
166 username,
167 password,
168 workgroup);
171 if (!NT_STATUS_IS_OK(status)) {
172 d_printf("Encryption required and "
173 "setup failed with error %s.\n",
174 nt_errstr(status));
175 return false;
178 return true;
182 static struct cli_state *open_nbt_connection(void)
184 struct cli_state *c;
185 NTSTATUS status;
186 int flags = 0;
188 if (disable_spnego) {
189 flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
192 if (use_oplocks) {
193 flags |= CLI_FULL_CONNECTION_OPLOCKS;
196 if (use_level_II_oplocks) {
197 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
200 if (use_kerberos) {
201 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
204 if (force_dos_errors) {
205 flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
208 status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
209 signing_state, flags, &c);
210 if (!NT_STATUS_IS_OK(status)) {
211 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
212 return NULL;
215 cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
217 return c;
220 /****************************************************************************
221 Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
222 ****************************************************************************/
224 static bool cli_bad_session_request(int fd,
225 struct nmb_name *calling, struct nmb_name *called)
227 TALLOC_CTX *frame;
228 uint8_t len_buf[4];
229 struct iovec iov[3];
230 ssize_t len;
231 uint8_t *inbuf;
232 int err;
233 bool ret = false;
234 uint8_t message_type;
235 uint8_t error;
237 frame = talloc_stackframe();
239 iov[0].iov_base = len_buf;
240 iov[0].iov_len = sizeof(len_buf);
242 /* put in the destination name */
244 iov[1].iov_base = name_mangle(talloc_tos(), called->name,
245 called->name_type);
246 if (iov[1].iov_base == NULL) {
247 goto fail;
249 iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
250 talloc_get_size(iov[1].iov_base));
252 /* and my name */
254 iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
255 calling->name_type);
256 if (iov[2].iov_base == NULL) {
257 goto fail;
259 iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
260 talloc_get_size(iov[2].iov_base));
262 /* Deliberately corrupt the name len (first byte) */
263 *((uint8_t *)iov[2].iov_base) = 100;
265 /* send a session request (RFC 1002) */
266 /* setup the packet length
267 * Remove four bytes from the length count, since the length
268 * field in the NBT Session Service header counts the number
269 * of bytes which follow. The cli_send_smb() function knows
270 * about this and accounts for those four bytes.
271 * CRH.
274 _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
275 SCVAL(len_buf,0,0x81);
277 len = write_data_iov(fd, iov, 3);
278 if (len == -1) {
279 goto fail;
281 len = read_smb(fd, talloc_tos(), &inbuf, &err);
282 if (len == -1) {
283 errno = err;
284 goto fail;
287 message_type = CVAL(inbuf, 0);
288 if (message_type != 0x83) {
289 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
290 message_type);
291 goto fail;
294 if (smb_len(inbuf) != 1) {
295 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
296 (int)smb_len(inbuf));
297 goto fail;
300 error = CVAL(inbuf, 4);
301 if (error != 0x82) {
302 d_fprintf(stderr, "Expected error 0x82, got %d\n",
303 (int)error);
304 goto fail;
307 ret = true;
308 fail:
309 TALLOC_FREE(frame);
310 return ret;
313 /* Insert a NULL at the first separator of the given path and return a pointer
314 * to the remainder of the string.
316 static char *
317 terminate_path_at_separator(char * path)
319 char * p;
321 if (!path) {
322 return NULL;
325 if ((p = strchr_m(path, '/'))) {
326 *p = '\0';
327 return p + 1;
330 if ((p = strchr_m(path, '\\'))) {
331 *p = '\0';
332 return p + 1;
335 /* No separator. */
336 return NULL;
340 parse a //server/share type UNC name
342 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
343 char **hostname, char **sharename)
345 char *p;
347 *hostname = *sharename = NULL;
349 if (strncmp(unc_name, "\\\\", 2) &&
350 strncmp(unc_name, "//", 2)) {
351 return False;
354 *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
355 p = terminate_path_at_separator(*hostname);
357 if (p && *p) {
358 *sharename = talloc_strdup(mem_ctx, p);
359 terminate_path_at_separator(*sharename);
362 if (*hostname && *sharename) {
363 return True;
366 TALLOC_FREE(*hostname);
367 TALLOC_FREE(*sharename);
368 return False;
371 static bool torture_open_connection_share(struct cli_state **c,
372 const char *hostname,
373 const char *sharename)
375 int flags = 0;
376 NTSTATUS status;
378 if (use_kerberos)
379 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
380 if (use_oplocks)
381 flags |= CLI_FULL_CONNECTION_OPLOCKS;
382 if (use_level_II_oplocks)
383 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
385 status = cli_full_connection(c, myname,
386 hostname, NULL, port_to_use,
387 sharename, "?????",
388 username, workgroup,
389 password, flags, signing_state);
390 if (!NT_STATUS_IS_OK(status)) {
391 printf("failed to open share connection: //%s/%s port:%d - %s\n",
392 hostname, sharename, port_to_use, nt_errstr(status));
393 return False;
396 cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
398 if (do_encrypt) {
399 return force_cli_encryption(*c,
400 sharename);
402 return True;
405 bool torture_open_connection(struct cli_state **c, int conn_index)
407 char **unc_list = NULL;
408 int num_unc_names = 0;
409 bool result;
411 if (use_multishare_conn==True) {
412 char *h, *s;
413 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
414 if (!unc_list || num_unc_names <= 0) {
415 printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
416 exit(1);
419 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
420 NULL, &h, &s)) {
421 printf("Failed to parse UNC name %s\n",
422 unc_list[conn_index % num_unc_names]);
423 TALLOC_FREE(unc_list);
424 exit(1);
427 result = torture_open_connection_share(c, h, s);
429 /* h, s were copied earlier */
430 TALLOC_FREE(unc_list);
431 return result;
434 return torture_open_connection_share(c, host, share);
437 bool torture_init_connection(struct cli_state **pcli)
439 struct cli_state *cli;
441 cli = open_nbt_connection();
442 if (cli == NULL) {
443 return false;
446 *pcli = cli;
447 return true;
450 bool torture_cli_session_setup2(struct cli_state *cli, uint16 *new_vuid)
452 uint16_t old_vuid = cli_state_get_uid(cli);
453 fstring old_user_name;
454 size_t passlen = strlen(password);
455 NTSTATUS status;
456 bool ret;
458 fstrcpy(old_user_name, cli->user_name);
459 cli_state_set_uid(cli, 0);
460 ret = NT_STATUS_IS_OK(cli_session_setup(cli, username,
461 password, passlen,
462 password, passlen,
463 workgroup));
464 *new_vuid = cli_state_get_uid(cli);
465 cli_state_set_uid(cli, old_vuid);
466 status = cli_set_username(cli, old_user_name);
467 if (!NT_STATUS_IS_OK(status)) {
468 return false;
470 return ret;
474 bool torture_close_connection(struct cli_state *c)
476 bool ret = True;
477 NTSTATUS status;
479 status = cli_tdis(c);
480 if (!NT_STATUS_IS_OK(status)) {
481 printf("tdis failed (%s)\n", nt_errstr(status));
482 ret = False;
485 cli_shutdown(c);
487 return ret;
491 /* check if the server produced the expected dos or nt error code */
492 static bool check_both_error(int line, NTSTATUS status,
493 uint8 eclass, uint32 ecode, NTSTATUS nterr)
495 if (NT_STATUS_IS_DOS(status)) {
496 uint8 cclass;
497 uint32 num;
499 /* Check DOS error */
500 cclass = NT_STATUS_DOS_CLASS(status);
501 num = NT_STATUS_DOS_CODE(status);
503 if (eclass != cclass || ecode != num) {
504 printf("unexpected error code class=%d code=%d\n",
505 (int)cclass, (int)num);
506 printf(" expected %d/%d %s (line=%d)\n",
507 (int)eclass, (int)ecode, nt_errstr(nterr), line);
508 return false;
510 } else {
511 /* Check NT error */
512 if (!NT_STATUS_EQUAL(nterr, status)) {
513 printf("unexpected error code %s\n",
514 nt_errstr(status));
515 printf(" expected %s (line=%d)\n",
516 nt_errstr(nterr), line);
517 return false;
521 return true;
525 /* check if the server produced the expected error code */
526 static bool check_error(int line, NTSTATUS status,
527 uint8 eclass, uint32 ecode, NTSTATUS nterr)
529 if (NT_STATUS_IS_DOS(status)) {
530 uint8 cclass;
531 uint32 num;
533 /* Check DOS error */
535 cclass = NT_STATUS_DOS_CLASS(status);
536 num = NT_STATUS_DOS_CODE(status);
538 if (eclass != cclass || ecode != num) {
539 printf("unexpected error code class=%d code=%d\n",
540 (int)cclass, (int)num);
541 printf(" expected %d/%d %s (line=%d)\n",
542 (int)eclass, (int)ecode, nt_errstr(nterr),
543 line);
544 return False;
547 } else {
548 /* Check NT error */
550 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
551 printf("unexpected error code %s\n",
552 nt_errstr(status));
553 printf(" expected %s (line=%d)\n", nt_errstr(nterr),
554 line);
555 return False;
559 return True;
563 static bool wait_lock(struct cli_state *c, int fnum, uint32 offset, uint32 len)
565 NTSTATUS status;
567 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
569 while (!NT_STATUS_IS_OK(status)) {
570 if (!check_both_error(__LINE__, status, ERRDOS,
571 ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
572 return false;
575 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
578 return true;
582 static bool rw_torture(struct cli_state *c)
584 const char *lockfname = "\\torture.lck";
585 fstring fname;
586 uint16_t fnum;
587 uint16_t fnum2;
588 pid_t pid2, pid = getpid();
589 int i, j;
590 char buf[1024];
591 bool correct = True;
592 size_t nread = 0;
593 NTSTATUS status;
595 memset(buf, '\0', sizeof(buf));
597 status = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
598 DENY_NONE, &fnum2);
599 if (!NT_STATUS_IS_OK(status)) {
600 status = cli_open(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
602 if (!NT_STATUS_IS_OK(status)) {
603 printf("open of %s failed (%s)\n",
604 lockfname, nt_errstr(status));
605 return False;
608 for (i=0;i<torture_numops;i++) {
609 unsigned n = (unsigned)sys_random()%10;
611 if (i % 10 == 0) {
612 printf("%d\r", i); fflush(stdout);
614 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
616 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
617 return False;
620 status = cli_open(c, fname, O_RDWR | O_CREAT | O_TRUNC,
621 DENY_ALL, &fnum);
622 if (!NT_STATUS_IS_OK(status)) {
623 printf("open failed (%s)\n", nt_errstr(status));
624 correct = False;
625 break;
628 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
629 sizeof(pid), NULL);
630 if (!NT_STATUS_IS_OK(status)) {
631 printf("write failed (%s)\n", nt_errstr(status));
632 correct = False;
635 for (j=0;j<50;j++) {
636 status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
637 sizeof(pid)+(j*sizeof(buf)),
638 sizeof(buf), NULL);
639 if (!NT_STATUS_IS_OK(status)) {
640 printf("write failed (%s)\n",
641 nt_errstr(status));
642 correct = False;
646 pid2 = 0;
648 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
649 &nread);
650 if (!NT_STATUS_IS_OK(status)) {
651 printf("read failed (%s)\n", nt_errstr(status));
652 correct = false;
653 } else if (nread != sizeof(pid)) {
654 printf("read/write compare failed: "
655 "recv %ld req %ld\n", (unsigned long)nread,
656 (unsigned long)sizeof(pid));
657 correct = false;
660 if (pid2 != pid) {
661 printf("data corruption!\n");
662 correct = False;
665 status = cli_close(c, fnum);
666 if (!NT_STATUS_IS_OK(status)) {
667 printf("close failed (%s)\n", nt_errstr(status));
668 correct = False;
671 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
672 if (!NT_STATUS_IS_OK(status)) {
673 printf("unlink failed (%s)\n", nt_errstr(status));
674 correct = False;
677 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
678 if (!NT_STATUS_IS_OK(status)) {
679 printf("unlock failed (%s)\n", nt_errstr(status));
680 correct = False;
684 cli_close(c, fnum2);
685 cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
687 printf("%d\n", i);
689 return correct;
692 static bool run_torture(int dummy)
694 struct cli_state *cli;
695 bool ret;
697 cli = current_cli;
699 cli_sockopt(cli, sockops);
701 ret = rw_torture(cli);
703 if (!torture_close_connection(cli)) {
704 ret = False;
707 return ret;
710 static bool rw_torture3(struct cli_state *c, char *lockfname)
712 uint16_t fnum = (uint16_t)-1;
713 unsigned int i = 0;
714 char buf[131072];
715 char buf_rd[131072];
716 unsigned count;
717 unsigned countprev = 0;
718 size_t sent = 0;
719 bool correct = True;
720 NTSTATUS status = NT_STATUS_OK;
722 srandom(1);
723 for (i = 0; i < sizeof(buf); i += sizeof(uint32))
725 SIVAL(buf, i, sys_random());
728 if (procnum == 0)
730 status = cli_unlink(
731 c, lockfname,
732 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
733 if (!NT_STATUS_IS_OK(status)) {
734 printf("unlink failed (%s) (normal, this file should "
735 "not exist)\n", nt_errstr(status));
738 status = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
739 DENY_NONE, &fnum);
740 if (!NT_STATUS_IS_OK(status)) {
741 printf("first open read/write of %s failed (%s)\n",
742 lockfname, nt_errstr(status));
743 return False;
746 else
748 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
750 status = cli_open(c, lockfname, O_RDONLY,
751 DENY_NONE, &fnum);
752 if (!NT_STATUS_IS_OK(status)) {
753 break;
755 smb_msleep(10);
757 if (!NT_STATUS_IS_OK(status)) {
758 printf("second open read-only of %s failed (%s)\n",
759 lockfname, nt_errstr(status));
760 return False;
764 i = 0;
765 for (count = 0; count < sizeof(buf); count += sent)
767 if (count >= countprev) {
768 printf("%d %8d\r", i, count);
769 fflush(stdout);
770 i++;
771 countprev += (sizeof(buf) / 20);
774 if (procnum == 0)
776 sent = ((unsigned)sys_random()%(20))+ 1;
777 if (sent > sizeof(buf) - count)
779 sent = sizeof(buf) - count;
782 status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
783 count, sent, NULL);
784 if (!NT_STATUS_IS_OK(status)) {
785 printf("write failed (%s)\n",
786 nt_errstr(status));
787 correct = False;
790 else
792 status = cli_read(c, fnum, buf_rd+count, count,
793 sizeof(buf)-count, &sent);
794 if(!NT_STATUS_IS_OK(status)) {
795 printf("read failed offset:%d size:%ld (%s)\n",
796 count, (unsigned long)sizeof(buf)-count,
797 nt_errstr(status));
798 correct = False;
799 sent = 0;
800 } else if (sent > 0) {
801 if (memcmp(buf_rd+count, buf+count, sent) != 0)
803 printf("read/write compare failed\n");
804 printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
805 correct = False;
806 break;
813 status = cli_close(c, fnum);
814 if (!NT_STATUS_IS_OK(status)) {
815 printf("close failed (%s)\n", nt_errstr(status));
816 correct = False;
819 return correct;
822 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
824 const char *lockfname = "\\torture2.lck";
825 uint16_t fnum1;
826 uint16_t fnum2;
827 int i;
828 char buf[131072];
829 char buf_rd[131072];
830 bool correct = True;
831 size_t bytes_read;
832 NTSTATUS status;
834 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
835 if (!NT_STATUS_IS_OK(status)) {
836 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
839 status = cli_open(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
840 DENY_NONE, &fnum1);
841 if (!NT_STATUS_IS_OK(status)) {
842 printf("first open read/write of %s failed (%s)\n",
843 lockfname, nt_errstr(status));
844 return False;
847 status = cli_open(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
848 if (!NT_STATUS_IS_OK(status)) {
849 printf("second open read-only of %s failed (%s)\n",
850 lockfname, nt_errstr(status));
851 cli_close(c1, fnum1);
852 return False;
855 for (i = 0; i < torture_numops; i++)
857 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
858 if (i % 10 == 0) {
859 printf("%d\r", i); fflush(stdout);
862 generate_random_buffer((unsigned char *)buf, buf_size);
864 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
865 buf_size, NULL);
866 if (!NT_STATUS_IS_OK(status)) {
867 printf("write failed (%s)\n", nt_errstr(status));
868 correct = False;
869 break;
872 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
873 if(!NT_STATUS_IS_OK(status)) {
874 printf("read failed (%s)\n", nt_errstr(status));
875 correct = false;
876 break;
877 } else if (bytes_read != buf_size) {
878 printf("read failed\n");
879 printf("read %ld, expected %ld\n",
880 (unsigned long)bytes_read,
881 (unsigned long)buf_size);
882 correct = False;
883 break;
886 if (memcmp(buf_rd, buf, buf_size) != 0)
888 printf("read/write compare failed\n");
889 correct = False;
890 break;
894 status = cli_close(c2, fnum2);
895 if (!NT_STATUS_IS_OK(status)) {
896 printf("close failed (%s)\n", nt_errstr(status));
897 correct = False;
900 status = cli_close(c1, fnum1);
901 if (!NT_STATUS_IS_OK(status)) {
902 printf("close failed (%s)\n", nt_errstr(status));
903 correct = False;
906 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
907 if (!NT_STATUS_IS_OK(status)) {
908 printf("unlink failed (%s)\n", nt_errstr(status));
909 correct = False;
912 return correct;
915 static bool run_readwritetest(int dummy)
917 struct cli_state *cli1, *cli2;
918 bool test1, test2 = False;
920 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
921 return False;
923 cli_sockopt(cli1, sockops);
924 cli_sockopt(cli2, sockops);
926 printf("starting readwritetest\n");
928 test1 = rw_torture2(cli1, cli2);
929 printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
931 if (test1) {
932 test2 = rw_torture2(cli1, cli1);
933 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
936 if (!torture_close_connection(cli1)) {
937 test1 = False;
940 if (!torture_close_connection(cli2)) {
941 test2 = False;
944 return (test1 && test2);
947 static bool run_readwritemulti(int dummy)
949 struct cli_state *cli;
950 bool test;
952 cli = current_cli;
954 cli_sockopt(cli, sockops);
956 printf("run_readwritemulti: fname %s\n", randomfname);
957 test = rw_torture3(cli, randomfname);
959 if (!torture_close_connection(cli)) {
960 test = False;
963 return test;
966 static bool run_readwritelarge_internal(void)
968 static struct cli_state *cli1;
969 uint16_t fnum1;
970 const char *lockfname = "\\large.dat";
971 SMB_OFF_T fsize;
972 char buf[126*1024];
973 bool correct = True;
974 NTSTATUS status;
976 if (!torture_open_connection(&cli1, 0)) {
977 return False;
979 cli_sockopt(cli1, sockops);
980 memset(buf,'\0',sizeof(buf));
982 printf("starting readwritelarge_internal\n");
984 cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
986 status = cli_open(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
987 DENY_NONE, &fnum1);
988 if (!NT_STATUS_IS_OK(status)) {
989 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
990 return False;
993 cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
995 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
996 NULL, NULL, NULL);
997 if (!NT_STATUS_IS_OK(status)) {
998 printf("qfileinfo failed (%s)\n", nt_errstr(status));
999 correct = False;
1002 if (fsize == sizeof(buf))
1003 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
1004 (unsigned long)fsize);
1005 else {
1006 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
1007 (unsigned long)fsize);
1008 correct = False;
1011 status = cli_close(cli1, fnum1);
1012 if (!NT_STATUS_IS_OK(status)) {
1013 printf("close failed (%s)\n", nt_errstr(status));
1014 correct = False;
1017 status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1018 if (!NT_STATUS_IS_OK(status)) {
1019 printf("unlink failed (%s)\n", nt_errstr(status));
1020 correct = False;
1023 status = cli_open(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1024 DENY_NONE, &fnum1);
1025 if (!NT_STATUS_IS_OK(status)) {
1026 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1027 return False;
1030 cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1032 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1033 NULL, NULL, NULL);
1034 if (!NT_STATUS_IS_OK(status)) {
1035 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1036 correct = False;
1039 if (fsize == sizeof(buf))
1040 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1041 (unsigned long)fsize);
1042 else {
1043 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1044 (unsigned long)fsize);
1045 correct = False;
1048 #if 0
1049 /* ToDo - set allocation. JRA */
1050 if(!cli_set_allocation_size(cli1, fnum1, 0)) {
1051 printf("set allocation size to zero failed (%s)\n", cli_errstr(&cli1));
1052 return False;
1054 if (!cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL, NULL,
1055 NULL, NULL)) {
1056 printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
1057 correct = False;
1059 if (fsize != 0)
1060 printf("readwritelarge test 3 (truncate test) succeeded (size = %x)\n", fsize);
1061 #endif
1063 status = cli_close(cli1, fnum1);
1064 if (!NT_STATUS_IS_OK(status)) {
1065 printf("close failed (%s)\n", nt_errstr(status));
1066 correct = False;
1069 if (!torture_close_connection(cli1)) {
1070 correct = False;
1072 return correct;
1075 static bool run_readwritelarge(int dummy)
1077 return run_readwritelarge_internal();
1080 static bool run_readwritelarge_signtest(int dummy)
1082 bool ret;
1083 signing_state = Required;
1084 ret = run_readwritelarge_internal();
1085 signing_state = Undefined;
1086 return ret;
1089 int line_count = 0;
1090 int nbio_id;
1092 #define ival(s) strtol(s, NULL, 0)
1094 /* run a test that simulates an approximate netbench client load */
1095 static bool run_netbench(int client)
1097 struct cli_state *cli;
1098 int i;
1099 char line[1024];
1100 char cname[20];
1101 FILE *f;
1102 const char *params[20];
1103 bool correct = True;
1105 cli = current_cli;
1107 nbio_id = client;
1109 cli_sockopt(cli, sockops);
1111 nb_setup(cli);
1113 slprintf(cname,sizeof(cname)-1, "client%d", client);
1115 f = fopen(client_txt, "r");
1117 if (!f) {
1118 perror(client_txt);
1119 return False;
1122 while (fgets(line, sizeof(line)-1, f)) {
1123 char *saveptr;
1124 line_count++;
1126 line[strlen(line)-1] = 0;
1128 /* printf("[%d] %s\n", line_count, line); */
1130 all_string_sub(line,"client1", cname, sizeof(line));
1132 /* parse the command parameters */
1133 params[0] = strtok_r(line, " ", &saveptr);
1134 i = 0;
1135 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1137 params[i] = "";
1139 if (i < 2) continue;
1141 if (!strncmp(params[0],"SMB", 3)) {
1142 printf("ERROR: You are using a dbench 1 load file\n");
1143 exit(1);
1146 if (!strcmp(params[0],"NTCreateX")) {
1147 nb_createx(params[1], ival(params[2]), ival(params[3]),
1148 ival(params[4]));
1149 } else if (!strcmp(params[0],"Close")) {
1150 nb_close(ival(params[1]));
1151 } else if (!strcmp(params[0],"Rename")) {
1152 nb_rename(params[1], params[2]);
1153 } else if (!strcmp(params[0],"Unlink")) {
1154 nb_unlink(params[1]);
1155 } else if (!strcmp(params[0],"Deltree")) {
1156 nb_deltree(params[1]);
1157 } else if (!strcmp(params[0],"Rmdir")) {
1158 nb_rmdir(params[1]);
1159 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1160 nb_qpathinfo(params[1]);
1161 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1162 nb_qfileinfo(ival(params[1]));
1163 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1164 nb_qfsinfo(ival(params[1]));
1165 } else if (!strcmp(params[0],"FIND_FIRST")) {
1166 nb_findfirst(params[1]);
1167 } else if (!strcmp(params[0],"WriteX")) {
1168 nb_writex(ival(params[1]),
1169 ival(params[2]), ival(params[3]), ival(params[4]));
1170 } else if (!strcmp(params[0],"ReadX")) {
1171 nb_readx(ival(params[1]),
1172 ival(params[2]), ival(params[3]), ival(params[4]));
1173 } else if (!strcmp(params[0],"Flush")) {
1174 nb_flush(ival(params[1]));
1175 } else {
1176 printf("Unknown operation %s\n", params[0]);
1177 exit(1);
1180 fclose(f);
1182 nb_cleanup();
1184 if (!torture_close_connection(cli)) {
1185 correct = False;
1188 return correct;
1192 /* run a test that simulates an approximate netbench client load */
1193 static bool run_nbench(int dummy)
1195 double t;
1196 bool correct = True;
1198 nbio_shmem(nprocs);
1200 nbio_id = -1;
1202 signal(SIGALRM, nb_alarm);
1203 alarm(1);
1204 t = create_procs(run_netbench, &correct);
1205 alarm(0);
1207 printf("\nThroughput %g MB/sec\n",
1208 1.0e-6 * nbio_total() / t);
1209 return correct;
1214 This test checks for two things:
1216 1) correct support for retaining locks over a close (ie. the server
1217 must not use posix semantics)
1218 2) support for lock timeouts
1220 static bool run_locktest1(int dummy)
1222 struct cli_state *cli1, *cli2;
1223 const char *fname = "\\lockt1.lck";
1224 uint16_t fnum1, fnum2, fnum3;
1225 time_t t1, t2;
1226 unsigned lock_timeout;
1227 NTSTATUS status;
1229 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1230 return False;
1232 cli_sockopt(cli1, sockops);
1233 cli_sockopt(cli2, sockops);
1235 printf("starting locktest1\n");
1237 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1239 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1240 &fnum1);
1241 if (!NT_STATUS_IS_OK(status)) {
1242 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1243 return False;
1246 status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1247 if (!NT_STATUS_IS_OK(status)) {
1248 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1249 return False;
1252 status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1253 if (!NT_STATUS_IS_OK(status)) {
1254 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1255 return False;
1258 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1259 if (!NT_STATUS_IS_OK(status)) {
1260 printf("lock1 failed (%s)\n", nt_errstr(status));
1261 return false;
1264 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1265 if (NT_STATUS_IS_OK(status)) {
1266 printf("lock2 succeeded! This is a locking bug\n");
1267 return false;
1268 } else {
1269 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1270 NT_STATUS_LOCK_NOT_GRANTED)) {
1271 return false;
1275 lock_timeout = (1 + (random() % 20));
1276 printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1277 t1 = time(NULL);
1278 status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1279 if (NT_STATUS_IS_OK(status)) {
1280 printf("lock3 succeeded! This is a locking bug\n");
1281 return false;
1282 } else {
1283 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1284 NT_STATUS_FILE_LOCK_CONFLICT)) {
1285 return false;
1288 t2 = time(NULL);
1290 if (ABS(t2 - t1) < lock_timeout-1) {
1291 printf("error: This server appears not to support timed lock requests\n");
1294 printf("server slept for %u seconds for a %u second timeout\n",
1295 (unsigned int)(t2-t1), lock_timeout);
1297 status = cli_close(cli1, fnum2);
1298 if (!NT_STATUS_IS_OK(status)) {
1299 printf("close1 failed (%s)\n", nt_errstr(status));
1300 return False;
1303 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1304 if (NT_STATUS_IS_OK(status)) {
1305 printf("lock4 succeeded! This is a locking bug\n");
1306 return false;
1307 } else {
1308 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1309 NT_STATUS_FILE_LOCK_CONFLICT)) {
1310 return false;
1314 status = cli_close(cli1, fnum1);
1315 if (!NT_STATUS_IS_OK(status)) {
1316 printf("close2 failed (%s)\n", nt_errstr(status));
1317 return False;
1320 status = cli_close(cli2, fnum3);
1321 if (!NT_STATUS_IS_OK(status)) {
1322 printf("close3 failed (%s)\n", nt_errstr(status));
1323 return False;
1326 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1327 if (!NT_STATUS_IS_OK(status)) {
1328 printf("unlink failed (%s)\n", nt_errstr(status));
1329 return False;
1333 if (!torture_close_connection(cli1)) {
1334 return False;
1337 if (!torture_close_connection(cli2)) {
1338 return False;
1341 printf("Passed locktest1\n");
1342 return True;
1346 this checks to see if a secondary tconx can use open files from an
1347 earlier tconx
1349 static bool run_tcon_test(int dummy)
1351 static struct cli_state *cli;
1352 const char *fname = "\\tcontest.tmp";
1353 uint16 fnum1;
1354 uint16 cnum1, cnum2, cnum3;
1355 uint16 vuid1, vuid2;
1356 char buf[4];
1357 bool ret = True;
1358 NTSTATUS status;
1360 memset(buf, '\0', sizeof(buf));
1362 if (!torture_open_connection(&cli, 0)) {
1363 return False;
1365 cli_sockopt(cli, sockops);
1367 printf("starting tcontest\n");
1369 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1371 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1372 if (!NT_STATUS_IS_OK(status)) {
1373 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1374 return False;
1377 cnum1 = cli_state_get_tid(cli);
1378 vuid1 = cli_state_get_uid(cli);
1380 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1381 if (!NT_STATUS_IS_OK(status)) {
1382 printf("initial write failed (%s)", nt_errstr(status));
1383 return False;
1386 status = cli_tcon_andx(cli, share, "?????",
1387 password, strlen(password)+1);
1388 if (!NT_STATUS_IS_OK(status)) {
1389 printf("%s refused 2nd tree connect (%s)\n", host,
1390 nt_errstr(status));
1391 cli_shutdown(cli);
1392 return False;
1395 cnum2 = cli_state_get_tid(cli);
1396 cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1397 vuid2 = cli_state_get_uid(cli) + 1;
1399 /* try a write with the wrong tid */
1400 cli_state_set_tid(cli, cnum2);
1402 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1403 if (NT_STATUS_IS_OK(status)) {
1404 printf("* server allows write with wrong TID\n");
1405 ret = False;
1406 } else {
1407 printf("server fails write with wrong TID : %s\n",
1408 nt_errstr(status));
1412 /* try a write with an invalid tid */
1413 cli_state_set_tid(cli, cnum3);
1415 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1416 if (NT_STATUS_IS_OK(status)) {
1417 printf("* server allows write with invalid TID\n");
1418 ret = False;
1419 } else {
1420 printf("server fails write with invalid TID : %s\n",
1421 nt_errstr(status));
1424 /* try a write with an invalid vuid */
1425 cli_state_set_uid(cli, vuid2);
1426 cli_state_set_tid(cli, cnum1);
1428 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1429 if (NT_STATUS_IS_OK(status)) {
1430 printf("* server allows write with invalid VUID\n");
1431 ret = False;
1432 } else {
1433 printf("server fails write with invalid VUID : %s\n",
1434 nt_errstr(status));
1437 cli_state_set_tid(cli, cnum1);
1438 cli_state_set_uid(cli, vuid1);
1440 status = cli_close(cli, fnum1);
1441 if (!NT_STATUS_IS_OK(status)) {
1442 printf("close failed (%s)\n", nt_errstr(status));
1443 return False;
1446 cli_state_set_tid(cli, cnum2);
1448 status = cli_tdis(cli);
1449 if (!NT_STATUS_IS_OK(status)) {
1450 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1451 return False;
1454 cli_state_set_tid(cli, cnum1);
1456 if (!torture_close_connection(cli)) {
1457 return False;
1460 return ret;
1465 checks for old style tcon support
1467 static bool run_tcon2_test(int dummy)
1469 static struct cli_state *cli;
1470 uint16 cnum, max_xmit;
1471 char *service;
1472 NTSTATUS status;
1474 if (!torture_open_connection(&cli, 0)) {
1475 return False;
1477 cli_sockopt(cli, sockops);
1479 printf("starting tcon2 test\n");
1481 if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1482 return false;
1485 status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1487 SAFE_FREE(service);
1489 if (!NT_STATUS_IS_OK(status)) {
1490 printf("tcon2 failed : %s\n", nt_errstr(status));
1491 } else {
1492 printf("tcon OK : max_xmit=%d cnum=%d\n",
1493 (int)max_xmit, (int)cnum);
1496 if (!torture_close_connection(cli)) {
1497 return False;
1500 printf("Passed tcon2 test\n");
1501 return True;
1504 static bool tcon_devtest(struct cli_state *cli,
1505 const char *myshare, const char *devtype,
1506 const char *return_devtype,
1507 NTSTATUS expected_error)
1509 NTSTATUS status;
1510 bool ret;
1512 status = cli_tcon_andx(cli, myshare, devtype,
1513 password, strlen(password)+1);
1515 if (NT_STATUS_IS_OK(expected_error)) {
1516 if (NT_STATUS_IS_OK(status)) {
1517 if (strcmp(cli->dev, return_devtype) == 0) {
1518 ret = True;
1519 } else {
1520 printf("tconX to share %s with type %s "
1521 "succeeded but returned the wrong "
1522 "device type (got [%s] but should have got [%s])\n",
1523 myshare, devtype, cli->dev, return_devtype);
1524 ret = False;
1526 } else {
1527 printf("tconX to share %s with type %s "
1528 "should have succeeded but failed\n",
1529 myshare, devtype);
1530 ret = False;
1532 cli_tdis(cli);
1533 } else {
1534 if (NT_STATUS_IS_OK(status)) {
1535 printf("tconx to share %s with type %s "
1536 "should have failed but succeeded\n",
1537 myshare, devtype);
1538 ret = False;
1539 } else {
1540 if (NT_STATUS_EQUAL(cli_nt_error(cli),
1541 expected_error)) {
1542 ret = True;
1543 } else {
1544 printf("Returned unexpected error\n");
1545 ret = False;
1549 return ret;
1553 checks for correct tconX support
1555 static bool run_tcon_devtype_test(int dummy)
1557 static struct cli_state *cli1 = NULL;
1558 int flags = 0;
1559 NTSTATUS status;
1560 bool ret = True;
1562 status = cli_full_connection(&cli1, myname,
1563 host, NULL, port_to_use,
1564 NULL, NULL,
1565 username, workgroup,
1566 password, flags, signing_state);
1568 if (!NT_STATUS_IS_OK(status)) {
1569 printf("could not open connection\n");
1570 return False;
1573 if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1574 ret = False;
1576 if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1577 ret = False;
1579 if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1580 ret = False;
1582 if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1583 ret = False;
1585 if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1586 ret = False;
1588 if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1589 ret = False;
1591 if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1592 ret = False;
1594 if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1595 ret = False;
1597 if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1598 ret = False;
1600 if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1601 ret = False;
1603 cli_shutdown(cli1);
1605 if (ret)
1606 printf("Passed tcondevtest\n");
1608 return ret;
1613 This test checks that
1615 1) the server supports multiple locking contexts on the one SMB
1616 connection, distinguished by PID.
1618 2) the server correctly fails overlapping locks made by the same PID (this
1619 goes against POSIX behaviour, which is why it is tricky to implement)
1621 3) the server denies unlock requests by an incorrect client PID
1623 static bool run_locktest2(int dummy)
1625 static struct cli_state *cli;
1626 const char *fname = "\\lockt2.lck";
1627 uint16_t fnum1, fnum2, fnum3;
1628 bool correct = True;
1629 NTSTATUS status;
1631 if (!torture_open_connection(&cli, 0)) {
1632 return False;
1635 cli_sockopt(cli, sockops);
1637 printf("starting locktest2\n");
1639 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1641 cli_setpid(cli, 1);
1643 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1644 if (!NT_STATUS_IS_OK(status)) {
1645 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1646 return False;
1649 status = cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1650 if (!NT_STATUS_IS_OK(status)) {
1651 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1652 return False;
1655 cli_setpid(cli, 2);
1657 status = cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1658 if (!NT_STATUS_IS_OK(status)) {
1659 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1660 return False;
1663 cli_setpid(cli, 1);
1665 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1666 if (!NT_STATUS_IS_OK(status)) {
1667 printf("lock1 failed (%s)\n", nt_errstr(status));
1668 return false;
1671 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1672 if (NT_STATUS_IS_OK(status)) {
1673 printf("WRITE lock1 succeeded! This is a locking bug\n");
1674 correct = false;
1675 } else {
1676 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1677 NT_STATUS_LOCK_NOT_GRANTED)) {
1678 return false;
1682 status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1683 if (NT_STATUS_IS_OK(status)) {
1684 printf("WRITE lock2 succeeded! This is a locking bug\n");
1685 correct = false;
1686 } else {
1687 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1688 NT_STATUS_LOCK_NOT_GRANTED)) {
1689 return false;
1693 status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1694 if (NT_STATUS_IS_OK(status)) {
1695 printf("READ lock2 succeeded! This is a locking bug\n");
1696 correct = false;
1697 } else {
1698 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1699 NT_STATUS_FILE_LOCK_CONFLICT)) {
1700 return false;
1704 status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1705 if (!NT_STATUS_IS_OK(status)) {
1706 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1708 cli_setpid(cli, 2);
1709 if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1710 printf("unlock at 100 succeeded! This is a locking bug\n");
1711 correct = False;
1714 status = cli_unlock(cli, fnum1, 0, 4);
1715 if (NT_STATUS_IS_OK(status)) {
1716 printf("unlock1 succeeded! This is a locking bug\n");
1717 correct = false;
1718 } else {
1719 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1720 NT_STATUS_RANGE_NOT_LOCKED)) {
1721 return false;
1725 status = cli_unlock(cli, fnum1, 0, 8);
1726 if (NT_STATUS_IS_OK(status)) {
1727 printf("unlock2 succeeded! This is a locking bug\n");
1728 correct = false;
1729 } else {
1730 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1731 NT_STATUS_RANGE_NOT_LOCKED)) {
1732 return false;
1736 status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1737 if (NT_STATUS_IS_OK(status)) {
1738 printf("lock3 succeeded! This is a locking bug\n");
1739 correct = false;
1740 } else {
1741 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1742 NT_STATUS_LOCK_NOT_GRANTED)) {
1743 return false;
1747 cli_setpid(cli, 1);
1749 status = cli_close(cli, fnum1);
1750 if (!NT_STATUS_IS_OK(status)) {
1751 printf("close1 failed (%s)\n", nt_errstr(status));
1752 return False;
1755 status = cli_close(cli, fnum2);
1756 if (!NT_STATUS_IS_OK(status)) {
1757 printf("close2 failed (%s)\n", nt_errstr(status));
1758 return False;
1761 status = cli_close(cli, fnum3);
1762 if (!NT_STATUS_IS_OK(status)) {
1763 printf("close3 failed (%s)\n", nt_errstr(status));
1764 return False;
1767 if (!torture_close_connection(cli)) {
1768 correct = False;
1771 printf("locktest2 finished\n");
1773 return correct;
1778 This test checks that
1780 1) the server supports the full offset range in lock requests
1782 static bool run_locktest3(int dummy)
1784 static struct cli_state *cli1, *cli2;
1785 const char *fname = "\\lockt3.lck";
1786 uint16_t fnum1, fnum2;
1787 int i;
1788 uint32 offset;
1789 bool correct = True;
1790 NTSTATUS status;
1792 #define NEXT_OFFSET offset += (~(uint32)0) / torture_numops
1794 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1795 return False;
1797 cli_sockopt(cli1, sockops);
1798 cli_sockopt(cli2, sockops);
1800 printf("starting locktest3\n");
1802 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1804 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1805 &fnum1);
1806 if (!NT_STATUS_IS_OK(status)) {
1807 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1808 return False;
1811 status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1812 if (!NT_STATUS_IS_OK(status)) {
1813 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1814 return False;
1817 for (offset=i=0;i<torture_numops;i++) {
1818 NEXT_OFFSET;
1820 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1821 if (!NT_STATUS_IS_OK(status)) {
1822 printf("lock1 %d failed (%s)\n",
1824 nt_errstr(status));
1825 return False;
1828 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1829 if (!NT_STATUS_IS_OK(status)) {
1830 printf("lock2 %d failed (%s)\n",
1832 nt_errstr(status));
1833 return False;
1837 for (offset=i=0;i<torture_numops;i++) {
1838 NEXT_OFFSET;
1840 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1841 if (NT_STATUS_IS_OK(status)) {
1842 printf("error: lock1 %d succeeded!\n", i);
1843 return False;
1846 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1847 if (NT_STATUS_IS_OK(status)) {
1848 printf("error: lock2 %d succeeded!\n", i);
1849 return False;
1852 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1853 if (NT_STATUS_IS_OK(status)) {
1854 printf("error: lock3 %d succeeded!\n", i);
1855 return False;
1858 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1859 if (NT_STATUS_IS_OK(status)) {
1860 printf("error: lock4 %d succeeded!\n", i);
1861 return False;
1865 for (offset=i=0;i<torture_numops;i++) {
1866 NEXT_OFFSET;
1868 status = cli_unlock(cli1, fnum1, offset-1, 1);
1869 if (!NT_STATUS_IS_OK(status)) {
1870 printf("unlock1 %d failed (%s)\n",
1872 nt_errstr(status));
1873 return False;
1876 status = cli_unlock(cli2, fnum2, offset-2, 1);
1877 if (!NT_STATUS_IS_OK(status)) {
1878 printf("unlock2 %d failed (%s)\n",
1880 nt_errstr(status));
1881 return False;
1885 status = cli_close(cli1, fnum1);
1886 if (!NT_STATUS_IS_OK(status)) {
1887 printf("close1 failed (%s)\n", nt_errstr(status));
1888 return False;
1891 status = cli_close(cli2, fnum2);
1892 if (!NT_STATUS_IS_OK(status)) {
1893 printf("close2 failed (%s)\n", nt_errstr(status));
1894 return False;
1897 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1898 if (!NT_STATUS_IS_OK(status)) {
1899 printf("unlink failed (%s)\n", nt_errstr(status));
1900 return False;
1903 if (!torture_close_connection(cli1)) {
1904 correct = False;
1907 if (!torture_close_connection(cli2)) {
1908 correct = False;
1911 printf("finished locktest3\n");
1913 return correct;
1916 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
1917 char *buf, off_t offset, size_t size,
1918 size_t *nread, size_t expect)
1920 NTSTATUS status;
1921 size_t l_nread;
1923 status = cli_read(cli, fnum, buf, offset, size, &l_nread);
1925 if(!NT_STATUS_IS_OK(status)) {
1926 return false;
1927 } else if (l_nread != expect) {
1928 return false;
1931 if (nread) {
1932 *nread = l_nread;
1935 return true;
1938 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1939 printf("** "); correct = False; \
1943 looks at overlapping locks
1945 static bool run_locktest4(int dummy)
1947 static struct cli_state *cli1, *cli2;
1948 const char *fname = "\\lockt4.lck";
1949 uint16_t fnum1, fnum2, f;
1950 bool ret;
1951 char buf[1000];
1952 bool correct = True;
1953 NTSTATUS status;
1955 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1956 return False;
1959 cli_sockopt(cli1, sockops);
1960 cli_sockopt(cli2, sockops);
1962 printf("starting locktest4\n");
1964 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1966 cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1967 cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1969 memset(buf, 0, sizeof(buf));
1971 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
1972 NULL);
1973 if (!NT_STATUS_IS_OK(status)) {
1974 printf("Failed to create file: %s\n", nt_errstr(status));
1975 correct = False;
1976 goto fail;
1979 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1980 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
1981 EXPECTED(ret, False);
1982 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1984 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
1985 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
1986 EXPECTED(ret, True);
1987 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1989 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
1990 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
1991 EXPECTED(ret, False);
1992 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1994 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
1995 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
1996 EXPECTED(ret, True);
1997 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1999 ret = (cli_setpid(cli1, 1),
2000 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
2001 (cli_setpid(cli1, 2),
2002 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
2003 EXPECTED(ret, False);
2004 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
2006 ret = (cli_setpid(cli1, 1),
2007 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
2008 (cli_setpid(cli1, 2),
2009 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
2010 EXPECTED(ret, True);
2011 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
2013 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
2014 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
2015 EXPECTED(ret, True);
2016 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
2018 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
2019 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
2020 EXPECTED(ret, False);
2021 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
2023 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
2024 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
2025 EXPECTED(ret, False);
2026 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
2028 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
2029 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2030 EXPECTED(ret, True);
2031 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2033 ret = (cli_setpid(cli1, 1),
2034 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2035 (cli_setpid(cli1, 2),
2036 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2037 EXPECTED(ret, False);
2038 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2040 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2041 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2042 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2043 EXPECTED(ret, False);
2044 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2047 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2048 test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2049 EXPECTED(ret, False);
2050 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2052 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2053 ret = NT_STATUS_IS_OK(status);
2054 if (ret) {
2055 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2056 NULL);
2057 ret = NT_STATUS_IS_OK(status);
2059 EXPECTED(ret, False);
2060 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2063 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2064 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2065 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2066 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2067 EXPECTED(ret, True);
2068 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2071 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2072 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2073 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2074 test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2075 !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2076 150, 4, NULL))) &&
2077 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2078 EXPECTED(ret, True);
2079 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2081 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2082 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2083 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2084 160, 4, NULL)) &&
2085 test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2086 EXPECTED(ret, True);
2087 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2089 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2090 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2091 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2092 170, 4, NULL)) &&
2093 test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2094 EXPECTED(ret, True);
2095 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2097 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2098 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2099 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2100 !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2101 190, 4, NULL)) &&
2102 test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2103 EXPECTED(ret, True);
2104 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2106 cli_close(cli1, fnum1);
2107 cli_close(cli2, fnum2);
2108 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2109 cli_open(cli1, fname, O_RDWR, DENY_NONE, &f);
2110 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2111 NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2112 NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2113 NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2114 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2115 cli_close(cli1, f);
2116 cli_close(cli1, fnum1);
2117 EXPECTED(ret, True);
2118 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2120 fail:
2121 cli_close(cli1, fnum1);
2122 cli_close(cli2, fnum2);
2123 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2124 torture_close_connection(cli1);
2125 torture_close_connection(cli2);
2127 printf("finished locktest4\n");
2128 return correct;
2132 looks at lock upgrade/downgrade.
2134 static bool run_locktest5(int dummy)
2136 static struct cli_state *cli1, *cli2;
2137 const char *fname = "\\lockt5.lck";
2138 uint16_t fnum1, fnum2, fnum3;
2139 bool ret;
2140 char buf[1000];
2141 bool correct = True;
2142 NTSTATUS status;
2144 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2145 return False;
2148 cli_sockopt(cli1, sockops);
2149 cli_sockopt(cli2, sockops);
2151 printf("starting locktest5\n");
2153 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2155 cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2156 cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2157 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2159 memset(buf, 0, sizeof(buf));
2161 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2162 NULL);
2163 if (!NT_STATUS_IS_OK(status)) {
2164 printf("Failed to create file: %s\n", nt_errstr(status));
2165 correct = False;
2166 goto fail;
2169 /* Check for NT bug... */
2170 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2171 NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2172 cli_close(cli1, fnum1);
2173 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2174 status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2175 ret = NT_STATUS_IS_OK(status);
2176 EXPECTED(ret, True);
2177 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2178 cli_close(cli1, fnum1);
2179 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2180 cli_unlock(cli1, fnum3, 0, 1);
2182 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2183 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2184 EXPECTED(ret, True);
2185 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2187 status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2188 ret = NT_STATUS_IS_OK(status);
2189 EXPECTED(ret, False);
2191 printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2193 /* Unlock the process 2 lock. */
2194 cli_unlock(cli2, fnum2, 0, 4);
2196 status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2197 ret = NT_STATUS_IS_OK(status);
2198 EXPECTED(ret, False);
2200 printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
2202 /* Unlock the process 1 fnum3 lock. */
2203 cli_unlock(cli1, fnum3, 0, 4);
2205 /* Stack 2 more locks here. */
2206 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2207 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2209 EXPECTED(ret, True);
2210 printf("the same process %s stack read locks\n", ret?"can":"cannot");
2212 /* Unlock the first process lock, then check this was the WRITE lock that was
2213 removed. */
2215 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2216 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2218 EXPECTED(ret, True);
2219 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2221 /* Unlock the process 2 lock. */
2222 cli_unlock(cli2, fnum2, 0, 4);
2224 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2226 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2227 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2228 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2230 EXPECTED(ret, True);
2231 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2233 /* Ensure the next unlock fails. */
2234 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2235 EXPECTED(ret, False);
2236 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2238 /* Ensure connection 2 can get a write lock. */
2239 status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2240 ret = NT_STATUS_IS_OK(status);
2241 EXPECTED(ret, True);
2243 printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2246 fail:
2247 cli_close(cli1, fnum1);
2248 cli_close(cli2, fnum2);
2249 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2250 if (!torture_close_connection(cli1)) {
2251 correct = False;
2253 if (!torture_close_connection(cli2)) {
2254 correct = False;
2257 printf("finished locktest5\n");
2259 return correct;
2263 tries the unusual lockingX locktype bits
2265 static bool run_locktest6(int dummy)
2267 static struct cli_state *cli;
2268 const char *fname[1] = { "\\lock6.txt" };
2269 int i;
2270 uint16_t fnum;
2271 NTSTATUS status;
2273 if (!torture_open_connection(&cli, 0)) {
2274 return False;
2277 cli_sockopt(cli, sockops);
2279 printf("starting locktest6\n");
2281 for (i=0;i<1;i++) {
2282 printf("Testing %s\n", fname[i]);
2284 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2286 cli_open(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2287 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2288 cli_close(cli, fnum);
2289 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2291 cli_open(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2292 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2293 cli_close(cli, fnum);
2294 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2296 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2299 torture_close_connection(cli);
2301 printf("finished locktest6\n");
2302 return True;
2305 static bool run_locktest7(int dummy)
2307 struct cli_state *cli1;
2308 const char *fname = "\\lockt7.lck";
2309 uint16_t fnum1;
2310 char buf[200];
2311 bool correct = False;
2312 size_t nread;
2313 NTSTATUS status;
2315 if (!torture_open_connection(&cli1, 0)) {
2316 return False;
2319 cli_sockopt(cli1, sockops);
2321 printf("starting locktest7\n");
2323 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2325 cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2327 memset(buf, 0, sizeof(buf));
2329 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2330 NULL);
2331 if (!NT_STATUS_IS_OK(status)) {
2332 printf("Failed to create file: %s\n", nt_errstr(status));
2333 goto fail;
2336 cli_setpid(cli1, 1);
2338 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2339 if (!NT_STATUS_IS_OK(status)) {
2340 printf("Unable to apply read lock on range 130:4, "
2341 "error was %s\n", nt_errstr(status));
2342 goto fail;
2343 } else {
2344 printf("pid1 successfully locked range 130:4 for READ\n");
2347 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2348 if (!NT_STATUS_IS_OK(status)) {
2349 printf("pid1 unable to read the range 130:4, error was %s\n",
2350 nt_errstr(status));
2351 goto fail;
2352 } else if (nread != 4) {
2353 printf("pid1 unable to read the range 130:4, "
2354 "recv %ld req %d\n", (unsigned long)nread, 4);
2355 goto fail;
2356 } else {
2357 printf("pid1 successfully read the range 130:4\n");
2360 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2361 if (!NT_STATUS_IS_OK(status)) {
2362 printf("pid1 unable to write to the range 130:4, error was "
2363 "%s\n", nt_errstr(status));
2364 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2365 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2366 goto fail;
2368 } else {
2369 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2370 goto fail;
2373 cli_setpid(cli1, 2);
2375 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2376 if (!NT_STATUS_IS_OK(status)) {
2377 printf("pid2 unable to read the range 130:4, error was %s\n",
2378 nt_errstr(status));
2379 goto fail;
2380 } else if (nread != 4) {
2381 printf("pid2 unable to read the range 130:4, "
2382 "recv %ld req %d\n", (unsigned long)nread, 4);
2383 goto fail;
2384 } else {
2385 printf("pid2 successfully read the range 130:4\n");
2388 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2389 if (!NT_STATUS_IS_OK(status)) {
2390 printf("pid2 unable to write to the range 130:4, error was "
2391 "%s\n", nt_errstr(status));
2392 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2393 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2394 goto fail;
2396 } else {
2397 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2398 goto fail;
2401 cli_setpid(cli1, 1);
2402 cli_unlock(cli1, fnum1, 130, 4);
2404 status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2405 if (!NT_STATUS_IS_OK(status)) {
2406 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2407 goto fail;
2408 } else {
2409 printf("pid1 successfully locked range 130:4 for WRITE\n");
2412 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2413 if (!NT_STATUS_IS_OK(status)) {
2414 printf("pid1 unable to read the range 130:4, error was %s\n",
2415 nt_errstr(status));
2416 goto fail;
2417 } else if (nread != 4) {
2418 printf("pid1 unable to read the range 130:4, "
2419 "recv %ld req %d\n", (unsigned long)nread, 4);
2420 goto fail;
2421 } else {
2422 printf("pid1 successfully read the range 130:4\n");
2425 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2426 if (!NT_STATUS_IS_OK(status)) {
2427 printf("pid1 unable to write to the range 130:4, error was "
2428 "%s\n", nt_errstr(status));
2429 goto fail;
2430 } else {
2431 printf("pid1 successfully wrote to the range 130:4\n");
2434 cli_setpid(cli1, 2);
2436 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2437 if (!NT_STATUS_IS_OK(status)) {
2438 printf("pid2 unable to read the range 130:4, error was "
2439 "%s\n", nt_errstr(status));
2440 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2441 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2442 goto fail;
2444 } else {
2445 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2446 (unsigned long)nread);
2447 goto fail;
2450 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2451 if (!NT_STATUS_IS_OK(status)) {
2452 printf("pid2 unable to write to the range 130:4, error was "
2453 "%s\n", nt_errstr(status));
2454 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2455 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2456 goto fail;
2458 } else {
2459 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2460 goto fail;
2463 cli_unlock(cli1, fnum1, 130, 0);
2464 correct = True;
2466 fail:
2467 cli_close(cli1, fnum1);
2468 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2469 torture_close_connection(cli1);
2471 printf("finished locktest7\n");
2472 return correct;
2476 * This demonstrates a problem with our use of GPFS share modes: A file
2477 * descriptor sitting in the pending close queue holding a GPFS share mode
2478 * blocks opening a file another time. Happens with Word 2007 temp files.
2479 * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2480 * open is denied with NT_STATUS_SHARING_VIOLATION.
2483 static bool run_locktest8(int dummy)
2485 struct cli_state *cli1;
2486 const char *fname = "\\lockt8.lck";
2487 uint16_t fnum1, fnum2;
2488 char buf[200];
2489 bool correct = False;
2490 NTSTATUS status;
2492 if (!torture_open_connection(&cli1, 0)) {
2493 return False;
2496 cli_sockopt(cli1, sockops);
2498 printf("starting locktest8\n");
2500 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2502 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2503 &fnum1);
2504 if (!NT_STATUS_IS_OK(status)) {
2505 d_fprintf(stderr, "cli_open returned %s\n", nt_errstr(status));
2506 return false;
2509 memset(buf, 0, sizeof(buf));
2511 status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2512 if (!NT_STATUS_IS_OK(status)) {
2513 d_fprintf(stderr, "cli_open second time returned %s\n",
2514 nt_errstr(status));
2515 goto fail;
2518 status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2519 if (!NT_STATUS_IS_OK(status)) {
2520 printf("Unable to apply read lock on range 1:1, error was "
2521 "%s\n", nt_errstr(status));
2522 goto fail;
2525 status = cli_close(cli1, fnum1);
2526 if (!NT_STATUS_IS_OK(status)) {
2527 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2528 goto fail;
2531 status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2532 if (!NT_STATUS_IS_OK(status)) {
2533 d_fprintf(stderr, "cli_open third time returned %s\n",
2534 nt_errstr(status));
2535 goto fail;
2538 correct = true;
2540 fail:
2541 cli_close(cli1, fnum1);
2542 cli_close(cli1, fnum2);
2543 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2544 torture_close_connection(cli1);
2546 printf("finished locktest8\n");
2547 return correct;
2551 * This test is designed to be run in conjunction with
2552 * external NFS or POSIX locks taken in the filesystem.
2553 * It checks that the smbd server will block until the
2554 * lock is released and then acquire it. JRA.
2557 static bool got_alarm;
2558 static struct cli_state *alarm_cli;
2560 static void alarm_handler(int dummy)
2562 got_alarm = True;
2565 static void alarm_handler_parent(int dummy)
2567 cli_state_disconnect(alarm_cli);
2570 static void do_local_lock(int read_fd, int write_fd)
2572 int fd;
2573 char c = '\0';
2574 struct flock lock;
2575 const char *local_pathname = NULL;
2576 int ret;
2578 local_pathname = talloc_asprintf(talloc_tos(),
2579 "%s/lockt9.lck", local_path);
2580 if (!local_pathname) {
2581 printf("child: alloc fail\n");
2582 exit(1);
2585 unlink(local_pathname);
2586 fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2587 if (fd == -1) {
2588 printf("child: open of %s failed %s.\n",
2589 local_pathname, strerror(errno));
2590 exit(1);
2593 /* Now take a fcntl lock. */
2594 lock.l_type = F_WRLCK;
2595 lock.l_whence = SEEK_SET;
2596 lock.l_start = 0;
2597 lock.l_len = 4;
2598 lock.l_pid = getpid();
2600 ret = fcntl(fd,F_SETLK,&lock);
2601 if (ret == -1) {
2602 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2603 local_pathname, strerror(errno));
2604 exit(1);
2605 } else {
2606 printf("child: got lock 0:4 on file %s.\n",
2607 local_pathname );
2608 fflush(stdout);
2611 CatchSignal(SIGALRM, alarm_handler);
2612 alarm(5);
2613 /* Signal the parent. */
2614 if (write(write_fd, &c, 1) != 1) {
2615 printf("child: start signal fail %s.\n",
2616 strerror(errno));
2617 exit(1);
2619 alarm(0);
2621 alarm(10);
2622 /* Wait for the parent to be ready. */
2623 if (read(read_fd, &c, 1) != 1) {
2624 printf("child: reply signal fail %s.\n",
2625 strerror(errno));
2626 exit(1);
2628 alarm(0);
2630 sleep(5);
2631 close(fd);
2632 printf("child: released lock 0:4 on file %s.\n",
2633 local_pathname );
2634 fflush(stdout);
2635 exit(0);
2638 static bool run_locktest9(int dummy)
2640 struct cli_state *cli1;
2641 const char *fname = "\\lockt9.lck";
2642 uint16_t fnum;
2643 bool correct = False;
2644 int pipe_in[2], pipe_out[2];
2645 pid_t child_pid;
2646 char c = '\0';
2647 int ret;
2648 struct timeval start;
2649 double seconds;
2650 NTSTATUS status;
2652 printf("starting locktest9\n");
2654 if (local_path == NULL) {
2655 d_fprintf(stderr, "locktest9 must be given a local path via -l <localpath>\n");
2656 return false;
2659 if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2660 return false;
2663 child_pid = fork();
2664 if (child_pid == -1) {
2665 return false;
2668 if (child_pid == 0) {
2669 /* Child. */
2670 do_local_lock(pipe_out[0], pipe_in[1]);
2671 exit(0);
2674 close(pipe_out[0]);
2675 close(pipe_in[1]);
2676 pipe_out[0] = -1;
2677 pipe_in[1] = -1;
2679 /* Parent. */
2680 ret = read(pipe_in[0], &c, 1);
2681 if (ret != 1) {
2682 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2683 strerror(errno));
2684 return false;
2687 if (!torture_open_connection(&cli1, 0)) {
2688 return false;
2691 cli_sockopt(cli1, sockops);
2693 status = cli_open(cli1, fname, O_RDWR, DENY_NONE,
2694 &fnum);
2695 if (!NT_STATUS_IS_OK(status)) {
2696 d_fprintf(stderr, "cli_open returned %s\n", nt_errstr(status));
2697 return false;
2700 /* Ensure the child has the lock. */
2701 status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2702 if (NT_STATUS_IS_OK(status)) {
2703 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2704 goto fail;
2705 } else {
2706 d_printf("Child has the lock.\n");
2709 /* Tell the child to wait 5 seconds then exit. */
2710 ret = write(pipe_out[1], &c, 1);
2711 if (ret != 1) {
2712 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2713 strerror(errno));
2714 goto fail;
2717 /* Wait 20 seconds for the lock. */
2718 alarm_cli = cli1;
2719 CatchSignal(SIGALRM, alarm_handler_parent);
2720 alarm(20);
2722 start = timeval_current();
2724 status = cli_lock32(cli1, fnum, 0, 4, -1, WRITE_LOCK);
2725 if (!NT_STATUS_IS_OK(status)) {
2726 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2727 "%s\n", nt_errstr(status));
2728 goto fail_nofd;
2730 alarm(0);
2732 seconds = timeval_elapsed(&start);
2734 printf("Parent got the lock after %.2f seconds.\n",
2735 seconds);
2737 status = cli_close(cli1, fnum);
2738 if (!NT_STATUS_IS_OK(status)) {
2739 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2740 goto fail;
2743 correct = true;
2745 fail:
2746 cli_close(cli1, fnum);
2747 torture_close_connection(cli1);
2749 fail_nofd:
2751 printf("finished locktest9\n");
2752 return correct;
2756 test whether fnums and tids open on one VC are available on another (a major
2757 security hole)
2759 static bool run_fdpasstest(int dummy)
2761 struct cli_state *cli1, *cli2;
2762 const char *fname = "\\fdpass.tst";
2763 uint16_t fnum1;
2764 char buf[1024];
2765 NTSTATUS status;
2767 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2768 return False;
2770 cli_sockopt(cli1, sockops);
2771 cli_sockopt(cli2, sockops);
2773 printf("starting fdpasstest\n");
2775 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2777 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
2778 &fnum1);
2779 if (!NT_STATUS_IS_OK(status)) {
2780 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2781 return False;
2784 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
2785 13, NULL);
2786 if (!NT_STATUS_IS_OK(status)) {
2787 printf("write failed (%s)\n", nt_errstr(status));
2788 return False;
2791 cli_state_set_uid(cli2, cli_state_get_uid(cli1));
2792 cli_state_set_tid(cli2, cli_state_get_tid(cli1));
2793 cli_setpid(cli2, cli_getpid(cli1));
2795 if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
2796 printf("read succeeded! nasty security hole [%s]\n", buf);
2797 return false;
2800 cli_close(cli1, fnum1);
2801 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2803 torture_close_connection(cli1);
2804 torture_close_connection(cli2);
2806 printf("finished fdpasstest\n");
2807 return True;
2810 static bool run_fdsesstest(int dummy)
2812 struct cli_state *cli;
2813 uint16 new_vuid;
2814 uint16 saved_vuid;
2815 uint16 new_cnum;
2816 uint16 saved_cnum;
2817 const char *fname = "\\fdsess.tst";
2818 const char *fname1 = "\\fdsess1.tst";
2819 uint16_t fnum1;
2820 uint16_t fnum2;
2821 char buf[1024];
2822 bool ret = True;
2823 NTSTATUS status;
2825 if (!torture_open_connection(&cli, 0))
2826 return False;
2827 cli_sockopt(cli, sockops);
2829 if (!torture_cli_session_setup2(cli, &new_vuid))
2830 return False;
2832 saved_cnum = cli_state_get_tid(cli);
2833 if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, share, "?????", "", 1)))
2834 return False;
2835 new_cnum = cli_state_get_tid(cli);
2836 cli_state_set_tid(cli, saved_cnum);
2838 printf("starting fdsesstest\n");
2840 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2841 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2843 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2844 if (!NT_STATUS_IS_OK(status)) {
2845 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2846 return False;
2849 status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
2850 NULL);
2851 if (!NT_STATUS_IS_OK(status)) {
2852 printf("write failed (%s)\n", nt_errstr(status));
2853 return False;
2856 saved_vuid = cli_state_get_uid(cli);
2857 cli_state_set_uid(cli, new_vuid);
2859 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2860 printf("read succeeded with different vuid! "
2861 "nasty security hole [%s]\n", buf);
2862 ret = false;
2864 /* Try to open a file with different vuid, samba cnum. */
2865 if (NT_STATUS_IS_OK(cli_open(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
2866 printf("create with different vuid, same cnum succeeded.\n");
2867 cli_close(cli, fnum2);
2868 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2869 } else {
2870 printf("create with different vuid, same cnum failed.\n");
2871 printf("This will cause problems with service clients.\n");
2872 ret = False;
2875 cli_state_set_uid(cli, saved_vuid);
2877 /* Try with same vuid, different cnum. */
2878 cli_state_set_tid(cli, new_cnum);
2880 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2881 printf("read succeeded with different cnum![%s]\n", buf);
2882 ret = false;
2885 cli_state_set_tid(cli, saved_cnum);
2886 cli_close(cli, fnum1);
2887 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2889 torture_close_connection(cli);
2891 printf("finished fdsesstest\n");
2892 return ret;
2896 This test checks that
2898 1) the server does not allow an unlink on a file that is open
2900 static bool run_unlinktest(int dummy)
2902 struct cli_state *cli;
2903 const char *fname = "\\unlink.tst";
2904 uint16_t fnum;
2905 bool correct = True;
2906 NTSTATUS status;
2908 if (!torture_open_connection(&cli, 0)) {
2909 return False;
2912 cli_sockopt(cli, sockops);
2914 printf("starting unlink test\n");
2916 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2918 cli_setpid(cli, 1);
2920 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2921 if (!NT_STATUS_IS_OK(status)) {
2922 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2923 return False;
2926 status = cli_unlink(cli, fname,
2927 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2928 if (NT_STATUS_IS_OK(status)) {
2929 printf("error: server allowed unlink on an open file\n");
2930 correct = False;
2931 } else {
2932 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
2933 NT_STATUS_SHARING_VIOLATION);
2936 cli_close(cli, fnum);
2937 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2939 if (!torture_close_connection(cli)) {
2940 correct = False;
2943 printf("unlink test finished\n");
2945 return correct;
2950 test how many open files this server supports on the one socket
2952 static bool run_maxfidtest(int dummy)
2954 struct cli_state *cli;
2955 fstring fname;
2956 uint16_t fnums[0x11000];
2957 int i;
2958 int retries=4;
2959 bool correct = True;
2960 NTSTATUS status;
2962 cli = current_cli;
2964 if (retries <= 0) {
2965 printf("failed to connect\n");
2966 return False;
2969 cli_sockopt(cli, sockops);
2971 for (i=0; i<0x11000; i++) {
2972 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2973 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
2974 &fnums[i]);
2975 if (!NT_STATUS_IS_OK(status)) {
2976 printf("open of %s failed (%s)\n",
2977 fname, nt_errstr(status));
2978 printf("maximum fnum is %d\n", i);
2979 break;
2981 printf("%6d\r", i);
2983 printf("%6d\n", i);
2984 i--;
2986 printf("cleaning up\n");
2987 for (;i>=0;i--) {
2988 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2989 cli_close(cli, fnums[i]);
2991 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2992 if (!NT_STATUS_IS_OK(status)) {
2993 printf("unlink of %s failed (%s)\n",
2994 fname, nt_errstr(status));
2995 correct = False;
2997 printf("%6d\r", i);
2999 printf("%6d\n", 0);
3001 printf("maxfid test finished\n");
3002 if (!torture_close_connection(cli)) {
3003 correct = False;
3005 return correct;
3008 /* generate a random buffer */
3009 static void rand_buf(char *buf, int len)
3011 while (len--) {
3012 *buf = (char)sys_random();
3013 buf++;
3017 /* send smb negprot commands, not reading the response */
3018 static bool run_negprot_nowait(int dummy)
3020 struct tevent_context *ev;
3021 int i;
3022 struct cli_state *cli;
3023 bool correct = True;
3025 printf("starting negprot nowait test\n");
3027 ev = tevent_context_init(talloc_tos());
3028 if (ev == NULL) {
3029 return false;
3032 if (!(cli = open_nbt_connection())) {
3033 TALLOC_FREE(ev);
3034 return False;
3037 for (i=0;i<50000;i++) {
3038 struct tevent_req *req;
3040 req = cli_negprot_send(ev, ev, cli, PROTOCOL_NT1);
3041 if (req == NULL) {
3042 TALLOC_FREE(ev);
3043 return false;
3045 if (!tevent_req_poll(req, ev)) {
3046 d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3047 strerror(errno));
3048 TALLOC_FREE(ev);
3049 return false;
3051 TALLOC_FREE(req);
3054 if (torture_close_connection(cli)) {
3055 correct = False;
3058 printf("finished negprot nowait test\n");
3060 return correct;
3063 /* send smb negprot commands, not reading the response */
3064 static bool run_bad_nbt_session(int dummy)
3066 struct nmb_name called, calling;
3067 struct sockaddr_storage ss;
3068 NTSTATUS status;
3069 int fd;
3070 bool ret;
3072 printf("starting bad nbt session test\n");
3074 make_nmb_name(&calling, myname, 0x0);
3075 make_nmb_name(&called , host, 0x20);
3077 if (!resolve_name(host, &ss, 0x20, true)) {
3078 d_fprintf(stderr, "Could not resolve name %s\n", host);
3079 return false;
3082 status = open_socket_out(&ss, 139, 10000, &fd);
3083 if (!NT_STATUS_IS_OK(status)) {
3084 d_fprintf(stderr, "open_socket_out failed: %s\n",
3085 nt_errstr(status));
3086 return false;
3089 ret = cli_bad_session_request(fd, &calling, &called);
3090 close(fd);
3091 if (!ret) {
3092 d_fprintf(stderr, "open_socket_out failed: %s\n",
3093 nt_errstr(status));
3094 return false;
3097 printf("finished bad nbt session test\n");
3098 return true;
3101 /* send random IPC commands */
3102 static bool run_randomipc(int dummy)
3104 char *rparam = NULL;
3105 char *rdata = NULL;
3106 unsigned int rdrcnt,rprcnt;
3107 char param[1024];
3108 int api, param_len, i;
3109 struct cli_state *cli;
3110 bool correct = True;
3111 int count = 50000;
3113 printf("starting random ipc test\n");
3115 if (!torture_open_connection(&cli, 0)) {
3116 return False;
3119 for (i=0;i<count;i++) {
3120 api = sys_random() % 500;
3121 param_len = (sys_random() % 64);
3123 rand_buf(param, param_len);
3125 SSVAL(param,0,api);
3127 cli_api(cli,
3128 param, param_len, 8,
3129 NULL, 0, BUFFER_SIZE,
3130 &rparam, &rprcnt,
3131 &rdata, &rdrcnt);
3132 if (i % 100 == 0) {
3133 printf("%d/%d\r", i,count);
3136 printf("%d/%d\n", i, count);
3138 if (!torture_close_connection(cli)) {
3139 correct = False;
3142 printf("finished random ipc test\n");
3144 return correct;
3149 static void browse_callback(const char *sname, uint32 stype,
3150 const char *comment, void *state)
3152 printf("\t%20.20s %08x %s\n", sname, stype, comment);
3158 This test checks the browse list code
3161 static bool run_browsetest(int dummy)
3163 static struct cli_state *cli;
3164 bool correct = True;
3166 printf("starting browse test\n");
3168 if (!torture_open_connection(&cli, 0)) {
3169 return False;
3172 printf("domain list:\n");
3173 cli_NetServerEnum(cli, cli->server_domain,
3174 SV_TYPE_DOMAIN_ENUM,
3175 browse_callback, NULL);
3177 printf("machine list:\n");
3178 cli_NetServerEnum(cli, cli->server_domain,
3179 SV_TYPE_ALL,
3180 browse_callback, NULL);
3182 if (!torture_close_connection(cli)) {
3183 correct = False;
3186 printf("browse test finished\n");
3188 return correct;
3194 This checks how the getatr calls works
3196 static bool run_attrtest(int dummy)
3198 struct cli_state *cli;
3199 uint16_t fnum;
3200 time_t t, t2;
3201 const char *fname = "\\attrib123456789.tst";
3202 bool correct = True;
3203 NTSTATUS status;
3205 printf("starting attrib test\n");
3207 if (!torture_open_connection(&cli, 0)) {
3208 return False;
3211 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3212 cli_open(cli, fname,
3213 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3214 cli_close(cli, fnum);
3216 status = cli_getatr(cli, fname, NULL, NULL, &t);
3217 if (!NT_STATUS_IS_OK(status)) {
3218 printf("getatr failed (%s)\n", nt_errstr(status));
3219 correct = False;
3222 if (abs(t - time(NULL)) > 60*60*24*10) {
3223 printf("ERROR: SMBgetatr bug. time is %s",
3224 ctime(&t));
3225 t = time(NULL);
3226 correct = True;
3229 t2 = t-60*60*24; /* 1 day ago */
3231 status = cli_setatr(cli, fname, 0, t2);
3232 if (!NT_STATUS_IS_OK(status)) {
3233 printf("setatr failed (%s)\n", nt_errstr(status));
3234 correct = True;
3237 status = cli_getatr(cli, fname, NULL, NULL, &t);
3238 if (!NT_STATUS_IS_OK(status)) {
3239 printf("getatr failed (%s)\n", nt_errstr(status));
3240 correct = True;
3243 if (t != t2) {
3244 printf("ERROR: getatr/setatr bug. times are\n%s",
3245 ctime(&t));
3246 printf("%s", ctime(&t2));
3247 correct = True;
3250 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3252 if (!torture_close_connection(cli)) {
3253 correct = False;
3256 printf("attrib test finished\n");
3258 return correct;
3263 This checks a couple of trans2 calls
3265 static bool run_trans2test(int dummy)
3267 struct cli_state *cli;
3268 uint16_t fnum;
3269 SMB_OFF_T size;
3270 time_t c_time, a_time, m_time;
3271 struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
3272 const char *fname = "\\trans2.tst";
3273 const char *dname = "\\trans2";
3274 const char *fname2 = "\\trans2\\trans2.tst";
3275 char *pname;
3276 bool correct = True;
3277 NTSTATUS status;
3278 uint32_t fs_attr;
3280 printf("starting trans2 test\n");
3282 if (!torture_open_connection(&cli, 0)) {
3283 return False;
3286 status = cli_get_fs_attr_info(cli, &fs_attr);
3287 if (!NT_STATUS_IS_OK(status)) {
3288 printf("ERROR: cli_get_fs_attr_info returned %s\n",
3289 nt_errstr(status));
3290 correct = false;
3293 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3294 cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3295 status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
3296 &a_time_ts, &w_time_ts, &m_time_ts, NULL);
3297 if (!NT_STATUS_IS_OK(status)) {
3298 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
3299 correct = False;
3302 status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
3303 if (!NT_STATUS_IS_OK(status)) {
3304 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
3305 correct = False;
3308 if (strcmp(pname, fname)) {
3309 printf("qfilename gave different name? [%s] [%s]\n",
3310 fname, pname);
3311 correct = False;
3314 cli_close(cli, fnum);
3316 sleep(2);
3318 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3319 status = cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
3320 &fnum);
3321 if (!NT_STATUS_IS_OK(status)) {
3322 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3323 return False;
3325 cli_close(cli, fnum);
3327 status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
3328 NULL);
3329 if (!NT_STATUS_IS_OK(status)) {
3330 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
3331 correct = False;
3332 } else {
3333 time_t t = time(NULL);
3335 if (c_time != m_time) {
3336 printf("create time=%s", ctime(&c_time));
3337 printf("modify time=%s", ctime(&m_time));
3338 printf("This system appears to have sticky create times\n");
3340 if ((abs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
3341 printf("access time=%s", ctime(&a_time));
3342 printf("This system appears to set a midnight access time\n");
3343 correct = False;
3346 if (abs(m_time - t) > 60*60*24*7) {
3347 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
3348 correct = False;
3353 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3354 cli_open(cli, fname,
3355 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3356 cli_close(cli, fnum);
3357 status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
3358 &m_time_ts, &size, NULL, NULL);
3359 if (!NT_STATUS_IS_OK(status)) {
3360 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3361 correct = False;
3362 } else {
3363 if (w_time_ts.tv_sec < 60*60*24*2) {
3364 printf("write time=%s", ctime(&w_time_ts.tv_sec));
3365 printf("This system appears to set a initial 0 write time\n");
3366 correct = False;
3370 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3373 /* check if the server updates the directory modification time
3374 when creating a new file */
3375 status = cli_mkdir(cli, dname);
3376 if (!NT_STATUS_IS_OK(status)) {
3377 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
3378 correct = False;
3380 sleep(3);
3381 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3382 &w_time_ts, &m_time_ts, &size, NULL, NULL);
3383 if (!NT_STATUS_IS_OK(status)) {
3384 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3385 correct = False;
3388 cli_open(cli, fname2,
3389 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3390 cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
3391 cli_close(cli, fnum);
3392 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3393 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
3394 if (!NT_STATUS_IS_OK(status)) {
3395 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3396 correct = False;
3397 } else {
3398 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
3399 == 0) {
3400 printf("This system does not update directory modification times\n");
3401 correct = False;
3404 cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3405 cli_rmdir(cli, dname);
3407 if (!torture_close_connection(cli)) {
3408 correct = False;
3411 printf("trans2 test finished\n");
3413 return correct;
3417 This checks new W2K calls.
3420 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
3422 uint8_t *buf = NULL;
3423 uint32 len;
3424 NTSTATUS status;
3426 status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
3427 CLI_BUFFER_SIZE, NULL, &buf, &len);
3428 if (!NT_STATUS_IS_OK(status)) {
3429 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
3430 nt_errstr(status));
3431 } else {
3432 printf("qfileinfo: level %d, len = %u\n", level, len);
3433 dump_data(0, (uint8 *)buf, len);
3434 printf("\n");
3436 TALLOC_FREE(buf);
3437 return status;
3440 static bool run_w2ktest(int dummy)
3442 struct cli_state *cli;
3443 uint16_t fnum;
3444 const char *fname = "\\w2ktest\\w2k.tst";
3445 int level;
3446 bool correct = True;
3448 printf("starting w2k test\n");
3450 if (!torture_open_connection(&cli, 0)) {
3451 return False;
3454 cli_open(cli, fname,
3455 O_RDWR | O_CREAT , DENY_NONE, &fnum);
3457 for (level = 1004; level < 1040; level++) {
3458 new_trans(cli, fnum, level);
3461 cli_close(cli, fnum);
3463 if (!torture_close_connection(cli)) {
3464 correct = False;
3467 printf("w2k test finished\n");
3469 return correct;
3474 this is a harness for some oplock tests
3476 static bool run_oplock1(int dummy)
3478 struct cli_state *cli1;
3479 const char *fname = "\\lockt1.lck";
3480 uint16_t fnum1;
3481 bool correct = True;
3482 NTSTATUS status;
3484 printf("starting oplock test 1\n");
3486 if (!torture_open_connection(&cli1, 0)) {
3487 return False;
3490 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3492 cli_sockopt(cli1, sockops);
3494 cli1->use_oplocks = True;
3496 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3497 &fnum1);
3498 if (!NT_STATUS_IS_OK(status)) {
3499 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3500 return False;
3503 cli1->use_oplocks = False;
3505 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3506 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3508 status = cli_close(cli1, fnum1);
3509 if (!NT_STATUS_IS_OK(status)) {
3510 printf("close2 failed (%s)\n", nt_errstr(status));
3511 return False;
3514 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3515 if (!NT_STATUS_IS_OK(status)) {
3516 printf("unlink failed (%s)\n", nt_errstr(status));
3517 return False;
3520 if (!torture_close_connection(cli1)) {
3521 correct = False;
3524 printf("finished oplock test 1\n");
3526 return correct;
3529 static bool run_oplock2(int dummy)
3531 struct cli_state *cli1, *cli2;
3532 const char *fname = "\\lockt2.lck";
3533 uint16_t fnum1, fnum2;
3534 int saved_use_oplocks = use_oplocks;
3535 char buf[4];
3536 bool correct = True;
3537 volatile bool *shared_correct;
3538 size_t nread;
3539 NTSTATUS status;
3541 shared_correct = (volatile bool *)shm_setup(sizeof(bool));
3542 *shared_correct = True;
3544 use_level_II_oplocks = True;
3545 use_oplocks = True;
3547 printf("starting oplock test 2\n");
3549 if (!torture_open_connection(&cli1, 0)) {
3550 use_level_II_oplocks = False;
3551 use_oplocks = saved_use_oplocks;
3552 return False;
3555 if (!torture_open_connection(&cli2, 1)) {
3556 use_level_II_oplocks = False;
3557 use_oplocks = saved_use_oplocks;
3558 return False;
3561 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3563 cli_sockopt(cli1, sockops);
3564 cli_sockopt(cli2, sockops);
3566 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3567 &fnum1);
3568 if (!NT_STATUS_IS_OK(status)) {
3569 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3570 return False;
3573 /* Don't need the globals any more. */
3574 use_level_II_oplocks = False;
3575 use_oplocks = saved_use_oplocks;
3577 if (fork() == 0) {
3578 /* Child code */
3579 status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
3580 if (!NT_STATUS_IS_OK(status)) {
3581 printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
3582 *shared_correct = False;
3583 exit(0);
3586 sleep(2);
3588 status = cli_close(cli2, fnum2);
3589 if (!NT_STATUS_IS_OK(status)) {
3590 printf("close2 failed (%s)\n", nt_errstr(status));
3591 *shared_correct = False;
3594 exit(0);
3597 sleep(2);
3599 /* Ensure cli1 processes the break. Empty file should always return 0
3600 * bytes. */
3601 status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
3602 if (!NT_STATUS_IS_OK(status)) {
3603 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
3604 correct = false;
3605 } else if (nread != 0) {
3606 printf("read on empty fnum1 failed. recv %ld expected %d\n",
3607 (unsigned long)nread, 0);
3608 correct = false;
3611 /* Should now be at level II. */
3612 /* Test if sending a write locks causes a break to none. */
3613 status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
3614 if (!NT_STATUS_IS_OK(status)) {
3615 printf("lock failed (%s)\n", nt_errstr(status));
3616 correct = False;
3619 cli_unlock(cli1, fnum1, 0, 4);
3621 sleep(2);
3623 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
3624 if (!NT_STATUS_IS_OK(status)) {
3625 printf("lock failed (%s)\n", nt_errstr(status));
3626 correct = False;
3629 cli_unlock(cli1, fnum1, 0, 4);
3631 sleep(2);
3633 cli_read(cli1, fnum1, buf, 0, 4, NULL);
3635 status = cli_close(cli1, fnum1);
3636 if (!NT_STATUS_IS_OK(status)) {
3637 printf("close1 failed (%s)\n", nt_errstr(status));
3638 correct = False;
3641 sleep(4);
3643 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3644 if (!NT_STATUS_IS_OK(status)) {
3645 printf("unlink failed (%s)\n", nt_errstr(status));
3646 correct = False;
3649 if (!torture_close_connection(cli1)) {
3650 correct = False;
3653 if (!*shared_correct) {
3654 correct = False;
3657 printf("finished oplock test 2\n");
3659 return correct;
3662 struct oplock4_state {
3663 struct tevent_context *ev;
3664 struct cli_state *cli;
3665 bool *got_break;
3666 uint16_t *fnum2;
3669 static void oplock4_got_break(struct tevent_req *req);
3670 static void oplock4_got_open(struct tevent_req *req);
3672 static bool run_oplock4(int dummy)
3674 struct tevent_context *ev;
3675 struct cli_state *cli1, *cli2;
3676 struct tevent_req *oplock_req, *open_req;
3677 const char *fname = "\\lockt4.lck";
3678 const char *fname_ln = "\\lockt4_ln.lck";
3679 uint16_t fnum1, fnum2;
3680 int saved_use_oplocks = use_oplocks;
3681 NTSTATUS status;
3682 bool correct = true;
3684 bool got_break;
3686 struct oplock4_state *state;
3688 printf("starting oplock test 4\n");
3690 if (!torture_open_connection(&cli1, 0)) {
3691 use_level_II_oplocks = false;
3692 use_oplocks = saved_use_oplocks;
3693 return false;
3696 if (!torture_open_connection(&cli2, 1)) {
3697 use_level_II_oplocks = false;
3698 use_oplocks = saved_use_oplocks;
3699 return false;
3702 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3703 cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3705 cli_sockopt(cli1, sockops);
3706 cli_sockopt(cli2, sockops);
3708 /* Create the file. */
3709 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3710 &fnum1);
3711 if (!NT_STATUS_IS_OK(status)) {
3712 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3713 return false;
3716 status = cli_close(cli1, fnum1);
3717 if (!NT_STATUS_IS_OK(status)) {
3718 printf("close1 failed (%s)\n", nt_errstr(status));
3719 return false;
3722 /* Now create a hardlink. */
3723 status = cli_nt_hardlink(cli1, fname, fname_ln);
3724 if (!NT_STATUS_IS_OK(status)) {
3725 printf("nt hardlink failed (%s)\n", nt_errstr(status));
3726 return false;
3729 /* Prove that opening hardlinks cause deny modes to conflict. */
3730 status = cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
3731 if (!NT_STATUS_IS_OK(status)) {
3732 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3733 return false;
3736 status = cli_open(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
3737 if (NT_STATUS_IS_OK(status)) {
3738 printf("open of %s succeeded - should fail with sharing violation.\n",
3739 fname_ln);
3740 return false;
3743 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3744 printf("open of %s should fail with sharing violation. Got %s\n",
3745 fname_ln, nt_errstr(status));
3746 return false;
3749 status = cli_close(cli1, fnum1);
3750 if (!NT_STATUS_IS_OK(status)) {
3751 printf("close1 failed (%s)\n", nt_errstr(status));
3752 return false;
3755 cli1->use_oplocks = true;
3756 cli2->use_oplocks = true;
3758 status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3759 if (!NT_STATUS_IS_OK(status)) {
3760 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3761 return false;
3764 ev = tevent_context_init(talloc_tos());
3765 if (ev == NULL) {
3766 printf("tevent_req_create failed\n");
3767 return false;
3770 state = talloc(ev, struct oplock4_state);
3771 if (state == NULL) {
3772 printf("talloc failed\n");
3773 return false;
3775 state->ev = ev;
3776 state->cli = cli1;
3777 state->got_break = &got_break;
3778 state->fnum2 = &fnum2;
3780 oplock_req = cli_smb_oplock_break_waiter_send(
3781 talloc_tos(), ev, cli1);
3782 if (oplock_req == NULL) {
3783 printf("cli_smb_oplock_break_waiter_send failed\n");
3784 return false;
3786 tevent_req_set_callback(oplock_req, oplock4_got_break, state);
3788 open_req = cli_open_send(
3789 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
3790 if (oplock_req == NULL) {
3791 printf("cli_open_send failed\n");
3792 return false;
3794 tevent_req_set_callback(open_req, oplock4_got_open, state);
3796 got_break = false;
3797 fnum2 = 0xffff;
3799 while (!got_break || fnum2 == 0xffff) {
3800 int ret;
3801 ret = tevent_loop_once(ev);
3802 if (ret == -1) {
3803 printf("tevent_loop_once failed: %s\n",
3804 strerror(errno));
3805 return false;
3809 status = cli_close(cli2, fnum2);
3810 if (!NT_STATUS_IS_OK(status)) {
3811 printf("close2 failed (%s)\n", nt_errstr(status));
3812 correct = false;
3815 status = cli_close(cli1, fnum1);
3816 if (!NT_STATUS_IS_OK(status)) {
3817 printf("close1 failed (%s)\n", nt_errstr(status));
3818 correct = false;
3821 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3822 if (!NT_STATUS_IS_OK(status)) {
3823 printf("unlink failed (%s)\n", nt_errstr(status));
3824 correct = false;
3827 status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3828 if (!NT_STATUS_IS_OK(status)) {
3829 printf("unlink failed (%s)\n", nt_errstr(status));
3830 correct = false;
3833 if (!torture_close_connection(cli1)) {
3834 correct = false;
3837 if (!got_break) {
3838 correct = false;
3841 printf("finished oplock test 4\n");
3843 return correct;
3846 static void oplock4_got_break(struct tevent_req *req)
3848 struct oplock4_state *state = tevent_req_callback_data(
3849 req, struct oplock4_state);
3850 uint16_t fnum;
3851 uint8_t level;
3852 NTSTATUS status;
3854 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
3855 TALLOC_FREE(req);
3856 if (!NT_STATUS_IS_OK(status)) {
3857 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
3858 nt_errstr(status));
3859 return;
3861 *state->got_break = true;
3863 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
3864 NO_OPLOCK);
3865 if (req == NULL) {
3866 printf("cli_oplock_ack_send failed\n");
3867 return;
3871 static void oplock4_got_open(struct tevent_req *req)
3873 struct oplock4_state *state = tevent_req_callback_data(
3874 req, struct oplock4_state);
3875 NTSTATUS status;
3877 status = cli_open_recv(req, state->fnum2);
3878 if (!NT_STATUS_IS_OK(status)) {
3879 printf("cli_open_recv returned %s\n", nt_errstr(status));
3880 *state->fnum2 = 0xffff;
3885 Test delete on close semantics.
3887 static bool run_deletetest(int dummy)
3889 struct cli_state *cli1 = NULL;
3890 struct cli_state *cli2 = NULL;
3891 const char *fname = "\\delete.file";
3892 uint16_t fnum1 = (uint16_t)-1;
3893 uint16_t fnum2 = (uint16_t)-1;
3894 bool correct = True;
3895 NTSTATUS status;
3897 printf("starting delete test\n");
3899 if (!torture_open_connection(&cli1, 0)) {
3900 return False;
3903 cli_sockopt(cli1, sockops);
3905 /* Test 1 - this should delete the file on close. */
3907 cli_setatr(cli1, fname, 0, 0);
3908 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3910 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
3911 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
3912 FILE_DELETE_ON_CLOSE, 0, &fnum1);
3913 if (!NT_STATUS_IS_OK(status)) {
3914 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
3915 correct = False;
3916 goto fail;
3919 status = cli_close(cli1, fnum1);
3920 if (!NT_STATUS_IS_OK(status)) {
3921 printf("[1] close failed (%s)\n", nt_errstr(status));
3922 correct = False;
3923 goto fail;
3926 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1))) {
3927 printf("[1] open of %s succeeded (should fail)\n", fname);
3928 correct = False;
3929 goto fail;
3932 printf("first delete on close test succeeded.\n");
3934 /* Test 2 - this should delete the file on close. */
3936 cli_setatr(cli1, fname, 0, 0);
3937 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3939 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3940 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
3941 FILE_OVERWRITE_IF, 0, 0, &fnum1);
3942 if (!NT_STATUS_IS_OK(status)) {
3943 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
3944 correct = False;
3945 goto fail;
3948 status = cli_nt_delete_on_close(cli1, fnum1, true);
3949 if (!NT_STATUS_IS_OK(status)) {
3950 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
3951 correct = False;
3952 goto fail;
3955 status = cli_close(cli1, fnum1);
3956 if (!NT_STATUS_IS_OK(status)) {
3957 printf("[2] close failed (%s)\n", nt_errstr(status));
3958 correct = False;
3959 goto fail;
3962 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3963 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
3964 status = cli_close(cli1, fnum1);
3965 if (!NT_STATUS_IS_OK(status)) {
3966 printf("[2] close failed (%s)\n", nt_errstr(status));
3967 correct = False;
3968 goto fail;
3970 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3971 } else
3972 printf("second delete on close test succeeded.\n");
3974 /* Test 3 - ... */
3975 cli_setatr(cli1, fname, 0, 0);
3976 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3978 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3979 FILE_ATTRIBUTE_NORMAL,
3980 FILE_SHARE_READ|FILE_SHARE_WRITE,
3981 FILE_OVERWRITE_IF, 0, 0, &fnum1);
3982 if (!NT_STATUS_IS_OK(status)) {
3983 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
3984 correct = False;
3985 goto fail;
3988 /* This should fail with a sharing violation - open for delete is only compatible
3989 with SHARE_DELETE. */
3991 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
3992 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, 0, &fnum2))) {
3993 printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
3994 correct = False;
3995 goto fail;
3998 /* This should succeed. */
3999 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4000 FILE_ATTRIBUTE_NORMAL,
4001 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4002 FILE_OPEN, 0, 0, &fnum2);
4003 if (!NT_STATUS_IS_OK(status)) {
4004 printf("[3] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
4005 correct = False;
4006 goto fail;
4009 status = cli_nt_delete_on_close(cli1, fnum1, true);
4010 if (!NT_STATUS_IS_OK(status)) {
4011 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
4012 correct = False;
4013 goto fail;
4016 status = cli_close(cli1, fnum1);
4017 if (!NT_STATUS_IS_OK(status)) {
4018 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
4019 correct = False;
4020 goto fail;
4023 status = cli_close(cli1, fnum2);
4024 if (!NT_STATUS_IS_OK(status)) {
4025 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
4026 correct = False;
4027 goto fail;
4030 /* This should fail - file should no longer be there. */
4032 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
4033 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
4034 status = cli_close(cli1, fnum1);
4035 if (!NT_STATUS_IS_OK(status)) {
4036 printf("[3] close failed (%s)\n", nt_errstr(status));
4038 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4039 correct = False;
4040 goto fail;
4041 } else
4042 printf("third delete on close test succeeded.\n");
4044 /* Test 4 ... */
4045 cli_setatr(cli1, fname, 0, 0);
4046 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4048 status = cli_ntcreate(cli1, fname, 0,
4049 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4050 FILE_ATTRIBUTE_NORMAL,
4051 FILE_SHARE_READ|FILE_SHARE_WRITE,
4052 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4053 if (!NT_STATUS_IS_OK(status)) {
4054 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
4055 correct = False;
4056 goto fail;
4059 /* This should succeed. */
4060 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4061 FILE_ATTRIBUTE_NORMAL,
4062 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4063 FILE_OPEN, 0, 0, &fnum2);
4064 if (!NT_STATUS_IS_OK(status)) {
4065 printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
4066 correct = False;
4067 goto fail;
4070 status = cli_close(cli1, fnum2);
4071 if (!NT_STATUS_IS_OK(status)) {
4072 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
4073 correct = False;
4074 goto fail;
4077 status = cli_nt_delete_on_close(cli1, fnum1, true);
4078 if (!NT_STATUS_IS_OK(status)) {
4079 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
4080 correct = False;
4081 goto fail;
4084 /* This should fail - no more opens once delete on close set. */
4085 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4086 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4087 FILE_OPEN, 0, 0, &fnum2))) {
4088 printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
4089 correct = False;
4090 goto fail;
4091 } else
4092 printf("fourth delete on close test succeeded.\n");
4094 status = cli_close(cli1, fnum1);
4095 if (!NT_STATUS_IS_OK(status)) {
4096 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
4097 correct = False;
4098 goto fail;
4101 /* Test 5 ... */
4102 cli_setatr(cli1, fname, 0, 0);
4103 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4105 status = cli_open(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
4106 if (!NT_STATUS_IS_OK(status)) {
4107 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4108 correct = False;
4109 goto fail;
4112 /* This should fail - only allowed on NT opens with DELETE access. */
4114 if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4115 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
4116 correct = False;
4117 goto fail;
4120 status = cli_close(cli1, fnum1);
4121 if (!NT_STATUS_IS_OK(status)) {
4122 printf("[5] close - 2 failed (%s)\n", nt_errstr(status));
4123 correct = False;
4124 goto fail;
4127 printf("fifth delete on close test succeeded.\n");
4129 /* Test 6 ... */
4130 cli_setatr(cli1, fname, 0, 0);
4131 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4133 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4134 FILE_ATTRIBUTE_NORMAL,
4135 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4136 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4137 if (!NT_STATUS_IS_OK(status)) {
4138 printf("[6] open of %s failed (%s)\n", fname,
4139 nt_errstr(status));
4140 correct = False;
4141 goto fail;
4144 /* This should fail - only allowed on NT opens with DELETE access. */
4146 if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4147 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
4148 correct = False;
4149 goto fail;
4152 status = cli_close(cli1, fnum1);
4153 if (!NT_STATUS_IS_OK(status)) {
4154 printf("[6] close - 2 failed (%s)\n", nt_errstr(status));
4155 correct = False;
4156 goto fail;
4159 printf("sixth delete on close test succeeded.\n");
4161 /* Test 7 ... */
4162 cli_setatr(cli1, fname, 0, 0);
4163 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4165 status = cli_ntcreate(cli1, fname, 0,
4166 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4167 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
4168 0, 0, &fnum1);
4169 if (!NT_STATUS_IS_OK(status)) {
4170 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4171 correct = False;
4172 goto fail;
4175 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4176 printf("[7] setting delete_on_close on file failed !\n");
4177 correct = False;
4178 goto fail;
4181 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, false))) {
4182 printf("[7] unsetting delete_on_close on file failed !\n");
4183 correct = False;
4184 goto fail;
4187 status = cli_close(cli1, fnum1);
4188 if (!NT_STATUS_IS_OK(status)) {
4189 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4190 correct = False;
4191 goto fail;
4194 /* This next open should succeed - we reset the flag. */
4195 status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4196 if (!NT_STATUS_IS_OK(status)) {
4197 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4198 correct = False;
4199 goto fail;
4202 status = cli_close(cli1, fnum1);
4203 if (!NT_STATUS_IS_OK(status)) {
4204 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4205 correct = False;
4206 goto fail;
4209 printf("seventh delete on close test succeeded.\n");
4211 /* Test 7 ... */
4212 cli_setatr(cli1, fname, 0, 0);
4213 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4215 if (!torture_open_connection(&cli2, 1)) {
4216 printf("[8] failed to open second connection.\n");
4217 correct = False;
4218 goto fail;
4221 cli_sockopt(cli1, sockops);
4223 status = cli_ntcreate(cli1, fname, 0,
4224 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4225 FILE_ATTRIBUTE_NORMAL,
4226 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4227 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4228 if (!NT_STATUS_IS_OK(status)) {
4229 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4230 correct = False;
4231 goto fail;
4234 status = cli_ntcreate(cli2, fname, 0,
4235 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4236 FILE_ATTRIBUTE_NORMAL,
4237 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4238 FILE_OPEN, 0, 0, &fnum2);
4239 if (!NT_STATUS_IS_OK(status)) {
4240 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4241 correct = False;
4242 goto fail;
4245 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4246 printf("[8] setting delete_on_close on file failed !\n");
4247 correct = False;
4248 goto fail;
4251 status = cli_close(cli1, fnum1);
4252 if (!NT_STATUS_IS_OK(status)) {
4253 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
4254 correct = False;
4255 goto fail;
4258 status = cli_close(cli2, fnum2);
4259 if (!NT_STATUS_IS_OK(status)) {
4260 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
4261 correct = False;
4262 goto fail;
4265 /* This should fail.. */
4266 status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4267 if (NT_STATUS_IS_OK(status)) {
4268 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
4269 goto fail;
4270 correct = False;
4271 } else
4272 printf("eighth delete on close test succeeded.\n");
4274 /* This should fail - we need to set DELETE_ACCESS. */
4275 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0,FILE_READ_DATA|FILE_WRITE_DATA,
4276 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE, 0, &fnum1))) {
4277 printf("[9] open of %s succeeded should have failed!\n", fname);
4278 correct = False;
4279 goto fail;
4282 printf("ninth delete on close test succeeded.\n");
4284 status = cli_ntcreate(cli1, fname, 0,
4285 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4286 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4287 FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
4288 0, &fnum1);
4289 if (!NT_STATUS_IS_OK(status)) {
4290 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
4291 correct = False;
4292 goto fail;
4295 /* This should delete the file. */
4296 status = cli_close(cli1, fnum1);
4297 if (!NT_STATUS_IS_OK(status)) {
4298 printf("[10] close failed (%s)\n", nt_errstr(status));
4299 correct = False;
4300 goto fail;
4303 /* This should fail.. */
4304 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
4305 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
4306 goto fail;
4307 correct = False;
4308 } else
4309 printf("tenth delete on close test succeeded.\n");
4311 cli_setatr(cli1, fname, 0, 0);
4312 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4314 /* What error do we get when attempting to open a read-only file with
4315 delete access ? */
4317 /* Create a readonly file. */
4318 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4319 FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
4320 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4321 if (!NT_STATUS_IS_OK(status)) {
4322 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
4323 correct = False;
4324 goto fail;
4327 status = cli_close(cli1, fnum1);
4328 if (!NT_STATUS_IS_OK(status)) {
4329 printf("[11] close failed (%s)\n", nt_errstr(status));
4330 correct = False;
4331 goto fail;
4334 /* Now try open for delete access. */
4335 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES|DELETE_ACCESS,
4336 0, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4337 FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4338 printf("[11] open of %s succeeded should have been denied with ACCESS_DENIED!\n", fname);
4339 cli_close(cli1, fnum1);
4340 goto fail;
4341 correct = False;
4342 } else {
4343 NTSTATUS nterr = cli_nt_error(cli1);
4344 if (!NT_STATUS_EQUAL(nterr,NT_STATUS_ACCESS_DENIED)) {
4345 printf("[11] open of %s should have been denied with ACCESS_DENIED! Got error %s\n", fname, nt_errstr(nterr));
4346 goto fail;
4347 correct = False;
4348 } else {
4349 printf("eleventh delete on close test succeeded.\n");
4353 printf("finished delete test\n");
4355 fail:
4356 /* FIXME: This will crash if we aborted before cli2 got
4357 * intialized, because these functions don't handle
4358 * uninitialized connections. */
4360 if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
4361 if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
4362 cli_setatr(cli1, fname, 0, 0);
4363 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4365 if (cli1 && !torture_close_connection(cli1)) {
4366 correct = False;
4368 if (cli2 && !torture_close_connection(cli2)) {
4369 correct = False;
4371 return correct;
4374 static bool run_deletetest_ln(int dummy)
4376 struct cli_state *cli;
4377 const char *fname = "\\delete1";
4378 const char *fname_ln = "\\delete1_ln";
4379 uint16_t fnum;
4380 uint16_t fnum1;
4381 NTSTATUS status;
4382 bool correct = true;
4383 time_t t;
4385 printf("starting deletetest-ln\n");
4387 if (!torture_open_connection(&cli, 0)) {
4388 return false;
4391 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4392 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4394 cli_sockopt(cli, sockops);
4396 /* Create the file. */
4397 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
4398 if (!NT_STATUS_IS_OK(status)) {
4399 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4400 return false;
4403 status = cli_close(cli, fnum);
4404 if (!NT_STATUS_IS_OK(status)) {
4405 printf("close1 failed (%s)\n", nt_errstr(status));
4406 return false;
4409 /* Now create a hardlink. */
4410 status = cli_nt_hardlink(cli, fname, fname_ln);
4411 if (!NT_STATUS_IS_OK(status)) {
4412 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4413 return false;
4416 /* Open the original file. */
4417 status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
4418 FILE_ATTRIBUTE_NORMAL,
4419 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4420 FILE_OPEN_IF, 0, 0, &fnum);
4421 if (!NT_STATUS_IS_OK(status)) {
4422 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
4423 return false;
4426 /* Unlink the hard link path. */
4427 status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
4428 FILE_ATTRIBUTE_NORMAL,
4429 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4430 FILE_OPEN_IF, 0, 0, &fnum1);
4431 if (!NT_STATUS_IS_OK(status)) {
4432 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
4433 return false;
4435 status = cli_nt_delete_on_close(cli, fnum1, true);
4436 if (!NT_STATUS_IS_OK(status)) {
4437 d_printf("(%s) failed to set delete_on_close %s: %s\n",
4438 __location__, fname_ln, nt_errstr(status));
4439 return false;
4442 status = cli_close(cli, fnum1);
4443 if (!NT_STATUS_IS_OK(status)) {
4444 printf("close %s failed (%s)\n",
4445 fname_ln, nt_errstr(status));
4446 return false;
4449 status = cli_close(cli, fnum);
4450 if (!NT_STATUS_IS_OK(status)) {
4451 printf("close %s failed (%s)\n",
4452 fname, nt_errstr(status));
4453 return false;
4456 /* Ensure the original file is still there. */
4457 status = cli_getatr(cli, fname, NULL, NULL, &t);
4458 if (!NT_STATUS_IS_OK(status)) {
4459 printf("%s getatr on file %s failed (%s)\n",
4460 __location__,
4461 fname,
4462 nt_errstr(status));
4463 correct = False;
4466 /* Ensure the link path is gone. */
4467 status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
4468 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4469 printf("%s, getatr for file %s returned wrong error code %s "
4470 "- should have been deleted\n",
4471 __location__,
4472 fname_ln, nt_errstr(status));
4473 correct = False;
4476 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4477 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4479 if (!torture_close_connection(cli)) {
4480 correct = false;
4483 printf("finished deletetest-ln\n");
4485 return correct;
4489 print out server properties
4491 static bool run_properties(int dummy)
4493 struct cli_state *cli;
4494 bool correct = True;
4496 printf("starting properties test\n");
4498 ZERO_STRUCT(cli);
4500 if (!torture_open_connection(&cli, 0)) {
4501 return False;
4504 cli_sockopt(cli, sockops);
4506 d_printf("Capabilities 0x%08x\n", cli_state_capabilities(cli));
4508 if (!torture_close_connection(cli)) {
4509 correct = False;
4512 return correct;
4517 /* FIRST_DESIRED_ACCESS 0xf019f */
4518 #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
4519 FILE_READ_EA| /* 0xf */ \
4520 FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
4521 FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
4522 DELETE_ACCESS|READ_CONTROL_ACCESS|\
4523 WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
4524 /* SECOND_DESIRED_ACCESS 0xe0080 */
4525 #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
4526 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4527 WRITE_OWNER_ACCESS /* 0xe0000 */
4529 #if 0
4530 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
4531 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4532 FILE_READ_DATA|\
4533 WRITE_OWNER_ACCESS /* */
4534 #endif
4537 Test ntcreate calls made by xcopy
4539 static bool run_xcopy(int dummy)
4541 static struct cli_state *cli1;
4542 const char *fname = "\\test.txt";
4543 bool correct = True;
4544 uint16_t fnum1, fnum2;
4545 NTSTATUS status;
4547 printf("starting xcopy test\n");
4549 if (!torture_open_connection(&cli1, 0)) {
4550 return False;
4553 status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
4554 FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
4555 FILE_OVERWRITE_IF, 0x4044, 0, &fnum1);
4556 if (!NT_STATUS_IS_OK(status)) {
4557 printf("First open failed - %s\n", nt_errstr(status));
4558 return False;
4561 status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
4562 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4563 FILE_OPEN, 0x200000, 0, &fnum2);
4564 if (!NT_STATUS_IS_OK(status)) {
4565 printf("second open failed - %s\n", nt_errstr(status));
4566 return False;
4569 if (!torture_close_connection(cli1)) {
4570 correct = False;
4573 return correct;
4577 Test rename on files open with share delete and no share delete.
4579 static bool run_rename(int dummy)
4581 static struct cli_state *cli1;
4582 const char *fname = "\\test.txt";
4583 const char *fname1 = "\\test1.txt";
4584 bool correct = True;
4585 uint16_t fnum1;
4586 uint16_t attr;
4587 NTSTATUS status;
4589 printf("starting rename test\n");
4591 if (!torture_open_connection(&cli1, 0)) {
4592 return False;
4595 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4596 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4598 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4599 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
4600 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4601 if (!NT_STATUS_IS_OK(status)) {
4602 printf("First open failed - %s\n", nt_errstr(status));
4603 return False;
4606 status = cli_rename(cli1, fname, fname1);
4607 if (!NT_STATUS_IS_OK(status)) {
4608 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
4609 } else {
4610 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
4611 correct = False;
4614 status = cli_close(cli1, fnum1);
4615 if (!NT_STATUS_IS_OK(status)) {
4616 printf("close - 1 failed (%s)\n", nt_errstr(status));
4617 return False;
4620 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4621 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4622 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4623 #if 0
4624 FILE_SHARE_DELETE|FILE_SHARE_NONE,
4625 #else
4626 FILE_SHARE_DELETE|FILE_SHARE_READ,
4627 #endif
4628 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4629 if (!NT_STATUS_IS_OK(status)) {
4630 printf("Second open failed - %s\n", nt_errstr(status));
4631 return False;
4634 status = cli_rename(cli1, fname, fname1);
4635 if (!NT_STATUS_IS_OK(status)) {
4636 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
4637 correct = False;
4638 } else {
4639 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
4642 status = cli_close(cli1, fnum1);
4643 if (!NT_STATUS_IS_OK(status)) {
4644 printf("close - 2 failed (%s)\n", nt_errstr(status));
4645 return False;
4648 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4649 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4651 status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
4652 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4653 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4654 if (!NT_STATUS_IS_OK(status)) {
4655 printf("Third open failed - %s\n", nt_errstr(status));
4656 return False;
4660 #if 0
4662 uint16_t fnum2;
4664 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
4665 FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4666 printf("Fourth open failed - %s\n", cli_errstr(cli1));
4667 return False;
4669 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum2, true))) {
4670 printf("[8] setting delete_on_close on file failed !\n");
4671 return False;
4674 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
4675 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
4676 return False;
4679 #endif
4681 status = cli_rename(cli1, fname, fname1);
4682 if (!NT_STATUS_IS_OK(status)) {
4683 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
4684 correct = False;
4685 } else {
4686 printf("Third rename succeeded (SHARE_NONE)\n");
4689 status = cli_close(cli1, fnum1);
4690 if (!NT_STATUS_IS_OK(status)) {
4691 printf("close - 3 failed (%s)\n", nt_errstr(status));
4692 return False;
4695 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4696 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4698 /*----*/
4700 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4701 FILE_ATTRIBUTE_NORMAL,
4702 FILE_SHARE_READ | FILE_SHARE_WRITE,
4703 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4704 if (!NT_STATUS_IS_OK(status)) {
4705 printf("Fourth open failed - %s\n", nt_errstr(status));
4706 return False;
4709 status = cli_rename(cli1, fname, fname1);
4710 if (!NT_STATUS_IS_OK(status)) {
4711 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
4712 } else {
4713 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
4714 correct = False;
4717 status = cli_close(cli1, fnum1);
4718 if (!NT_STATUS_IS_OK(status)) {
4719 printf("close - 4 failed (%s)\n", nt_errstr(status));
4720 return False;
4723 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4724 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4726 /*--*/
4728 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4729 FILE_ATTRIBUTE_NORMAL,
4730 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4731 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4732 if (!NT_STATUS_IS_OK(status)) {
4733 printf("Fifth open failed - %s\n", nt_errstr(status));
4734 return False;
4737 status = cli_rename(cli1, fname, fname1);
4738 if (!NT_STATUS_IS_OK(status)) {
4739 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
4740 correct = False;
4741 } else {
4742 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
4746 * Now check if the first name still exists ...
4749 /* if (!NT_STATUS_OP(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4750 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4751 printf("Opening original file after rename of open file fails: %s\n",
4752 cli_errstr(cli1));
4754 else {
4755 printf("Opening original file after rename of open file works ...\n");
4756 (void)cli_close(cli1, fnum2);
4757 } */
4759 /*--*/
4760 status = cli_close(cli1, fnum1);
4761 if (!NT_STATUS_IS_OK(status)) {
4762 printf("close - 5 failed (%s)\n", nt_errstr(status));
4763 return False;
4766 /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
4767 status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
4768 if (!NT_STATUS_IS_OK(status)) {
4769 printf("getatr on file %s failed - %s ! \n",
4770 fname1, nt_errstr(status));
4771 correct = False;
4772 } else {
4773 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
4774 printf("Renamed file %s has wrong attr 0x%x "
4775 "(should be 0x%x)\n",
4776 fname1,
4777 attr,
4778 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
4779 correct = False;
4780 } else {
4781 printf("Renamed file %s has archive bit set\n", fname1);
4785 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4786 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4788 if (!torture_close_connection(cli1)) {
4789 correct = False;
4792 return correct;
4795 static bool run_pipe_number(int dummy)
4797 struct cli_state *cli1;
4798 const char *pipe_name = "\\SPOOLSS";
4799 uint16_t fnum;
4800 int num_pipes = 0;
4801 NTSTATUS status;
4803 printf("starting pipenumber test\n");
4804 if (!torture_open_connection(&cli1, 0)) {
4805 return False;
4808 cli_sockopt(cli1, sockops);
4809 while(1) {
4810 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
4811 FILE_ATTRIBUTE_NORMAL,
4812 FILE_SHARE_READ|FILE_SHARE_WRITE,
4813 FILE_OPEN_IF, 0, 0, &fnum);
4814 if (!NT_STATUS_IS_OK(status)) {
4815 printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
4816 break;
4818 num_pipes++;
4819 printf("\r%6d", num_pipes);
4822 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
4823 torture_close_connection(cli1);
4824 return True;
4828 Test open mode returns on read-only files.
4830 static bool run_opentest(int dummy)
4832 static struct cli_state *cli1;
4833 static struct cli_state *cli2;
4834 const char *fname = "\\readonly.file";
4835 uint16_t fnum1, fnum2;
4836 char buf[20];
4837 SMB_OFF_T fsize;
4838 bool correct = True;
4839 char *tmp_path;
4840 NTSTATUS status;
4842 printf("starting open test\n");
4844 if (!torture_open_connection(&cli1, 0)) {
4845 return False;
4848 cli_setatr(cli1, fname, 0, 0);
4849 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4851 cli_sockopt(cli1, sockops);
4853 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4854 if (!NT_STATUS_IS_OK(status)) {
4855 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4856 return False;
4859 status = cli_close(cli1, fnum1);
4860 if (!NT_STATUS_IS_OK(status)) {
4861 printf("close2 failed (%s)\n", nt_errstr(status));
4862 return False;
4865 status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
4866 if (!NT_STATUS_IS_OK(status)) {
4867 printf("cli_setatr failed (%s)\n", nt_errstr(status));
4868 return False;
4871 status = cli_open(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4872 if (!NT_STATUS_IS_OK(status)) {
4873 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4874 return False;
4877 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
4878 status = cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4880 if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
4881 NT_STATUS_ACCESS_DENIED)) {
4882 printf("correct error code ERRDOS/ERRnoaccess returned\n");
4885 printf("finished open test 1\n");
4887 cli_close(cli1, fnum1);
4889 /* Now try not readonly and ensure ERRbadshare is returned. */
4891 cli_setatr(cli1, fname, 0, 0);
4893 status = cli_open(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4894 if (!NT_STATUS_IS_OK(status)) {
4895 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4896 return False;
4899 /* This will fail - but the error should be ERRshare. */
4900 status = cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4902 if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
4903 NT_STATUS_SHARING_VIOLATION)) {
4904 printf("correct error code ERRDOS/ERRbadshare returned\n");
4907 status = cli_close(cli1, fnum1);
4908 if (!NT_STATUS_IS_OK(status)) {
4909 printf("close2 failed (%s)\n", nt_errstr(status));
4910 return False;
4913 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4915 printf("finished open test 2\n");
4917 /* Test truncate open disposition on file opened for read. */
4918 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4919 if (!NT_STATUS_IS_OK(status)) {
4920 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
4921 return False;
4924 /* write 20 bytes. */
4926 memset(buf, '\0', 20);
4928 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
4929 if (!NT_STATUS_IS_OK(status)) {
4930 printf("write failed (%s)\n", nt_errstr(status));
4931 correct = False;
4934 status = cli_close(cli1, fnum1);
4935 if (!NT_STATUS_IS_OK(status)) {
4936 printf("(3) close1 failed (%s)\n", nt_errstr(status));
4937 return False;
4940 /* Ensure size == 20. */
4941 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
4942 if (!NT_STATUS_IS_OK(status)) {
4943 printf("(3) getatr failed (%s)\n", nt_errstr(status));
4944 return False;
4947 if (fsize != 20) {
4948 printf("(3) file size != 20\n");
4949 return False;
4952 /* Now test if we can truncate a file opened for readonly. */
4953 status = cli_open(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
4954 if (!NT_STATUS_IS_OK(status)) {
4955 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
4956 return False;
4959 status = cli_close(cli1, fnum1);
4960 if (!NT_STATUS_IS_OK(status)) {
4961 printf("close2 failed (%s)\n", nt_errstr(status));
4962 return False;
4965 /* Ensure size == 0. */
4966 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
4967 if (!NT_STATUS_IS_OK(status)) {
4968 printf("(3) getatr failed (%s)\n", nt_errstr(status));
4969 return False;
4972 if (fsize != 0) {
4973 printf("(3) file size != 0\n");
4974 return False;
4976 printf("finished open test 3\n");
4978 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4980 printf("Do ctemp tests\n");
4981 status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
4982 if (!NT_STATUS_IS_OK(status)) {
4983 printf("ctemp failed (%s)\n", nt_errstr(status));
4984 return False;
4987 printf("ctemp gave path %s\n", tmp_path);
4988 status = cli_close(cli1, fnum1);
4989 if (!NT_STATUS_IS_OK(status)) {
4990 printf("close of temp failed (%s)\n", nt_errstr(status));
4993 status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4994 if (!NT_STATUS_IS_OK(status)) {
4995 printf("unlink of temp failed (%s)\n", nt_errstr(status));
4998 /* Test the non-io opens... */
5000 if (!torture_open_connection(&cli2, 1)) {
5001 return False;
5004 cli_setatr(cli2, fname, 0, 0);
5005 cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5007 cli_sockopt(cli2, sockops);
5009 printf("TEST #1 testing 2 non-io opens (no delete)\n");
5010 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5011 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5012 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5013 if (!NT_STATUS_IS_OK(status)) {
5014 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5015 return False;
5018 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5019 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5020 FILE_OPEN_IF, 0, 0, &fnum2);
5021 if (!NT_STATUS_IS_OK(status)) {
5022 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5023 return False;
5026 status = cli_close(cli1, fnum1);
5027 if (!NT_STATUS_IS_OK(status)) {
5028 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5029 return False;
5032 status = cli_close(cli2, fnum2);
5033 if (!NT_STATUS_IS_OK(status)) {
5034 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5035 return False;
5038 printf("non-io open test #1 passed.\n");
5040 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5042 printf("TEST #2 testing 2 non-io opens (first with delete)\n");
5044 status = cli_ntcreate(cli1, fname, 0,
5045 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5046 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5047 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5048 if (!NT_STATUS_IS_OK(status)) {
5049 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5050 return False;
5053 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5054 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5055 FILE_OPEN_IF, 0, 0, &fnum2);
5056 if (!NT_STATUS_IS_OK(status)) {
5057 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5058 return False;
5061 status = cli_close(cli1, fnum1);
5062 if (!NT_STATUS_IS_OK(status)) {
5063 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5064 return False;
5067 status = cli_close(cli2, fnum2);
5068 if (!NT_STATUS_IS_OK(status)) {
5069 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5070 return False;
5073 printf("non-io open test #2 passed.\n");
5075 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5077 printf("TEST #3 testing 2 non-io opens (second with delete)\n");
5079 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5080 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5081 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5082 if (!NT_STATUS_IS_OK(status)) {
5083 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5084 return False;
5087 status = cli_ntcreate(cli2, fname, 0,
5088 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5089 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5090 FILE_OPEN_IF, 0, 0, &fnum2);
5091 if (!NT_STATUS_IS_OK(status)) {
5092 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5093 return False;
5096 status = cli_close(cli1, fnum1);
5097 if (!NT_STATUS_IS_OK(status)) {
5098 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5099 return False;
5102 status = cli_close(cli2, fnum2);
5103 if (!NT_STATUS_IS_OK(status)) {
5104 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5105 return False;
5108 printf("non-io open test #3 passed.\n");
5110 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5112 printf("TEST #4 testing 2 non-io opens (both with delete)\n");
5114 status = cli_ntcreate(cli1, fname, 0,
5115 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5116 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5117 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5118 if (!NT_STATUS_IS_OK(status)) {
5119 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5120 return False;
5123 status = cli_ntcreate(cli2, fname, 0,
5124 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5125 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5126 FILE_OPEN_IF, 0, 0, &fnum2);
5127 if (NT_STATUS_IS_OK(status)) {
5128 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5129 return False;
5132 printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5134 status = cli_close(cli1, fnum1);
5135 if (!NT_STATUS_IS_OK(status)) {
5136 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5137 return False;
5140 printf("non-io open test #4 passed.\n");
5142 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5144 printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
5146 status = cli_ntcreate(cli1, fname, 0,
5147 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5148 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5149 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5150 if (!NT_STATUS_IS_OK(status)) {
5151 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5152 return False;
5155 status = cli_ntcreate(cli2, fname, 0,
5156 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5157 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5158 FILE_OPEN_IF, 0, 0, &fnum2);
5159 if (!NT_STATUS_IS_OK(status)) {
5160 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5161 return False;
5164 status = cli_close(cli1, fnum1);
5165 if (!NT_STATUS_IS_OK(status)) {
5166 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5167 return False;
5170 status = cli_close(cli2, fnum2);
5171 if (!NT_STATUS_IS_OK(status)) {
5172 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5173 return False;
5176 printf("non-io open test #5 passed.\n");
5178 printf("TEST #6 testing 1 non-io open, one io open\n");
5180 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5182 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5183 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5184 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5185 if (!NT_STATUS_IS_OK(status)) {
5186 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5187 return False;
5190 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5191 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
5192 FILE_OPEN_IF, 0, 0, &fnum2);
5193 if (!NT_STATUS_IS_OK(status)) {
5194 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5195 return False;
5198 status = cli_close(cli1, fnum1);
5199 if (!NT_STATUS_IS_OK(status)) {
5200 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5201 return False;
5204 status = cli_close(cli2, fnum2);
5205 if (!NT_STATUS_IS_OK(status)) {
5206 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5207 return False;
5210 printf("non-io open test #6 passed.\n");
5212 printf("TEST #7 testing 1 non-io open, one io open with delete\n");
5214 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5216 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5217 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5218 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5219 if (!NT_STATUS_IS_OK(status)) {
5220 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5221 return False;
5224 status = cli_ntcreate(cli2, fname, 0,
5225 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5226 FILE_ATTRIBUTE_NORMAL,
5227 FILE_SHARE_READ|FILE_SHARE_DELETE,
5228 FILE_OPEN_IF, 0, 0, &fnum2);
5229 if (NT_STATUS_IS_OK(status)) {
5230 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5231 return False;
5234 printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5236 status = cli_close(cli1, fnum1);
5237 if (!NT_STATUS_IS_OK(status)) {
5238 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5239 return False;
5242 printf("non-io open test #7 passed.\n");
5244 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5246 printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
5247 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
5248 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5249 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5250 if (!NT_STATUS_IS_OK(status)) {
5251 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
5252 correct = false;
5253 goto out;
5256 /* Write to ensure we have to update the file time. */
5257 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5258 NULL);
5259 if (!NT_STATUS_IS_OK(status)) {
5260 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
5261 correct = false;
5262 goto out;
5265 status = cli_close(cli1, fnum1);
5266 if (!NT_STATUS_IS_OK(status)) {
5267 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
5268 correct = false;
5271 out:
5273 if (!torture_close_connection(cli1)) {
5274 correct = False;
5276 if (!torture_close_connection(cli2)) {
5277 correct = False;
5280 return correct;
5283 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
5285 uint16 major, minor;
5286 uint32 caplow, caphigh;
5287 NTSTATUS status;
5289 if (!SERVER_HAS_UNIX_CIFS(cli)) {
5290 printf("Server doesn't support UNIX CIFS extensions.\n");
5291 return NT_STATUS_NOT_SUPPORTED;
5294 status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
5295 &caphigh);
5296 if (!NT_STATUS_IS_OK(status)) {
5297 printf("Server didn't return UNIX CIFS extensions: %s\n",
5298 nt_errstr(status));
5299 return status;
5302 status = cli_set_unix_extensions_capabilities(cli, major, minor,
5303 caplow, caphigh);
5304 if (!NT_STATUS_IS_OK(status)) {
5305 printf("Server doesn't support setting UNIX CIFS extensions: "
5306 "%s.\n", nt_errstr(status));
5307 return status;
5310 return NT_STATUS_OK;
5314 Test POSIX open /mkdir calls.
5316 static bool run_simple_posix_open_test(int dummy)
5318 static struct cli_state *cli1;
5319 const char *fname = "posix:file";
5320 const char *hname = "posix:hlink";
5321 const char *sname = "posix:symlink";
5322 const char *dname = "posix:dir";
5323 char buf[10];
5324 char namebuf[11];
5325 uint16_t fnum1 = (uint16_t)-1;
5326 SMB_STRUCT_STAT sbuf;
5327 bool correct = false;
5328 NTSTATUS status;
5329 size_t nread;
5331 printf("Starting simple POSIX open test\n");
5333 if (!torture_open_connection(&cli1, 0)) {
5334 return false;
5337 cli_sockopt(cli1, sockops);
5339 status = torture_setup_unix_extensions(cli1);
5340 if (!NT_STATUS_IS_OK(status)) {
5341 return false;
5344 cli_setatr(cli1, fname, 0, 0);
5345 cli_posix_unlink(cli1, fname);
5346 cli_setatr(cli1, dname, 0, 0);
5347 cli_posix_rmdir(cli1, dname);
5348 cli_setatr(cli1, hname, 0, 0);
5349 cli_posix_unlink(cli1, hname);
5350 cli_setatr(cli1, sname, 0, 0);
5351 cli_posix_unlink(cli1, sname);
5353 /* Create a directory. */
5354 status = cli_posix_mkdir(cli1, dname, 0777);
5355 if (!NT_STATUS_IS_OK(status)) {
5356 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
5357 goto out;
5360 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5361 0600, &fnum1);
5362 if (!NT_STATUS_IS_OK(status)) {
5363 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5364 goto out;
5367 /* Test ftruncate - set file size. */
5368 status = cli_ftruncate(cli1, fnum1, 1000);
5369 if (!NT_STATUS_IS_OK(status)) {
5370 printf("ftruncate failed (%s)\n", nt_errstr(status));
5371 goto out;
5374 /* Ensure st_size == 1000 */
5375 status = cli_posix_stat(cli1, fname, &sbuf);
5376 if (!NT_STATUS_IS_OK(status)) {
5377 printf("stat failed (%s)\n", nt_errstr(status));
5378 goto out;
5381 if (sbuf.st_ex_size != 1000) {
5382 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5383 goto out;
5386 /* Test ftruncate - set file size back to zero. */
5387 status = cli_ftruncate(cli1, fnum1, 0);
5388 if (!NT_STATUS_IS_OK(status)) {
5389 printf("ftruncate failed (%s)\n", nt_errstr(status));
5390 goto out;
5393 status = cli_close(cli1, fnum1);
5394 if (!NT_STATUS_IS_OK(status)) {
5395 printf("close failed (%s)\n", nt_errstr(status));
5396 goto out;
5399 /* Now open the file again for read only. */
5400 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5401 if (!NT_STATUS_IS_OK(status)) {
5402 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
5403 goto out;
5406 /* Now unlink while open. */
5407 status = cli_posix_unlink(cli1, fname);
5408 if (!NT_STATUS_IS_OK(status)) {
5409 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5410 goto out;
5413 status = cli_close(cli1, fnum1);
5414 if (!NT_STATUS_IS_OK(status)) {
5415 printf("close(2) failed (%s)\n", nt_errstr(status));
5416 goto out;
5419 /* Ensure the file has gone. */
5420 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5421 if (NT_STATUS_IS_OK(status)) {
5422 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
5423 goto out;
5426 /* Create again to test open with O_TRUNC. */
5427 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
5428 if (!NT_STATUS_IS_OK(status)) {
5429 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5430 goto out;
5433 /* Test ftruncate - set file size. */
5434 status = cli_ftruncate(cli1, fnum1, 1000);
5435 if (!NT_STATUS_IS_OK(status)) {
5436 printf("ftruncate failed (%s)\n", nt_errstr(status));
5437 goto out;
5440 /* Ensure st_size == 1000 */
5441 status = cli_posix_stat(cli1, fname, &sbuf);
5442 if (!NT_STATUS_IS_OK(status)) {
5443 printf("stat failed (%s)\n", nt_errstr(status));
5444 goto out;
5447 if (sbuf.st_ex_size != 1000) {
5448 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5449 goto out;
5452 status = cli_close(cli1, fnum1);
5453 if (!NT_STATUS_IS_OK(status)) {
5454 printf("close(2) failed (%s)\n", nt_errstr(status));
5455 goto out;
5458 /* Re-open with O_TRUNC. */
5459 status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
5460 if (!NT_STATUS_IS_OK(status)) {
5461 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5462 goto out;
5465 /* Ensure st_size == 0 */
5466 status = cli_posix_stat(cli1, fname, &sbuf);
5467 if (!NT_STATUS_IS_OK(status)) {
5468 printf("stat failed (%s)\n", nt_errstr(status));
5469 goto out;
5472 if (sbuf.st_ex_size != 0) {
5473 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
5474 goto out;
5477 status = cli_close(cli1, fnum1);
5478 if (!NT_STATUS_IS_OK(status)) {
5479 printf("close failed (%s)\n", nt_errstr(status));
5480 goto out;
5483 status = cli_posix_unlink(cli1, fname);
5484 if (!NT_STATUS_IS_OK(status)) {
5485 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5486 goto out;
5489 status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
5490 if (!NT_STATUS_IS_OK(status)) {
5491 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
5492 dname, nt_errstr(status));
5493 goto out;
5496 cli_close(cli1, fnum1);
5498 /* What happens when we try and POSIX open a directory for write ? */
5499 status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
5500 if (NT_STATUS_IS_OK(status)) {
5501 printf("POSIX open of directory %s succeeded, should have failed.\n", fname);
5502 goto out;
5503 } else {
5504 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
5505 NT_STATUS_FILE_IS_A_DIRECTORY)) {
5506 goto out;
5510 /* Create the file. */
5511 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5512 0600, &fnum1);
5513 if (!NT_STATUS_IS_OK(status)) {
5514 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5515 goto out;
5518 /* Write some data into it. */
5519 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5520 NULL);
5521 if (!NT_STATUS_IS_OK(status)) {
5522 printf("cli_write failed: %s\n", nt_errstr(status));
5523 goto out;
5526 cli_close(cli1, fnum1);
5528 /* Now create a hardlink. */
5529 status = cli_posix_hardlink(cli1, fname, hname);
5530 if (!NT_STATUS_IS_OK(status)) {
5531 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
5532 goto out;
5535 /* Now create a symlink. */
5536 status = cli_posix_symlink(cli1, fname, sname);
5537 if (!NT_STATUS_IS_OK(status)) {
5538 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
5539 goto out;
5542 /* Open the hardlink for read. */
5543 status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
5544 if (!NT_STATUS_IS_OK(status)) {
5545 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
5546 goto out;
5549 status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
5550 if (!NT_STATUS_IS_OK(status)) {
5551 printf("POSIX read of %s failed (%s)\n", hname,
5552 nt_errstr(status));
5553 goto out;
5554 } else if (nread != 10) {
5555 printf("POSIX read of %s failed. Received %ld, expected %d\n",
5556 hname, (unsigned long)nread, 10);
5557 goto out;
5560 if (memcmp(buf, "TEST DATA\n", 10)) {
5561 printf("invalid data read from hardlink\n");
5562 goto out;
5565 /* Do a POSIX lock/unlock. */
5566 status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
5567 if (!NT_STATUS_IS_OK(status)) {
5568 printf("POSIX lock failed %s\n", nt_errstr(status));
5569 goto out;
5572 /* Punch a hole in the locked area. */
5573 status = cli_posix_unlock(cli1, fnum1, 10, 80);
5574 if (!NT_STATUS_IS_OK(status)) {
5575 printf("POSIX unlock failed %s\n", nt_errstr(status));
5576 goto out;
5579 cli_close(cli1, fnum1);
5581 /* Open the symlink for read - this should fail. A POSIX
5582 client should not be doing opens on a symlink. */
5583 status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
5584 if (NT_STATUS_IS_OK(status)) {
5585 printf("POSIX open of %s succeeded (should have failed)\n", sname);
5586 goto out;
5587 } else {
5588 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
5589 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
5590 printf("POSIX open of %s should have failed "
5591 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
5592 "failed with %s instead.\n",
5593 sname, nt_errstr(status));
5594 goto out;
5598 status = cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf));
5599 if (!NT_STATUS_IS_OK(status)) {
5600 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
5601 goto out;
5604 if (strcmp(namebuf, fname) != 0) {
5605 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
5606 sname, fname, namebuf);
5607 goto out;
5610 status = cli_posix_rmdir(cli1, dname);
5611 if (!NT_STATUS_IS_OK(status)) {
5612 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
5613 goto out;
5616 printf("Simple POSIX open test passed\n");
5617 correct = true;
5619 out:
5621 if (fnum1 != (uint16_t)-1) {
5622 cli_close(cli1, fnum1);
5623 fnum1 = (uint16_t)-1;
5626 cli_setatr(cli1, sname, 0, 0);
5627 cli_posix_unlink(cli1, sname);
5628 cli_setatr(cli1, hname, 0, 0);
5629 cli_posix_unlink(cli1, hname);
5630 cli_setatr(cli1, fname, 0, 0);
5631 cli_posix_unlink(cli1, fname);
5632 cli_setatr(cli1, dname, 0, 0);
5633 cli_posix_rmdir(cli1, dname);
5635 if (!torture_close_connection(cli1)) {
5636 correct = false;
5639 return correct;
5643 static uint32 open_attrs_table[] = {
5644 FILE_ATTRIBUTE_NORMAL,
5645 FILE_ATTRIBUTE_ARCHIVE,
5646 FILE_ATTRIBUTE_READONLY,
5647 FILE_ATTRIBUTE_HIDDEN,
5648 FILE_ATTRIBUTE_SYSTEM,
5650 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
5651 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
5652 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
5653 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5654 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5655 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5657 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5658 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5659 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5660 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
5663 struct trunc_open_results {
5664 unsigned int num;
5665 uint32 init_attr;
5666 uint32 trunc_attr;
5667 uint32 result_attr;
5670 static struct trunc_open_results attr_results[] = {
5671 { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5672 { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5673 { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5674 { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5675 { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5676 { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5677 { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5678 { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5679 { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5680 { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5681 { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5682 { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
5683 { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5684 { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5685 { 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 },
5686 { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5687 { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5688 { 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 },
5689 { 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 },
5690 { 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 },
5691 { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5692 { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5693 { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5694 { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5695 { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5696 { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
5699 static bool run_openattrtest(int dummy)
5701 static struct cli_state *cli1;
5702 const char *fname = "\\openattr.file";
5703 uint16_t fnum1;
5704 bool correct = True;
5705 uint16 attr;
5706 unsigned int i, j, k, l;
5707 NTSTATUS status;
5709 printf("starting open attr test\n");
5711 if (!torture_open_connection(&cli1, 0)) {
5712 return False;
5715 cli_sockopt(cli1, sockops);
5717 for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32); i++) {
5718 cli_setatr(cli1, fname, 0, 0);
5719 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5721 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
5722 open_attrs_table[i], FILE_SHARE_NONE,
5723 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5724 if (!NT_STATUS_IS_OK(status)) {
5725 printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5726 return False;
5729 status = cli_close(cli1, fnum1);
5730 if (!NT_STATUS_IS_OK(status)) {
5731 printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5732 return False;
5735 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32); j++) {
5736 status = cli_ntcreate(cli1, fname, 0,
5737 FILE_READ_DATA|FILE_WRITE_DATA,
5738 open_attrs_table[j],
5739 FILE_SHARE_NONE, FILE_OVERWRITE,
5740 0, 0, &fnum1);
5741 if (!NT_STATUS_IS_OK(status)) {
5742 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5743 if (attr_results[l].num == k) {
5744 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
5745 k, open_attrs_table[i],
5746 open_attrs_table[j],
5747 fname, NT_STATUS_V(status), nt_errstr(status));
5748 correct = False;
5752 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5753 printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
5754 k, open_attrs_table[i], open_attrs_table[j],
5755 nt_errstr(status));
5756 correct = False;
5758 #if 0
5759 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
5760 #endif
5761 k++;
5762 continue;
5765 status = cli_close(cli1, fnum1);
5766 if (!NT_STATUS_IS_OK(status)) {
5767 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
5768 return False;
5771 status = cli_getatr(cli1, fname, &attr, NULL, NULL);
5772 if (!NT_STATUS_IS_OK(status)) {
5773 printf("getatr(2) failed (%s)\n", nt_errstr(status));
5774 return False;
5777 #if 0
5778 printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
5779 k, open_attrs_table[i], open_attrs_table[j], attr );
5780 #endif
5782 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5783 if (attr_results[l].num == k) {
5784 if (attr != attr_results[l].result_attr ||
5785 open_attrs_table[i] != attr_results[l].init_attr ||
5786 open_attrs_table[j] != attr_results[l].trunc_attr) {
5787 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
5788 open_attrs_table[i],
5789 open_attrs_table[j],
5790 (unsigned int)attr,
5791 attr_results[l].result_attr);
5792 correct = False;
5794 break;
5797 k++;
5801 cli_setatr(cli1, fname, 0, 0);
5802 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5804 printf("open attr test %s.\n", correct ? "passed" : "failed");
5806 if (!torture_close_connection(cli1)) {
5807 correct = False;
5809 return correct;
5812 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
5813 const char *name, void *state)
5815 int *matched = (int *)state;
5816 if (matched != NULL) {
5817 *matched += 1;
5819 return NT_STATUS_OK;
5823 test directory listing speed
5825 static bool run_dirtest(int dummy)
5827 int i;
5828 static struct cli_state *cli;
5829 uint16_t fnum;
5830 struct timeval core_start;
5831 bool correct = True;
5832 int matched;
5834 printf("starting directory test\n");
5836 if (!torture_open_connection(&cli, 0)) {
5837 return False;
5840 cli_sockopt(cli, sockops);
5842 srandom(0);
5843 for (i=0;i<torture_numops;i++) {
5844 fstring fname;
5845 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5846 if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
5847 fprintf(stderr,"Failed to open %s\n", fname);
5848 return False;
5850 cli_close(cli, fnum);
5853 core_start = timeval_current();
5855 matched = 0;
5856 cli_list(cli, "a*.*", 0, list_fn, &matched);
5857 printf("Matched %d\n", matched);
5859 matched = 0;
5860 cli_list(cli, "b*.*", 0, list_fn, &matched);
5861 printf("Matched %d\n", matched);
5863 matched = 0;
5864 cli_list(cli, "xyzabc", 0, list_fn, &matched);
5865 printf("Matched %d\n", matched);
5867 printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
5869 srandom(0);
5870 for (i=0;i<torture_numops;i++) {
5871 fstring fname;
5872 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5873 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5876 if (!torture_close_connection(cli)) {
5877 correct = False;
5880 printf("finished dirtest\n");
5882 return correct;
5885 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
5886 void *state)
5888 struct cli_state *pcli = (struct cli_state *)state;
5889 fstring fname;
5890 slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
5892 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
5893 return NT_STATUS_OK;
5895 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
5896 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
5897 printf("del_fn: failed to rmdir %s\n,", fname );
5898 } else {
5899 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
5900 printf("del_fn: failed to unlink %s\n,", fname );
5902 return NT_STATUS_OK;
5907 sees what IOCTLs are supported
5909 bool torture_ioctl_test(int dummy)
5911 static struct cli_state *cli;
5912 uint16_t device, function;
5913 uint16_t fnum;
5914 const char *fname = "\\ioctl.dat";
5915 DATA_BLOB blob;
5916 NTSTATUS status;
5918 if (!torture_open_connection(&cli, 0)) {
5919 return False;
5922 printf("starting ioctl test\n");
5924 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5926 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5927 if (!NT_STATUS_IS_OK(status)) {
5928 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5929 return False;
5932 status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
5933 printf("ioctl device info: %s\n", nt_errstr(status));
5935 status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
5936 printf("ioctl job info: %s\n", nt_errstr(status));
5938 for (device=0;device<0x100;device++) {
5939 printf("ioctl test with device = 0x%x\n", device);
5940 for (function=0;function<0x100;function++) {
5941 uint32 code = (device<<16) | function;
5943 status = cli_raw_ioctl(cli, fnum, code, &blob);
5945 if (NT_STATUS_IS_OK(status)) {
5946 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
5947 (int)blob.length);
5948 data_blob_free(&blob);
5953 if (!torture_close_connection(cli)) {
5954 return False;
5957 return True;
5962 tries varients of chkpath
5964 bool torture_chkpath_test(int dummy)
5966 static struct cli_state *cli;
5967 uint16_t fnum;
5968 bool ret;
5969 NTSTATUS status;
5971 if (!torture_open_connection(&cli, 0)) {
5972 return False;
5975 printf("starting chkpath test\n");
5977 /* cleanup from an old run */
5978 cli_rmdir(cli, "\\chkpath.dir\\dir2");
5979 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5980 cli_rmdir(cli, "\\chkpath.dir");
5982 status = cli_mkdir(cli, "\\chkpath.dir");
5983 if (!NT_STATUS_IS_OK(status)) {
5984 printf("mkdir1 failed : %s\n", nt_errstr(status));
5985 return False;
5988 status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
5989 if (!NT_STATUS_IS_OK(status)) {
5990 printf("mkdir2 failed : %s\n", nt_errstr(status));
5991 return False;
5994 status = cli_open(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
5995 DENY_NONE, &fnum);
5996 if (!NT_STATUS_IS_OK(status)) {
5997 printf("open1 failed (%s)\n", nt_errstr(status));
5998 return False;
6000 cli_close(cli, fnum);
6002 status = cli_chkpath(cli, "\\chkpath.dir");
6003 if (!NT_STATUS_IS_OK(status)) {
6004 printf("chkpath1 failed: %s\n", nt_errstr(status));
6005 ret = False;
6008 status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
6009 if (!NT_STATUS_IS_OK(status)) {
6010 printf("chkpath2 failed: %s\n", nt_errstr(status));
6011 ret = False;
6014 status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
6015 if (!NT_STATUS_IS_OK(status)) {
6016 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
6017 NT_STATUS_NOT_A_DIRECTORY);
6018 } else {
6019 printf("* chkpath on a file should fail\n");
6020 ret = False;
6023 status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
6024 if (!NT_STATUS_IS_OK(status)) {
6025 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
6026 NT_STATUS_OBJECT_NAME_NOT_FOUND);
6027 } else {
6028 printf("* chkpath on a non existant file should fail\n");
6029 ret = False;
6032 status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
6033 if (!NT_STATUS_IS_OK(status)) {
6034 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
6035 NT_STATUS_OBJECT_PATH_NOT_FOUND);
6036 } else {
6037 printf("* chkpath on a non existent component should fail\n");
6038 ret = False;
6041 cli_rmdir(cli, "\\chkpath.dir\\dir2");
6042 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6043 cli_rmdir(cli, "\\chkpath.dir");
6045 if (!torture_close_connection(cli)) {
6046 return False;
6049 return ret;
6052 static bool run_eatest(int dummy)
6054 static struct cli_state *cli;
6055 const char *fname = "\\eatest.txt";
6056 bool correct = True;
6057 uint16_t fnum;
6058 int i;
6059 size_t num_eas;
6060 struct ea_struct *ea_list = NULL;
6061 TALLOC_CTX *mem_ctx = talloc_init("eatest");
6062 NTSTATUS status;
6064 printf("starting eatest\n");
6066 if (!torture_open_connection(&cli, 0)) {
6067 talloc_destroy(mem_ctx);
6068 return False;
6071 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6073 status = cli_ntcreate(cli, fname, 0,
6074 FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6075 FILE_SHARE_NONE, FILE_OVERWRITE_IF,
6076 0x4044, 0, &fnum);
6077 if (!NT_STATUS_IS_OK(status)) {
6078 printf("open failed - %s\n", nt_errstr(status));
6079 talloc_destroy(mem_ctx);
6080 return False;
6083 for (i = 0; i < 10; i++) {
6084 fstring ea_name, ea_val;
6086 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
6087 memset(ea_val, (char)i+1, i+1);
6088 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
6089 if (!NT_STATUS_IS_OK(status)) {
6090 printf("ea_set of name %s failed - %s\n", ea_name,
6091 nt_errstr(status));
6092 talloc_destroy(mem_ctx);
6093 return False;
6097 cli_close(cli, fnum);
6098 for (i = 0; i < 10; i++) {
6099 fstring ea_name, ea_val;
6101 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
6102 memset(ea_val, (char)i+1, i+1);
6103 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
6104 if (!NT_STATUS_IS_OK(status)) {
6105 printf("ea_set of name %s failed - %s\n", ea_name,
6106 nt_errstr(status));
6107 talloc_destroy(mem_ctx);
6108 return False;
6112 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6113 if (!NT_STATUS_IS_OK(status)) {
6114 printf("ea_get list failed - %s\n", nt_errstr(status));
6115 correct = False;
6118 printf("num_eas = %d\n", (int)num_eas);
6120 if (num_eas != 20) {
6121 printf("Should be 20 EA's stored... failing.\n");
6122 correct = False;
6125 for (i = 0; i < num_eas; i++) {
6126 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6127 dump_data(0, ea_list[i].value.data,
6128 ea_list[i].value.length);
6131 /* Setting EA's to zero length deletes them. Test this */
6132 printf("Now deleting all EA's - case indepenent....\n");
6134 #if 1
6135 cli_set_ea_path(cli, fname, "", "", 0);
6136 #else
6137 for (i = 0; i < 20; i++) {
6138 fstring ea_name;
6139 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
6140 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
6141 if (!NT_STATUS_IS_OK(status)) {
6142 printf("ea_set of name %s failed - %s\n", ea_name,
6143 nt_errstr(status));
6144 talloc_destroy(mem_ctx);
6145 return False;
6148 #endif
6150 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6151 if (!NT_STATUS_IS_OK(status)) {
6152 printf("ea_get list failed - %s\n", nt_errstr(status));
6153 correct = False;
6156 printf("num_eas = %d\n", (int)num_eas);
6157 for (i = 0; i < num_eas; i++) {
6158 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6159 dump_data(0, ea_list[i].value.data,
6160 ea_list[i].value.length);
6163 if (num_eas != 0) {
6164 printf("deleting EA's failed.\n");
6165 correct = False;
6168 /* Try and delete a non existant EA. */
6169 status = cli_set_ea_path(cli, fname, "foo", "", 0);
6170 if (!NT_STATUS_IS_OK(status)) {
6171 printf("deleting non-existant EA 'foo' should succeed. %s\n",
6172 nt_errstr(status));
6173 correct = False;
6176 talloc_destroy(mem_ctx);
6177 if (!torture_close_connection(cli)) {
6178 correct = False;
6181 return correct;
6184 static bool run_dirtest1(int dummy)
6186 int i;
6187 static struct cli_state *cli;
6188 uint16_t fnum;
6189 int num_seen;
6190 bool correct = True;
6192 printf("starting directory test\n");
6194 if (!torture_open_connection(&cli, 0)) {
6195 return False;
6198 cli_sockopt(cli, sockops);
6200 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6201 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6202 cli_rmdir(cli, "\\LISTDIR");
6203 cli_mkdir(cli, "\\LISTDIR");
6205 /* Create 1000 files and 1000 directories. */
6206 for (i=0;i<1000;i++) {
6207 fstring fname;
6208 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
6209 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6210 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum))) {
6211 fprintf(stderr,"Failed to open %s\n", fname);
6212 return False;
6214 cli_close(cli, fnum);
6216 for (i=0;i<1000;i++) {
6217 fstring fname;
6218 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
6219 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
6220 fprintf(stderr,"Failed to open %s\n", fname);
6221 return False;
6225 /* Now ensure that doing an old list sees both files and directories. */
6226 num_seen = 0;
6227 cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6228 printf("num_seen = %d\n", num_seen );
6229 /* We should see 100 files + 1000 directories + . and .. */
6230 if (num_seen != 2002)
6231 correct = False;
6233 /* Ensure if we have the "must have" bits we only see the
6234 * relevent entries.
6236 num_seen = 0;
6237 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6238 printf("num_seen = %d\n", num_seen );
6239 if (num_seen != 1002)
6240 correct = False;
6242 num_seen = 0;
6243 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6244 printf("num_seen = %d\n", num_seen );
6245 if (num_seen != 1000)
6246 correct = False;
6248 /* Delete everything. */
6249 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6250 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6251 cli_rmdir(cli, "\\LISTDIR");
6253 #if 0
6254 printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
6255 printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
6256 printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
6257 #endif
6259 if (!torture_close_connection(cli)) {
6260 correct = False;
6263 printf("finished dirtest1\n");
6265 return correct;
6268 static bool run_error_map_extract(int dummy) {
6270 static struct cli_state *c_dos;
6271 static struct cli_state *c_nt;
6272 NTSTATUS status;
6274 uint32 error;
6276 uint32 errnum;
6277 uint8 errclass;
6279 NTSTATUS nt_status;
6281 fstring user;
6283 /* NT-Error connection */
6285 disable_spnego = true;
6286 if (!(c_nt = open_nbt_connection())) {
6287 disable_spnego = false;
6288 return False;
6290 disable_spnego = false;
6292 status = cli_negprot(c_nt, PROTOCOL_NT1);
6294 if (!NT_STATUS_IS_OK(status)) {
6295 printf("%s rejected the NT-error negprot (%s)\n", host,
6296 nt_errstr(status));
6297 cli_shutdown(c_nt);
6298 return False;
6301 status = cli_session_setup(c_nt, "", "", 0, "", 0, workgroup);
6302 if (!NT_STATUS_IS_OK(status)) {
6303 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
6304 return False;
6307 /* DOS-Error connection */
6309 disable_spnego = true;
6310 force_dos_errors = true;
6311 if (!(c_dos = open_nbt_connection())) {
6312 disable_spnego = false;
6313 force_dos_errors = false;
6314 return False;
6316 disable_spnego = false;
6317 force_dos_errors = false;
6319 status = cli_negprot(c_dos, PROTOCOL_NT1);
6320 if (!NT_STATUS_IS_OK(status)) {
6321 printf("%s rejected the DOS-error negprot (%s)\n", host,
6322 nt_errstr(status));
6323 cli_shutdown(c_dos);
6324 return False;
6327 status = cli_session_setup(c_dos, "", "", 0, "", 0, workgroup);
6328 if (!NT_STATUS_IS_OK(status)) {
6329 printf("%s rejected the DOS-error initial session setup (%s)\n",
6330 host, nt_errstr(status));
6331 return False;
6334 for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
6335 fstr_sprintf(user, "%X", error);
6337 status = cli_session_setup(c_nt, user,
6338 password, strlen(password),
6339 password, strlen(password),
6340 workgroup);
6341 if (NT_STATUS_IS_OK(status)) {
6342 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
6345 /* Case #1: 32-bit NT errors */
6346 if (cli_is_nt_error(c_nt)) {
6347 nt_status = cli_nt_error(c_nt);
6348 } else {
6349 printf("/** Dos error on NT connection! (%s) */\n",
6350 cli_errstr(c_nt));
6351 nt_status = NT_STATUS(0xc0000000);
6354 status = cli_session_setup(c_dos, user,
6355 password, strlen(password),
6356 password, strlen(password),
6357 workgroup);
6358 if (NT_STATUS_IS_OK(status)) {
6359 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
6362 /* Case #1: 32-bit NT errors */
6363 if (!cli_is_dos_error(c_dos)) {
6364 printf("/** NT error on DOS connection! (%s) */\n",
6365 cli_errstr(c_dos));
6366 errnum = errclass = 0;
6367 } else {
6368 cli_dos_error(c_dos, &errclass, &errnum);
6371 if (NT_STATUS_V(nt_status) != error) {
6372 printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
6373 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
6374 get_nt_error_c_code(talloc_tos(), nt_status));
6377 printf("\t{%s,\t%s,\t%s},\n",
6378 smb_dos_err_class(errclass),
6379 smb_dos_err_name(errclass, errnum),
6380 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
6382 return True;
6385 static bool run_sesssetup_bench(int dummy)
6387 static struct cli_state *c;
6388 const char *fname = "\\file.dat";
6389 uint16_t fnum;
6390 NTSTATUS status;
6391 int i;
6393 if (!torture_open_connection(&c, 0)) {
6394 return false;
6397 status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6398 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6399 FILE_DELETE_ON_CLOSE, 0, &fnum);
6400 if (!NT_STATUS_IS_OK(status)) {
6401 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
6402 return false;
6405 for (i=0; i<torture_numops; i++) {
6406 status = cli_session_setup(
6407 c, username,
6408 password, strlen(password),
6409 password, strlen(password),
6410 workgroup);
6411 if (!NT_STATUS_IS_OK(status)) {
6412 d_printf("(%s) cli_session_setup failed: %s\n",
6413 __location__, nt_errstr(status));
6414 return false;
6417 d_printf("\r%d ", (int)cli_state_get_uid(c));
6419 status = cli_ulogoff(c);
6420 if (!NT_STATUS_IS_OK(status)) {
6421 d_printf("(%s) cli_ulogoff failed: %s\n",
6422 __location__, nt_errstr(status));
6423 return false;
6427 return true;
6430 static bool subst_test(const char *str, const char *user, const char *domain,
6431 uid_t uid, gid_t gid, const char *expected)
6433 char *subst;
6434 bool result = true;
6436 subst = talloc_sub_specified(talloc_tos(), str, user, domain, uid, gid);
6438 if (strcmp(subst, expected) != 0) {
6439 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
6440 "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
6441 expected);
6442 result = false;
6445 TALLOC_FREE(subst);
6446 return result;
6449 static void chain1_open_completion(struct tevent_req *req)
6451 uint16_t fnum;
6452 NTSTATUS status;
6453 status = cli_open_recv(req, &fnum);
6454 TALLOC_FREE(req);
6456 d_printf("cli_open_recv returned %s: %d\n",
6457 nt_errstr(status),
6458 NT_STATUS_IS_OK(status) ? fnum : -1);
6461 static void chain1_write_completion(struct tevent_req *req)
6463 size_t written;
6464 NTSTATUS status;
6465 status = cli_write_andx_recv(req, &written);
6466 TALLOC_FREE(req);
6468 d_printf("cli_write_andx_recv returned %s: %d\n",
6469 nt_errstr(status),
6470 NT_STATUS_IS_OK(status) ? (int)written : -1);
6473 static void chain1_close_completion(struct tevent_req *req)
6475 NTSTATUS status;
6476 bool *done = (bool *)tevent_req_callback_data_void(req);
6478 status = cli_close_recv(req);
6479 *done = true;
6481 TALLOC_FREE(req);
6483 d_printf("cli_close returned %s\n", nt_errstr(status));
6486 static bool run_chain1(int dummy)
6488 struct cli_state *cli1;
6489 struct event_context *evt = event_context_init(NULL);
6490 struct tevent_req *reqs[3], *smbreqs[3];
6491 bool done = false;
6492 const char *str = "foobar";
6493 NTSTATUS status;
6495 printf("starting chain1 test\n");
6496 if (!torture_open_connection(&cli1, 0)) {
6497 return False;
6500 cli_sockopt(cli1, sockops);
6502 reqs[0] = cli_open_create(talloc_tos(), evt, cli1, "\\test",
6503 O_CREAT|O_RDWR, 0, &smbreqs[0]);
6504 if (reqs[0] == NULL) return false;
6505 tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
6508 reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
6509 (const uint8_t *)str, 0, strlen(str)+1,
6510 smbreqs, 1, &smbreqs[1]);
6511 if (reqs[1] == NULL) return false;
6512 tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
6514 reqs[2] = cli_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
6515 if (reqs[2] == NULL) return false;
6516 tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
6518 status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
6519 if (!NT_STATUS_IS_OK(status)) {
6520 return false;
6523 while (!done) {
6524 tevent_loop_once(evt);
6527 torture_close_connection(cli1);
6528 return True;
6531 static void chain2_sesssetup_completion(struct tevent_req *req)
6533 NTSTATUS status;
6534 status = cli_session_setup_guest_recv(req);
6535 d_printf("sesssetup returned %s\n", nt_errstr(status));
6538 static void chain2_tcon_completion(struct tevent_req *req)
6540 bool *done = (bool *)tevent_req_callback_data_void(req);
6541 NTSTATUS status;
6542 status = cli_tcon_andx_recv(req);
6543 d_printf("tcon_and_x returned %s\n", nt_errstr(status));
6544 *done = true;
6547 static bool run_chain2(int dummy)
6549 struct cli_state *cli1;
6550 struct event_context *evt = event_context_init(NULL);
6551 struct tevent_req *reqs[2], *smbreqs[2];
6552 bool done = false;
6553 NTSTATUS status;
6555 printf("starting chain2 test\n");
6556 status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
6557 port_to_use, Undefined, 0);
6558 if (!NT_STATUS_IS_OK(status)) {
6559 return False;
6562 cli_sockopt(cli1, sockops);
6564 reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
6565 &smbreqs[0]);
6566 if (reqs[0] == NULL) return false;
6567 tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
6569 reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
6570 "?????", NULL, 0, &smbreqs[1]);
6571 if (reqs[1] == NULL) return false;
6572 tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
6574 status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
6575 if (!NT_STATUS_IS_OK(status)) {
6576 return false;
6579 while (!done) {
6580 tevent_loop_once(evt);
6583 torture_close_connection(cli1);
6584 return True;
6588 struct torture_createdel_state {
6589 struct tevent_context *ev;
6590 struct cli_state *cli;
6593 static void torture_createdel_created(struct tevent_req *subreq);
6594 static void torture_createdel_closed(struct tevent_req *subreq);
6596 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
6597 struct tevent_context *ev,
6598 struct cli_state *cli,
6599 const char *name)
6601 struct tevent_req *req, *subreq;
6602 struct torture_createdel_state *state;
6604 req = tevent_req_create(mem_ctx, &state,
6605 struct torture_createdel_state);
6606 if (req == NULL) {
6607 return NULL;
6609 state->ev = ev;
6610 state->cli = cli;
6612 subreq = cli_ntcreate_send(
6613 state, ev, cli, name, 0,
6614 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
6615 FILE_ATTRIBUTE_NORMAL,
6616 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6617 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
6619 if (tevent_req_nomem(subreq, req)) {
6620 return tevent_req_post(req, ev);
6622 tevent_req_set_callback(subreq, torture_createdel_created, req);
6623 return req;
6626 static void torture_createdel_created(struct tevent_req *subreq)
6628 struct tevent_req *req = tevent_req_callback_data(
6629 subreq, struct tevent_req);
6630 struct torture_createdel_state *state = tevent_req_data(
6631 req, struct torture_createdel_state);
6632 NTSTATUS status;
6633 uint16_t fnum;
6635 status = cli_ntcreate_recv(subreq, &fnum);
6636 TALLOC_FREE(subreq);
6637 if (!NT_STATUS_IS_OK(status)) {
6638 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
6639 nt_errstr(status)));
6640 tevent_req_nterror(req, status);
6641 return;
6644 subreq = cli_close_send(state, state->ev, state->cli, fnum);
6645 if (tevent_req_nomem(subreq, req)) {
6646 return;
6648 tevent_req_set_callback(subreq, torture_createdel_closed, req);
6651 static void torture_createdel_closed(struct tevent_req *subreq)
6653 struct tevent_req *req = tevent_req_callback_data(
6654 subreq, struct tevent_req);
6655 NTSTATUS status;
6657 status = cli_close_recv(subreq);
6658 if (!NT_STATUS_IS_OK(status)) {
6659 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
6660 tevent_req_nterror(req, status);
6661 return;
6663 tevent_req_done(req);
6666 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
6668 return tevent_req_simple_recv_ntstatus(req);
6671 struct torture_createdels_state {
6672 struct tevent_context *ev;
6673 struct cli_state *cli;
6674 const char *base_name;
6675 int sent;
6676 int received;
6677 int num_files;
6678 struct tevent_req **reqs;
6681 static void torture_createdels_done(struct tevent_req *subreq);
6683 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
6684 struct tevent_context *ev,
6685 struct cli_state *cli,
6686 const char *base_name,
6687 int num_parallel,
6688 int num_files)
6690 struct tevent_req *req;
6691 struct torture_createdels_state *state;
6692 int i;
6694 req = tevent_req_create(mem_ctx, &state,
6695 struct torture_createdels_state);
6696 if (req == NULL) {
6697 return NULL;
6699 state->ev = ev;
6700 state->cli = cli;
6701 state->base_name = talloc_strdup(state, base_name);
6702 if (tevent_req_nomem(state->base_name, req)) {
6703 return tevent_req_post(req, ev);
6705 state->num_files = MAX(num_parallel, num_files);
6706 state->sent = 0;
6707 state->received = 0;
6709 state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
6710 if (tevent_req_nomem(state->reqs, req)) {
6711 return tevent_req_post(req, ev);
6714 for (i=0; i<num_parallel; i++) {
6715 char *name;
6717 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6718 state->sent);
6719 if (tevent_req_nomem(name, req)) {
6720 return tevent_req_post(req, ev);
6722 state->reqs[i] = torture_createdel_send(
6723 state->reqs, state->ev, state->cli, name);
6724 if (tevent_req_nomem(state->reqs[i], req)) {
6725 return tevent_req_post(req, ev);
6727 name = talloc_move(state->reqs[i], &name);
6728 tevent_req_set_callback(state->reqs[i],
6729 torture_createdels_done, req);
6730 state->sent += 1;
6732 return req;
6735 static void torture_createdels_done(struct tevent_req *subreq)
6737 struct tevent_req *req = tevent_req_callback_data(
6738 subreq, struct tevent_req);
6739 struct torture_createdels_state *state = tevent_req_data(
6740 req, struct torture_createdels_state);
6741 size_t num_parallel = talloc_array_length(state->reqs);
6742 NTSTATUS status;
6743 char *name;
6744 int i;
6746 status = torture_createdel_recv(subreq);
6747 if (!NT_STATUS_IS_OK(status)){
6748 DEBUG(10, ("torture_createdel_recv returned %s\n",
6749 nt_errstr(status)));
6750 TALLOC_FREE(subreq);
6751 tevent_req_nterror(req, status);
6752 return;
6755 for (i=0; i<num_parallel; i++) {
6756 if (subreq == state->reqs[i]) {
6757 break;
6760 if (i == num_parallel) {
6761 DEBUG(10, ("received something we did not send\n"));
6762 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
6763 return;
6765 TALLOC_FREE(state->reqs[i]);
6767 if (state->sent >= state->num_files) {
6768 tevent_req_done(req);
6769 return;
6772 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6773 state->sent);
6774 if (tevent_req_nomem(name, req)) {
6775 return;
6777 state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
6778 state->cli, name);
6779 if (tevent_req_nomem(state->reqs[i], req)) {
6780 return;
6782 name = talloc_move(state->reqs[i], &name);
6783 tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
6784 state->sent += 1;
6787 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
6789 return tevent_req_simple_recv_ntstatus(req);
6792 struct swallow_notify_state {
6793 struct tevent_context *ev;
6794 struct cli_state *cli;
6795 uint16_t fnum;
6796 uint32_t completion_filter;
6797 bool recursive;
6798 bool (*fn)(uint32_t action, const char *name, void *priv);
6799 void *priv;
6802 static void swallow_notify_done(struct tevent_req *subreq);
6804 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
6805 struct tevent_context *ev,
6806 struct cli_state *cli,
6807 uint16_t fnum,
6808 uint32_t completion_filter,
6809 bool recursive,
6810 bool (*fn)(uint32_t action,
6811 const char *name,
6812 void *priv),
6813 void *priv)
6815 struct tevent_req *req, *subreq;
6816 struct swallow_notify_state *state;
6818 req = tevent_req_create(mem_ctx, &state,
6819 struct swallow_notify_state);
6820 if (req == NULL) {
6821 return NULL;
6823 state->ev = ev;
6824 state->cli = cli;
6825 state->fnum = fnum;
6826 state->completion_filter = completion_filter;
6827 state->recursive = recursive;
6828 state->fn = fn;
6829 state->priv = priv;
6831 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6832 0xffff, state->completion_filter,
6833 state->recursive);
6834 if (tevent_req_nomem(subreq, req)) {
6835 return tevent_req_post(req, ev);
6837 tevent_req_set_callback(subreq, swallow_notify_done, req);
6838 return req;
6841 static void swallow_notify_done(struct tevent_req *subreq)
6843 struct tevent_req *req = tevent_req_callback_data(
6844 subreq, struct tevent_req);
6845 struct swallow_notify_state *state = tevent_req_data(
6846 req, struct swallow_notify_state);
6847 NTSTATUS status;
6848 uint32_t i, num_changes;
6849 struct notify_change *changes;
6851 status = cli_notify_recv(subreq, state, &num_changes, &changes);
6852 TALLOC_FREE(subreq);
6853 if (!NT_STATUS_IS_OK(status)) {
6854 DEBUG(10, ("cli_notify_recv returned %s\n",
6855 nt_errstr(status)));
6856 tevent_req_nterror(req, status);
6857 return;
6860 for (i=0; i<num_changes; i++) {
6861 state->fn(changes[i].action, changes[i].name, state->priv);
6863 TALLOC_FREE(changes);
6865 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6866 0xffff, state->completion_filter,
6867 state->recursive);
6868 if (tevent_req_nomem(subreq, req)) {
6869 return;
6871 tevent_req_set_callback(subreq, swallow_notify_done, req);
6874 static bool print_notifies(uint32_t action, const char *name, void *priv)
6876 if (DEBUGLEVEL > 5) {
6877 d_printf("%d %s\n", (int)action, name);
6879 return true;
6882 static void notify_bench_done(struct tevent_req *req)
6884 int *num_finished = (int *)tevent_req_callback_data_void(req);
6885 *num_finished += 1;
6888 static bool run_notify_bench(int dummy)
6890 const char *dname = "\\notify-bench";
6891 struct tevent_context *ev;
6892 NTSTATUS status;
6893 uint16_t dnum;
6894 struct tevent_req *req1;
6895 struct tevent_req *req2 = NULL;
6896 int i, num_unc_names;
6897 int num_finished = 0;
6899 printf("starting notify-bench test\n");
6901 if (use_multishare_conn) {
6902 char **unc_list;
6903 unc_list = file_lines_load(multishare_conn_fname,
6904 &num_unc_names, 0, NULL);
6905 if (!unc_list || num_unc_names <= 0) {
6906 d_printf("Failed to load unc names list from '%s'\n",
6907 multishare_conn_fname);
6908 return false;
6910 TALLOC_FREE(unc_list);
6911 } else {
6912 num_unc_names = 1;
6915 ev = tevent_context_init(talloc_tos());
6916 if (ev == NULL) {
6917 d_printf("tevent_context_init failed\n");
6918 return false;
6921 for (i=0; i<num_unc_names; i++) {
6922 struct cli_state *cli;
6923 char *base_fname;
6925 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
6926 dname, i);
6927 if (base_fname == NULL) {
6928 return false;
6931 if (!torture_open_connection(&cli, i)) {
6932 return false;
6935 status = cli_ntcreate(cli, dname, 0,
6936 MAXIMUM_ALLOWED_ACCESS,
6937 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
6938 FILE_SHARE_DELETE,
6939 FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
6940 &dnum);
6942 if (!NT_STATUS_IS_OK(status)) {
6943 d_printf("Could not create %s: %s\n", dname,
6944 nt_errstr(status));
6945 return false;
6948 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
6949 FILE_NOTIFY_CHANGE_FILE_NAME |
6950 FILE_NOTIFY_CHANGE_DIR_NAME |
6951 FILE_NOTIFY_CHANGE_ATTRIBUTES |
6952 FILE_NOTIFY_CHANGE_LAST_WRITE,
6953 false, print_notifies, NULL);
6954 if (req1 == NULL) {
6955 d_printf("Could not create notify request\n");
6956 return false;
6959 req2 = torture_createdels_send(talloc_tos(), ev, cli,
6960 base_fname, 10, torture_numops);
6961 if (req2 == NULL) {
6962 d_printf("Could not create createdels request\n");
6963 return false;
6965 TALLOC_FREE(base_fname);
6967 tevent_req_set_callback(req2, notify_bench_done,
6968 &num_finished);
6971 while (num_finished < num_unc_names) {
6972 int ret;
6973 ret = tevent_loop_once(ev);
6974 if (ret != 0) {
6975 d_printf("tevent_loop_once failed\n");
6976 return false;
6980 if (!tevent_req_poll(req2, ev)) {
6981 d_printf("tevent_req_poll failed\n");
6984 status = torture_createdels_recv(req2);
6985 d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
6987 return true;
6990 static bool run_mangle1(int dummy)
6992 struct cli_state *cli;
6993 const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
6994 uint16_t fnum;
6995 fstring alt_name;
6996 NTSTATUS status;
6997 time_t change_time, access_time, write_time;
6998 SMB_OFF_T size;
6999 uint16_t mode;
7001 printf("starting mangle1 test\n");
7002 if (!torture_open_connection(&cli, 0)) {
7003 return False;
7006 cli_sockopt(cli, sockops);
7008 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
7009 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
7010 0, 0, &fnum);
7011 if (!NT_STATUS_IS_OK(status)) {
7012 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
7013 return false;
7015 cli_close(cli, fnum);
7017 status = cli_qpathinfo_alt_name(cli, fname, alt_name);
7018 if (!NT_STATUS_IS_OK(status)) {
7019 d_printf("cli_qpathinfo_alt_name failed: %s\n",
7020 nt_errstr(status));
7021 return false;
7023 d_printf("alt_name: %s\n", alt_name);
7025 status = cli_open(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
7026 if (!NT_STATUS_IS_OK(status)) {
7027 d_printf("cli_open(%s) failed: %s\n", alt_name,
7028 nt_errstr(status));
7029 return false;
7031 cli_close(cli, fnum);
7033 status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
7034 &write_time, &size, &mode);
7035 if (!NT_STATUS_IS_OK(status)) {
7036 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
7037 nt_errstr(status));
7038 return false;
7041 return true;
7044 static size_t null_source(uint8_t *buf, size_t n, void *priv)
7046 size_t *to_pull = (size_t *)priv;
7047 size_t thistime = *to_pull;
7049 thistime = MIN(thistime, n);
7050 if (thistime == 0) {
7051 return 0;
7054 memset(buf, 0, thistime);
7055 *to_pull -= thistime;
7056 return thistime;
7059 static bool run_windows_write(int dummy)
7061 struct cli_state *cli1;
7062 uint16_t fnum;
7063 int i;
7064 bool ret = false;
7065 const char *fname = "\\writetest.txt";
7066 struct timeval start_time;
7067 double seconds;
7068 double kbytes;
7069 NTSTATUS status;
7071 printf("starting windows_write test\n");
7072 if (!torture_open_connection(&cli1, 0)) {
7073 return False;
7076 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
7077 if (!NT_STATUS_IS_OK(status)) {
7078 printf("open failed (%s)\n", nt_errstr(status));
7079 return False;
7082 cli_sockopt(cli1, sockops);
7084 start_time = timeval_current();
7086 for (i=0; i<torture_numops; i++) {
7087 uint8_t c = 0;
7088 off_t start = i * torture_blocksize;
7089 size_t to_pull = torture_blocksize - 1;
7091 status = cli_writeall(cli1, fnum, 0, &c,
7092 start + torture_blocksize - 1, 1, NULL);
7093 if (!NT_STATUS_IS_OK(status)) {
7094 printf("cli_write failed: %s\n", nt_errstr(status));
7095 goto fail;
7098 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
7099 null_source, &to_pull);
7100 if (!NT_STATUS_IS_OK(status)) {
7101 printf("cli_push returned: %s\n", nt_errstr(status));
7102 goto fail;
7106 seconds = timeval_elapsed(&start_time);
7107 kbytes = (double)torture_blocksize * torture_numops;
7108 kbytes /= 1024;
7110 printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
7111 (double)seconds, (int)(kbytes/seconds));
7113 ret = true;
7114 fail:
7115 cli_close(cli1, fnum);
7116 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7117 torture_close_connection(cli1);
7118 return ret;
7121 static bool run_cli_echo(int dummy)
7123 struct cli_state *cli;
7124 NTSTATUS status;
7126 printf("starting cli_echo test\n");
7127 if (!torture_open_connection(&cli, 0)) {
7128 return false;
7130 cli_sockopt(cli, sockops);
7132 status = cli_echo(cli, 5, data_blob_const("hello", 5));
7134 d_printf("cli_echo returned %s\n", nt_errstr(status));
7136 torture_close_connection(cli);
7137 return NT_STATUS_IS_OK(status);
7140 static bool run_uid_regression_test(int dummy)
7142 static struct cli_state *cli;
7143 int16_t old_vuid;
7144 int16_t old_cnum;
7145 bool correct = True;
7146 NTSTATUS status;
7148 printf("starting uid regression test\n");
7150 if (!torture_open_connection(&cli, 0)) {
7151 return False;
7154 cli_sockopt(cli, sockops);
7156 /* Ok - now save then logoff our current user. */
7157 old_vuid = cli_state_get_uid(cli);
7159 status = cli_ulogoff(cli);
7160 if (!NT_STATUS_IS_OK(status)) {
7161 d_printf("(%s) cli_ulogoff failed: %s\n",
7162 __location__, nt_errstr(status));
7163 correct = false;
7164 goto out;
7167 cli_state_set_uid(cli, old_vuid);
7169 /* Try an operation. */
7170 status = cli_mkdir(cli, "\\uid_reg_test");
7171 if (NT_STATUS_IS_OK(status)) {
7172 d_printf("(%s) cli_mkdir succeeded\n",
7173 __location__);
7174 correct = false;
7175 goto out;
7176 } else {
7177 /* Should be bad uid. */
7178 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
7179 NT_STATUS_USER_SESSION_DELETED)) {
7180 correct = false;
7181 goto out;
7185 old_cnum = cli_state_get_tid(cli);
7187 /* Now try a SMBtdis with the invald vuid set to zero. */
7188 cli_state_set_uid(cli, 0);
7190 /* This should succeed. */
7191 status = cli_tdis(cli);
7193 if (NT_STATUS_IS_OK(status)) {
7194 d_printf("First tdis with invalid vuid should succeed.\n");
7195 } else {
7196 d_printf("First tdis failed (%s)\n", nt_errstr(status));
7197 correct = false;
7198 goto out;
7201 cli_state_set_uid(cli, old_vuid);
7202 cli_state_set_tid(cli, old_cnum);
7204 /* This should fail. */
7205 status = cli_tdis(cli);
7206 if (NT_STATUS_IS_OK(status)) {
7207 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
7208 correct = false;
7209 goto out;
7210 } else {
7211 /* Should be bad tid. */
7212 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
7213 NT_STATUS_NETWORK_NAME_DELETED)) {
7214 correct = false;
7215 goto out;
7219 cli_rmdir(cli, "\\uid_reg_test");
7221 out:
7223 cli_shutdown(cli);
7224 return correct;
7228 static const char *illegal_chars = "*\\/?<>|\":";
7229 static char force_shortname_chars[] = " +,.[];=\177";
7231 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
7232 const char *mask, void *state)
7234 struct cli_state *pcli = (struct cli_state *)state;
7235 fstring fname;
7236 NTSTATUS status = NT_STATUS_OK;
7238 slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
7240 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
7241 return NT_STATUS_OK;
7243 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
7244 status = cli_rmdir(pcli, fname);
7245 if (!NT_STATUS_IS_OK(status)) {
7246 printf("del_fn: failed to rmdir %s\n,", fname );
7248 } else {
7249 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7250 if (!NT_STATUS_IS_OK(status)) {
7251 printf("del_fn: failed to unlink %s\n,", fname );
7254 return status;
7257 struct sn_state {
7258 int matched;
7259 int i;
7260 bool val;
7263 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
7264 const char *name, void *state)
7266 struct sn_state *s = (struct sn_state *)state;
7267 int i = s->i;
7269 #if 0
7270 printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
7271 i, finfo->name, finfo->short_name);
7272 #endif
7274 if (strchr(force_shortname_chars, i)) {
7275 if (!finfo->short_name) {
7276 /* Shortname not created when it should be. */
7277 d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
7278 __location__, finfo->name, i);
7279 s->val = true;
7281 } else if (finfo->short_name){
7282 /* Shortname created when it should not be. */
7283 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
7284 __location__, finfo->short_name, finfo->name);
7285 s->val = true;
7287 s->matched += 1;
7288 return NT_STATUS_OK;
7291 static bool run_shortname_test(int dummy)
7293 static struct cli_state *cli;
7294 bool correct = True;
7295 int i;
7296 struct sn_state s;
7297 char fname[20];
7298 NTSTATUS status;
7300 printf("starting shortname test\n");
7302 if (!torture_open_connection(&cli, 0)) {
7303 return False;
7306 cli_sockopt(cli, sockops);
7308 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7309 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7310 cli_rmdir(cli, "\\shortname");
7312 status = cli_mkdir(cli, "\\shortname");
7313 if (!NT_STATUS_IS_OK(status)) {
7314 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
7315 __location__, nt_errstr(status));
7316 correct = false;
7317 goto out;
7320 strlcpy(fname, "\\shortname\\", sizeof(fname));
7321 strlcat(fname, "test .txt", sizeof(fname));
7323 s.val = false;
7325 for (i = 32; i < 128; i++) {
7326 uint16_t fnum = (uint16_t)-1;
7328 s.i = i;
7330 if (strchr(illegal_chars, i)) {
7331 continue;
7333 fname[15] = i;
7335 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
7336 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum);
7337 if (!NT_STATUS_IS_OK(status)) {
7338 d_printf("(%s) cli_nt_create of %s failed: %s\n",
7339 __location__, fname, nt_errstr(status));
7340 correct = false;
7341 goto out;
7343 cli_close(cli, fnum);
7345 s.matched = 0;
7346 status = cli_list(cli, "\\shortname\\test*.*", 0,
7347 shortname_list_fn, &s);
7348 if (s.matched != 1) {
7349 d_printf("(%s) failed to list %s: %s\n",
7350 __location__, fname, nt_errstr(status));
7351 correct = false;
7352 goto out;
7355 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7356 if (!NT_STATUS_IS_OK(status)) {
7357 d_printf("(%s) failed to delete %s: %s\n",
7358 __location__, fname, nt_errstr(status));
7359 correct = false;
7360 goto out;
7363 if (s.val) {
7364 correct = false;
7365 goto out;
7369 out:
7371 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7372 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7373 cli_rmdir(cli, "\\shortname");
7374 torture_close_connection(cli);
7375 return correct;
7378 static void pagedsearch_cb(struct tevent_req *req)
7380 int rc;
7381 struct tldap_message *msg;
7382 char *dn;
7384 rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
7385 if (rc != TLDAP_SUCCESS) {
7386 d_printf("tldap_search_paged_recv failed: %s\n",
7387 tldap_err2string(rc));
7388 return;
7390 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
7391 TALLOC_FREE(msg);
7392 return;
7394 if (!tldap_entry_dn(msg, &dn)) {
7395 d_printf("tldap_entry_dn failed\n");
7396 return;
7398 d_printf("%s\n", dn);
7399 TALLOC_FREE(msg);
7402 static bool run_tldap(int dummy)
7404 struct tldap_context *ld;
7405 int fd, rc;
7406 NTSTATUS status;
7407 struct sockaddr_storage addr;
7408 struct tevent_context *ev;
7409 struct tevent_req *req;
7410 char *basedn;
7411 const char *filter;
7413 if (!resolve_name(host, &addr, 0, false)) {
7414 d_printf("could not find host %s\n", host);
7415 return false;
7417 status = open_socket_out(&addr, 389, 9999, &fd);
7418 if (!NT_STATUS_IS_OK(status)) {
7419 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
7420 return false;
7423 ld = tldap_context_create(talloc_tos(), fd);
7424 if (ld == NULL) {
7425 close(fd);
7426 d_printf("tldap_context_create failed\n");
7427 return false;
7430 rc = tldap_fetch_rootdse(ld);
7431 if (rc != TLDAP_SUCCESS) {
7432 d_printf("tldap_fetch_rootdse failed: %s\n",
7433 tldap_errstr(talloc_tos(), ld, rc));
7434 return false;
7437 basedn = tldap_talloc_single_attribute(
7438 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
7439 if (basedn == NULL) {
7440 d_printf("no defaultNamingContext\n");
7441 return false;
7443 d_printf("defaultNamingContext: %s\n", basedn);
7445 ev = tevent_context_init(talloc_tos());
7446 if (ev == NULL) {
7447 d_printf("tevent_context_init failed\n");
7448 return false;
7451 req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
7452 TLDAP_SCOPE_SUB, "(objectclass=*)",
7453 NULL, 0, 0,
7454 NULL, 0, NULL, 0, 0, 0, 0, 5);
7455 if (req == NULL) {
7456 d_printf("tldap_search_paged_send failed\n");
7457 return false;
7459 tevent_req_set_callback(req, pagedsearch_cb, NULL);
7461 tevent_req_poll(req, ev);
7463 TALLOC_FREE(req);
7465 /* test search filters against rootDSE */
7466 filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
7467 "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
7469 rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
7470 NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
7471 talloc_tos(), NULL, NULL);
7472 if (rc != TLDAP_SUCCESS) {
7473 d_printf("tldap_search with complex filter failed: %s\n",
7474 tldap_errstr(talloc_tos(), ld, rc));
7475 return false;
7478 TALLOC_FREE(ld);
7479 return true;
7482 /* Torture test to ensure no regression of :
7483 https://bugzilla.samba.org/show_bug.cgi?id=7084
7486 static bool run_dir_createtime(int dummy)
7488 struct cli_state *cli;
7489 const char *dname = "\\testdir";
7490 const char *fname = "\\testdir\\testfile";
7491 NTSTATUS status;
7492 struct timespec create_time;
7493 struct timespec create_time1;
7494 uint16_t fnum;
7495 bool ret = false;
7497 if (!torture_open_connection(&cli, 0)) {
7498 return false;
7501 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7502 cli_rmdir(cli, dname);
7504 status = cli_mkdir(cli, dname);
7505 if (!NT_STATUS_IS_OK(status)) {
7506 printf("mkdir failed: %s\n", nt_errstr(status));
7507 goto out;
7510 status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
7511 NULL, NULL, NULL);
7512 if (!NT_STATUS_IS_OK(status)) {
7513 printf("cli_qpathinfo2 returned %s\n",
7514 nt_errstr(status));
7515 goto out;
7518 /* Sleep 3 seconds, then create a file. */
7519 sleep(3);
7521 status = cli_open(cli, fname, O_RDWR | O_CREAT | O_EXCL,
7522 DENY_NONE, &fnum);
7523 if (!NT_STATUS_IS_OK(status)) {
7524 printf("cli_open failed: %s\n", nt_errstr(status));
7525 goto out;
7528 status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
7529 NULL, NULL, NULL);
7530 if (!NT_STATUS_IS_OK(status)) {
7531 printf("cli_qpathinfo2 (2) returned %s\n",
7532 nt_errstr(status));
7533 goto out;
7536 if (timespec_compare(&create_time1, &create_time)) {
7537 printf("run_dir_createtime: create time was updated (error)\n");
7538 } else {
7539 printf("run_dir_createtime: create time was not updated (correct)\n");
7540 ret = true;
7543 out:
7545 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7546 cli_rmdir(cli, dname);
7547 if (!torture_close_connection(cli)) {
7548 ret = false;
7550 return ret;
7554 static bool run_streamerror(int dummy)
7556 struct cli_state *cli;
7557 const char *dname = "\\testdir";
7558 const char *streamname =
7559 "testdir:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
7560 NTSTATUS status;
7561 time_t change_time, access_time, write_time;
7562 SMB_OFF_T size;
7563 uint16_t mode, fnum;
7564 bool ret = true;
7566 if (!torture_open_connection(&cli, 0)) {
7567 return false;
7570 cli_unlink(cli, "\\testdir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7571 cli_rmdir(cli, dname);
7573 status = cli_mkdir(cli, dname);
7574 if (!NT_STATUS_IS_OK(status)) {
7575 printf("mkdir failed: %s\n", nt_errstr(status));
7576 return false;
7579 cli_qpathinfo1(cli, streamname, &change_time, &access_time, &write_time,
7580 &size, &mode);
7581 status = cli_nt_error(cli);
7583 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7584 printf("pathinfo returned %s, expected "
7585 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
7586 nt_errstr(status));
7587 ret = false;
7590 status = cli_ntcreate(cli, streamname, 0x16,
7591 FILE_READ_DATA|FILE_READ_EA|
7592 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
7593 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7594 FILE_OPEN, 0, 0, &fnum);
7596 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7597 printf("ntcreate returned %s, expected "
7598 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
7599 nt_errstr(status));
7600 ret = false;
7604 cli_rmdir(cli, dname);
7605 return ret;
7608 static bool run_local_substitute(int dummy)
7610 bool ok = true;
7612 ok &= subst_test("%U", "bla", "", -1, -1, "bla");
7613 ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
7614 ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
7615 ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
7616 ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
7617 ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
7618 ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
7619 ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
7621 /* Different captialization rules in sub_basic... */
7623 ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
7624 "blaDOM") == 0);
7626 return ok;
7629 static bool run_local_base64(int dummy)
7631 int i;
7632 bool ret = true;
7634 for (i=1; i<2000; i++) {
7635 DATA_BLOB blob1, blob2;
7636 char *b64;
7638 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
7639 blob1.length = i;
7640 generate_random_buffer(blob1.data, blob1.length);
7642 b64 = base64_encode_data_blob(talloc_tos(), blob1);
7643 if (b64 == NULL) {
7644 d_fprintf(stderr, "base64_encode_data_blob failed "
7645 "for %d bytes\n", i);
7646 ret = false;
7648 blob2 = base64_decode_data_blob(b64);
7649 TALLOC_FREE(b64);
7651 if (data_blob_cmp(&blob1, &blob2)) {
7652 d_fprintf(stderr, "data_blob_cmp failed for %d "
7653 "bytes\n", i);
7654 ret = false;
7656 TALLOC_FREE(blob1.data);
7657 data_blob_free(&blob2);
7659 return ret;
7662 static bool run_local_gencache(int dummy)
7664 char *val;
7665 time_t tm;
7666 DATA_BLOB blob;
7668 if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
7669 d_printf("%s: gencache_set() failed\n", __location__);
7670 return False;
7673 if (!gencache_get("foo", NULL, NULL)) {
7674 d_printf("%s: gencache_get() failed\n", __location__);
7675 return False;
7678 if (!gencache_get("foo", &val, &tm)) {
7679 d_printf("%s: gencache_get() failed\n", __location__);
7680 return False;
7683 if (strcmp(val, "bar") != 0) {
7684 d_printf("%s: gencache_get() returned %s, expected %s\n",
7685 __location__, val, "bar");
7686 SAFE_FREE(val);
7687 return False;
7690 SAFE_FREE(val);
7692 if (!gencache_del("foo")) {
7693 d_printf("%s: gencache_del() failed\n", __location__);
7694 return False;
7696 if (gencache_del("foo")) {
7697 d_printf("%s: second gencache_del() succeeded\n",
7698 __location__);
7699 return False;
7702 if (gencache_get("foo", &val, &tm)) {
7703 d_printf("%s: gencache_get() on deleted entry "
7704 "succeeded\n", __location__);
7705 return False;
7708 blob = data_blob_string_const_null("bar");
7709 tm = time(NULL) + 60;
7711 if (!gencache_set_data_blob("foo", &blob, tm)) {
7712 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
7713 return False;
7716 if (!gencache_get_data_blob("foo", &blob, NULL, NULL)) {
7717 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
7718 return False;
7721 if (strcmp((const char *)blob.data, "bar") != 0) {
7722 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
7723 __location__, (const char *)blob.data, "bar");
7724 data_blob_free(&blob);
7725 return False;
7728 data_blob_free(&blob);
7730 if (!gencache_del("foo")) {
7731 d_printf("%s: gencache_del() failed\n", __location__);
7732 return False;
7734 if (gencache_del("foo")) {
7735 d_printf("%s: second gencache_del() succeeded\n",
7736 __location__);
7737 return False;
7740 if (gencache_get_data_blob("foo", &blob, NULL, NULL)) {
7741 d_printf("%s: gencache_get_data_blob() on deleted entry "
7742 "succeeded\n", __location__);
7743 return False;
7746 return True;
7749 static bool rbt_testval(struct db_context *db, const char *key,
7750 const char *value)
7752 struct db_record *rec;
7753 TDB_DATA data = string_tdb_data(value);
7754 bool ret = false;
7755 NTSTATUS status;
7757 rec = db->fetch_locked(db, db, string_tdb_data(key));
7758 if (rec == NULL) {
7759 d_fprintf(stderr, "fetch_locked failed\n");
7760 goto done;
7762 status = rec->store(rec, data, 0);
7763 if (!NT_STATUS_IS_OK(status)) {
7764 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
7765 goto done;
7767 TALLOC_FREE(rec);
7769 rec = db->fetch_locked(db, db, string_tdb_data(key));
7770 if (rec == NULL) {
7771 d_fprintf(stderr, "second fetch_locked failed\n");
7772 goto done;
7774 if ((rec->value.dsize != data.dsize)
7775 || (memcmp(rec->value.dptr, data.dptr, data.dsize) != 0)) {
7776 d_fprintf(stderr, "Got wrong data back\n");
7777 goto done;
7780 ret = true;
7781 done:
7782 TALLOC_FREE(rec);
7783 return ret;
7786 static bool run_local_rbtree(int dummy)
7788 struct db_context *db;
7789 bool ret = false;
7790 int i;
7792 db = db_open_rbt(NULL);
7794 if (db == NULL) {
7795 d_fprintf(stderr, "db_open_rbt failed\n");
7796 return false;
7799 for (i=0; i<1000; i++) {
7800 char *key, *value;
7802 if (asprintf(&key, "key%ld", random()) == -1) {
7803 goto done;
7805 if (asprintf(&value, "value%ld", random()) == -1) {
7806 SAFE_FREE(key);
7807 goto done;
7810 if (!rbt_testval(db, key, value)) {
7811 SAFE_FREE(key);
7812 SAFE_FREE(value);
7813 goto done;
7816 SAFE_FREE(value);
7817 if (asprintf(&value, "value%ld", random()) == -1) {
7818 SAFE_FREE(key);
7819 goto done;
7822 if (!rbt_testval(db, key, value)) {
7823 SAFE_FREE(key);
7824 SAFE_FREE(value);
7825 goto done;
7828 SAFE_FREE(key);
7829 SAFE_FREE(value);
7832 ret = true;
7834 done:
7835 TALLOC_FREE(db);
7836 return ret;
7841 local test for character set functions
7843 This is a very simple test for the functionality in convert_string_error()
7845 static bool run_local_convert_string(int dummy)
7847 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
7848 const char *test_strings[2] = { "March", "M\303\244rz" };
7849 char dst[7];
7850 int i;
7852 for (i=0; i<2; i++) {
7853 const char *str = test_strings[i];
7854 int len = strlen(str);
7855 size_t converted_size;
7856 bool ret;
7858 memset(dst, 'X', sizeof(dst));
7860 /* first try with real source length */
7861 ret = convert_string_error(CH_UNIX, CH_UTF8,
7862 str, len,
7863 dst, sizeof(dst),
7864 &converted_size);
7865 if (ret != true) {
7866 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
7867 goto failed;
7870 if (converted_size != len) {
7871 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
7872 str, len, (int)converted_size);
7873 goto failed;
7876 if (strncmp(str, dst, converted_size) != 0) {
7877 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
7878 goto failed;
7881 if (strlen(str) != converted_size) {
7882 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
7883 (int)strlen(str), (int)converted_size);
7884 goto failed;
7887 if (dst[converted_size] != 'X') {
7888 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
7889 goto failed;
7892 /* now with srclen==-1, this causes the nul to be
7893 * converted too */
7894 ret = convert_string_error(CH_UNIX, CH_UTF8,
7895 str, -1,
7896 dst, sizeof(dst),
7897 &converted_size);
7898 if (ret != true) {
7899 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
7900 goto failed;
7903 if (converted_size != len+1) {
7904 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
7905 str, len, (int)converted_size);
7906 goto failed;
7909 if (strncmp(str, dst, converted_size) != 0) {
7910 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
7911 goto failed;
7914 if (len+1 != converted_size) {
7915 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
7916 len+1, (int)converted_size);
7917 goto failed;
7920 if (dst[converted_size] != 'X') {
7921 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
7922 goto failed;
7928 TALLOC_FREE(tmp_ctx);
7929 return true;
7930 failed:
7931 TALLOC_FREE(tmp_ctx);
7932 return false;
7936 struct talloc_dict_test {
7937 int content;
7940 static int talloc_dict_traverse_fn(DATA_BLOB key, void *data, void *priv)
7942 int *count = (int *)priv;
7943 *count += 1;
7944 return 0;
7947 static bool run_local_talloc_dict(int dummy)
7949 struct talloc_dict *dict;
7950 struct talloc_dict_test *t;
7951 int key, count;
7953 dict = talloc_dict_init(talloc_tos());
7954 if (dict == NULL) {
7955 return false;
7958 t = talloc(talloc_tos(), struct talloc_dict_test);
7959 if (t == NULL) {
7960 return false;
7963 key = 1;
7964 t->content = 1;
7965 if (!talloc_dict_set(dict, data_blob_const(&key, sizeof(key)), t)) {
7966 return false;
7969 count = 0;
7970 if (talloc_dict_traverse(dict, talloc_dict_traverse_fn, &count) != 0) {
7971 return false;
7974 if (count != 1) {
7975 return false;
7978 TALLOC_FREE(dict);
7980 return true;
7983 static bool run_local_string_to_sid(int dummy) {
7984 struct dom_sid sid;
7986 if (string_to_sid(&sid, "S--1-5-32-545")) {
7987 printf("allowing S--1-5-32-545\n");
7988 return false;
7990 if (string_to_sid(&sid, "S-1-5-32-+545")) {
7991 printf("allowing S-1-5-32-+545\n");
7992 return false;
7994 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")) {
7995 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
7996 return false;
7998 if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
7999 printf("allowing S-1-5-32-545-abc\n");
8000 return false;
8002 if (!string_to_sid(&sid, "S-1-5-32-545")) {
8003 printf("could not parse S-1-5-32-545\n");
8004 return false;
8006 if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
8007 printf("mis-parsed S-1-5-32-545 as %s\n",
8008 sid_string_tos(&sid));
8009 return false;
8011 return true;
8014 static bool run_local_binary_to_sid(int dummy) {
8015 struct dom_sid *sid = talloc(NULL, struct dom_sid);
8016 static const char good_binary_sid[] = {
8017 0x1, /* revision number */
8018 15, /* num auths */
8019 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8020 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8021 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8022 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8023 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8024 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8025 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8026 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8027 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8028 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8029 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8030 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8031 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8032 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8033 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8034 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8037 static const char long_binary_sid[] = {
8038 0x1, /* revision number */
8039 15, /* num auths */
8040 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8041 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8042 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8043 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8044 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8045 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8046 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8047 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8048 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8049 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8050 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8051 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8052 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8053 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8054 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8055 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8056 0x1, 0x1, 0x1, 0x1, /* auth[15] */
8057 0x1, 0x1, 0x1, 0x1, /* auth[16] */
8058 0x1, 0x1, 0x1, 0x1, /* auth[17] */
8061 static const char long_binary_sid2[] = {
8062 0x1, /* revision number */
8063 32, /* num auths */
8064 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8065 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8066 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8067 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8068 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8069 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8070 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8071 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8072 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8073 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8074 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8075 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8076 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8077 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8078 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8079 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8080 0x1, 0x1, 0x1, 0x1, /* auth[15] */
8081 0x1, 0x1, 0x1, 0x1, /* auth[16] */
8082 0x1, 0x1, 0x1, 0x1, /* auth[17] */
8083 0x1, 0x1, 0x1, 0x1, /* auth[18] */
8084 0x1, 0x1, 0x1, 0x1, /* auth[19] */
8085 0x1, 0x1, 0x1, 0x1, /* auth[20] */
8086 0x1, 0x1, 0x1, 0x1, /* auth[21] */
8087 0x1, 0x1, 0x1, 0x1, /* auth[22] */
8088 0x1, 0x1, 0x1, 0x1, /* auth[23] */
8089 0x1, 0x1, 0x1, 0x1, /* auth[24] */
8090 0x1, 0x1, 0x1, 0x1, /* auth[25] */
8091 0x1, 0x1, 0x1, 0x1, /* auth[26] */
8092 0x1, 0x1, 0x1, 0x1, /* auth[27] */
8093 0x1, 0x1, 0x1, 0x1, /* auth[28] */
8094 0x1, 0x1, 0x1, 0x1, /* auth[29] */
8095 0x1, 0x1, 0x1, 0x1, /* auth[30] */
8096 0x1, 0x1, 0x1, 0x1, /* auth[31] */
8099 if (!sid_parse(good_binary_sid, sizeof(good_binary_sid), sid)) {
8100 return false;
8102 if (sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid)) {
8103 return false;
8105 if (sid_parse(long_binary_sid, sizeof(long_binary_sid), sid)) {
8106 return false;
8108 return true;
8111 /* Split a path name into filename and stream name components. Canonicalise
8112 * such that an implicit $DATA token is always explicit.
8114 * The "specification" of this function can be found in the
8115 * run_local_stream_name() function in torture.c, I've tried those
8116 * combinations against a W2k3 server.
8119 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
8120 char **pbase, char **pstream)
8122 char *base = NULL;
8123 char *stream = NULL;
8124 char *sname; /* stream name */
8125 const char *stype; /* stream type */
8127 DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
8129 sname = strchr_m(fname, ':');
8131 if (lp_posix_pathnames() || (sname == NULL)) {
8132 if (pbase != NULL) {
8133 base = talloc_strdup(mem_ctx, fname);
8134 NT_STATUS_HAVE_NO_MEMORY(base);
8136 goto done;
8139 if (pbase != NULL) {
8140 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
8141 NT_STATUS_HAVE_NO_MEMORY(base);
8144 sname += 1;
8146 stype = strchr_m(sname, ':');
8148 if (stype == NULL) {
8149 sname = talloc_strdup(mem_ctx, sname);
8150 stype = "$DATA";
8152 else {
8153 if (strcasecmp_m(stype, ":$DATA") != 0) {
8155 * If there is an explicit stream type, so far we only
8156 * allow $DATA. Is there anything else allowed? -- vl
8158 DEBUG(10, ("[%s] is an invalid stream type\n", stype));
8159 TALLOC_FREE(base);
8160 return NT_STATUS_OBJECT_NAME_INVALID;
8162 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
8163 stype += 1;
8166 if (sname == NULL) {
8167 TALLOC_FREE(base);
8168 return NT_STATUS_NO_MEMORY;
8171 if (sname[0] == '\0') {
8173 * no stream name, so no stream
8175 goto done;
8178 if (pstream != NULL) {
8179 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
8180 if (stream == NULL) {
8181 TALLOC_FREE(sname);
8182 TALLOC_FREE(base);
8183 return NT_STATUS_NO_MEMORY;
8186 * upper-case the type field
8188 strupper_m(strchr_m(stream, ':')+1);
8191 done:
8192 if (pbase != NULL) {
8193 *pbase = base;
8195 if (pstream != NULL) {
8196 *pstream = stream;
8198 return NT_STATUS_OK;
8201 static bool test_stream_name(const char *fname, const char *expected_base,
8202 const char *expected_stream,
8203 NTSTATUS expected_status)
8205 NTSTATUS status;
8206 char *base = NULL;
8207 char *stream = NULL;
8209 status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
8210 if (!NT_STATUS_EQUAL(status, expected_status)) {
8211 goto error;
8214 if (!NT_STATUS_IS_OK(status)) {
8215 return true;
8218 if (base == NULL) goto error;
8220 if (strcmp(expected_base, base) != 0) goto error;
8222 if ((expected_stream != NULL) && (stream == NULL)) goto error;
8223 if ((expected_stream == NULL) && (stream != NULL)) goto error;
8225 if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
8226 goto error;
8228 TALLOC_FREE(base);
8229 TALLOC_FREE(stream);
8230 return true;
8232 error:
8233 d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
8234 fname, expected_base ? expected_base : "<NULL>",
8235 expected_stream ? expected_stream : "<NULL>",
8236 nt_errstr(expected_status));
8237 d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
8238 base ? base : "<NULL>", stream ? stream : "<NULL>",
8239 nt_errstr(status));
8240 TALLOC_FREE(base);
8241 TALLOC_FREE(stream);
8242 return false;
8245 static bool run_local_stream_name(int dummy)
8247 bool ret = true;
8249 ret &= test_stream_name(
8250 "bla", "bla", NULL, NT_STATUS_OK);
8251 ret &= test_stream_name(
8252 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
8253 ret &= test_stream_name(
8254 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8255 ret &= test_stream_name(
8256 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
8257 ret &= test_stream_name(
8258 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8259 ret &= test_stream_name(
8260 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
8261 ret &= test_stream_name(
8262 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
8263 ret &= test_stream_name(
8264 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
8266 return ret;
8269 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
8271 if (a.length != b.length) {
8272 printf("a.length=%d != b.length=%d\n",
8273 (int)a.length, (int)b.length);
8274 return false;
8276 if (memcmp(a.data, b.data, a.length) != 0) {
8277 printf("a.data and b.data differ\n");
8278 return false;
8280 return true;
8283 static bool run_local_memcache(int dummy)
8285 struct memcache *cache;
8286 DATA_BLOB k1, k2;
8287 DATA_BLOB d1, d2, d3;
8288 DATA_BLOB v1, v2, v3;
8290 TALLOC_CTX *mem_ctx;
8291 char *str1, *str2;
8292 size_t size1, size2;
8293 bool ret = false;
8295 cache = memcache_init(NULL, 100);
8297 if (cache == NULL) {
8298 printf("memcache_init failed\n");
8299 return false;
8302 d1 = data_blob_const("d1", 2);
8303 d2 = data_blob_const("d2", 2);
8304 d3 = data_blob_const("d3", 2);
8306 k1 = data_blob_const("d1", 2);
8307 k2 = data_blob_const("d2", 2);
8309 memcache_add(cache, STAT_CACHE, k1, d1);
8310 memcache_add(cache, GETWD_CACHE, k2, d2);
8312 if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
8313 printf("could not find k1\n");
8314 return false;
8316 if (!data_blob_equal(d1, v1)) {
8317 return false;
8320 if (!memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8321 printf("could not find k2\n");
8322 return false;
8324 if (!data_blob_equal(d2, v2)) {
8325 return false;
8328 memcache_add(cache, STAT_CACHE, k1, d3);
8330 if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
8331 printf("could not find replaced k1\n");
8332 return false;
8334 if (!data_blob_equal(d3, v3)) {
8335 return false;
8338 memcache_add(cache, GETWD_CACHE, k1, d1);
8340 if (memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8341 printf("Did find k2, should have been purged\n");
8342 return false;
8345 TALLOC_FREE(cache);
8347 cache = memcache_init(NULL, 0);
8349 mem_ctx = talloc_init("foo");
8351 str1 = talloc_strdup(mem_ctx, "string1");
8352 str2 = talloc_strdup(mem_ctx, "string2");
8354 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8355 data_blob_string_const("torture"), &str1);
8356 size1 = talloc_total_size(cache);
8358 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8359 data_blob_string_const("torture"), &str2);
8360 size2 = talloc_total_size(cache);
8362 printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
8364 if (size2 > size1) {
8365 printf("memcache leaks memory!\n");
8366 goto fail;
8369 ret = true;
8370 fail:
8371 TALLOC_FREE(cache);
8372 return ret;
8375 static void wbclient_done(struct tevent_req *req)
8377 wbcErr wbc_err;
8378 struct winbindd_response *wb_resp;
8379 int *i = (int *)tevent_req_callback_data_void(req);
8381 wbc_err = wb_trans_recv(req, req, &wb_resp);
8382 TALLOC_FREE(req);
8383 *i += 1;
8384 d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
8387 static bool run_local_wbclient(int dummy)
8389 struct event_context *ev;
8390 struct wb_context **wb_ctx;
8391 struct winbindd_request wb_req;
8392 bool result = false;
8393 int i, j;
8395 BlockSignals(True, SIGPIPE);
8397 ev = tevent_context_init_byname(talloc_tos(), "epoll");
8398 if (ev == NULL) {
8399 goto fail;
8402 wb_ctx = talloc_array(ev, struct wb_context *, nprocs);
8403 if (wb_ctx == NULL) {
8404 goto fail;
8407 ZERO_STRUCT(wb_req);
8408 wb_req.cmd = WINBINDD_PING;
8410 d_printf("nprocs=%d, numops=%d\n", (int)nprocs, (int)torture_numops);
8412 for (i=0; i<nprocs; i++) {
8413 wb_ctx[i] = wb_context_init(ev, NULL);
8414 if (wb_ctx[i] == NULL) {
8415 goto fail;
8417 for (j=0; j<torture_numops; j++) {
8418 struct tevent_req *req;
8419 req = wb_trans_send(ev, ev, wb_ctx[i],
8420 (j % 2) == 0, &wb_req);
8421 if (req == NULL) {
8422 goto fail;
8424 tevent_req_set_callback(req, wbclient_done, &i);
8428 i = 0;
8430 while (i < nprocs * torture_numops) {
8431 tevent_loop_once(ev);
8434 result = true;
8435 fail:
8436 TALLOC_FREE(ev);
8437 return result;
8440 static void getaddrinfo_finished(struct tevent_req *req)
8442 char *name = (char *)tevent_req_callback_data_void(req);
8443 struct addrinfo *ainfo;
8444 int res;
8446 res = getaddrinfo_recv(req, &ainfo);
8447 if (res != 0) {
8448 d_printf("gai(%s) returned %s\n", name, gai_strerror(res));
8449 return;
8451 d_printf("gai(%s) succeeded\n", name);
8452 freeaddrinfo(ainfo);
8455 static bool run_getaddrinfo_send(int dummy)
8457 TALLOC_CTX *frame = talloc_stackframe();
8458 struct fncall_context *ctx;
8459 struct tevent_context *ev;
8460 bool result = false;
8461 const char *names[4] = { "www.samba.org", "notfound.samba.org",
8462 "www.slashdot.org", "heise.de" };
8463 struct tevent_req *reqs[4];
8464 int i;
8466 ev = event_context_init(frame);
8467 if (ev == NULL) {
8468 goto fail;
8471 ctx = fncall_context_init(frame, 4);
8473 for (i=0; i<ARRAY_SIZE(names); i++) {
8474 reqs[i] = getaddrinfo_send(frame, ev, ctx, names[i], NULL,
8475 NULL);
8476 if (reqs[i] == NULL) {
8477 goto fail;
8479 tevent_req_set_callback(reqs[i], getaddrinfo_finished,
8480 discard_const_p(void, names[i]));
8483 for (i=0; i<ARRAY_SIZE(reqs); i++) {
8484 tevent_loop_once(ev);
8487 result = true;
8488 fail:
8489 TALLOC_FREE(frame);
8490 return result;
8493 static bool dbtrans_inc(struct db_context *db)
8495 struct db_record *rec;
8496 uint32_t *val;
8497 bool ret = false;
8498 NTSTATUS status;
8500 rec = db->fetch_locked(db, db, string_term_tdb_data("transtest"));
8501 if (rec == NULL) {
8502 printf(__location__ "fetch_lock failed\n");
8503 return false;
8506 if (rec->value.dsize != sizeof(uint32_t)) {
8507 printf(__location__ "value.dsize = %d\n",
8508 (int)rec->value.dsize);
8509 goto fail;
8512 val = (uint32_t *)rec->value.dptr;
8513 *val += 1;
8515 status = rec->store(rec, make_tdb_data((uint8_t *)val,
8516 sizeof(uint32_t)),
8518 if (!NT_STATUS_IS_OK(status)) {
8519 printf(__location__ "store failed: %s\n",
8520 nt_errstr(status));
8521 goto fail;
8524 ret = true;
8525 fail:
8526 TALLOC_FREE(rec);
8527 return ret;
8530 static bool run_local_dbtrans(int dummy)
8532 struct db_context *db;
8533 struct db_record *rec;
8534 NTSTATUS status;
8535 uint32_t initial;
8536 int res;
8538 db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
8539 O_RDWR|O_CREAT, 0600);
8540 if (db == NULL) {
8541 printf("Could not open transtest.db\n");
8542 return false;
8545 res = db->transaction_start(db);
8546 if (res != 0) {
8547 printf(__location__ "transaction_start failed\n");
8548 return false;
8551 rec = db->fetch_locked(db, db, string_term_tdb_data("transtest"));
8552 if (rec == NULL) {
8553 printf(__location__ "fetch_lock failed\n");
8554 return false;
8557 if (rec->value.dptr == NULL) {
8558 initial = 0;
8559 status = rec->store(
8560 rec, make_tdb_data((uint8_t *)&initial,
8561 sizeof(initial)),
8563 if (!NT_STATUS_IS_OK(status)) {
8564 printf(__location__ "store returned %s\n",
8565 nt_errstr(status));
8566 return false;
8570 TALLOC_FREE(rec);
8572 res = db->transaction_commit(db);
8573 if (res != 0) {
8574 printf(__location__ "transaction_commit failed\n");
8575 return false;
8578 while (true) {
8579 uint32_t val, val2;
8580 int i;
8582 res = db->transaction_start(db);
8583 if (res != 0) {
8584 printf(__location__ "transaction_start failed\n");
8585 break;
8588 if (!dbwrap_fetch_uint32(db, "transtest", &val)) {
8589 printf(__location__ "dbwrap_fetch_uint32 failed\n");
8590 break;
8593 for (i=0; i<10; i++) {
8594 if (!dbtrans_inc(db)) {
8595 return false;
8599 if (!dbwrap_fetch_uint32(db, "transtest", &val2)) {
8600 printf(__location__ "dbwrap_fetch_uint32 failed\n");
8601 break;
8604 if (val2 != val + 10) {
8605 printf(__location__ "val=%d, val2=%d\n",
8606 (int)val, (int)val2);
8607 break;
8610 printf("val2=%d\r", val2);
8612 res = db->transaction_commit(db);
8613 if (res != 0) {
8614 printf(__location__ "transaction_commit failed\n");
8615 break;
8619 TALLOC_FREE(db);
8620 return true;
8624 * Just a dummy test to be run under a debugger. There's no real way
8625 * to inspect the tevent_select specific function from outside of
8626 * tevent_select.c.
8629 static bool run_local_tevent_select(int dummy)
8631 struct tevent_context *ev;
8632 struct tevent_fd *fd1, *fd2;
8633 bool result = false;
8635 ev = tevent_context_init_byname(NULL, "select");
8636 if (ev == NULL) {
8637 d_fprintf(stderr, "tevent_context_init_byname failed\n");
8638 goto fail;
8641 fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
8642 if (fd1 == NULL) {
8643 d_fprintf(stderr, "tevent_add_fd failed\n");
8644 goto fail;
8646 fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
8647 if (fd2 == NULL) {
8648 d_fprintf(stderr, "tevent_add_fd failed\n");
8649 goto fail;
8651 TALLOC_FREE(fd2);
8653 fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
8654 if (fd2 == NULL) {
8655 d_fprintf(stderr, "tevent_add_fd failed\n");
8656 goto fail;
8659 result = true;
8660 fail:
8661 TALLOC_FREE(ev);
8662 return result;
8665 static double create_procs(bool (*fn)(int), bool *result)
8667 int i, status;
8668 volatile pid_t *child_status;
8669 volatile bool *child_status_out;
8670 int synccount;
8671 int tries = 8;
8672 struct timeval start;
8674 synccount = 0;
8676 child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*nprocs);
8677 if (!child_status) {
8678 printf("Failed to setup shared memory\n");
8679 return -1;
8682 child_status_out = (volatile bool *)shm_setup(sizeof(bool)*nprocs);
8683 if (!child_status_out) {
8684 printf("Failed to setup result status shared memory\n");
8685 return -1;
8688 for (i = 0; i < nprocs; i++) {
8689 child_status[i] = 0;
8690 child_status_out[i] = True;
8693 start = timeval_current();
8695 for (i=0;i<nprocs;i++) {
8696 procnum = i;
8697 if (fork() == 0) {
8698 pid_t mypid = getpid();
8699 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
8701 slprintf(myname,sizeof(myname),"CLIENT%d", i);
8703 while (1) {
8704 if (torture_open_connection(&current_cli, i)) break;
8705 if (tries-- == 0) {
8706 printf("pid %d failed to start\n", (int)getpid());
8707 _exit(1);
8709 smb_msleep(10);
8712 child_status[i] = getpid();
8714 while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
8716 child_status_out[i] = fn(i);
8717 _exit(0);
8721 do {
8722 synccount = 0;
8723 for (i=0;i<nprocs;i++) {
8724 if (child_status[i]) synccount++;
8726 if (synccount == nprocs) break;
8727 smb_msleep(10);
8728 } while (timeval_elapsed(&start) < 30);
8730 if (synccount != nprocs) {
8731 printf("FAILED TO START %d CLIENTS (started %d)\n", nprocs, synccount);
8732 *result = False;
8733 return timeval_elapsed(&start);
8736 /* start the client load */
8737 start = timeval_current();
8739 for (i=0;i<nprocs;i++) {
8740 child_status[i] = 0;
8743 printf("%d clients started\n", nprocs);
8745 for (i=0;i<nprocs;i++) {
8746 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
8749 printf("\n");
8751 for (i=0;i<nprocs;i++) {
8752 if (!child_status_out[i]) {
8753 *result = False;
8756 return timeval_elapsed(&start);
8759 #define FLAG_MULTIPROC 1
8761 static struct {
8762 const char *name;
8763 bool (*fn)(int);
8764 unsigned flags;
8765 } torture_ops[] = {
8766 {"FDPASS", run_fdpasstest, 0},
8767 {"LOCK1", run_locktest1, 0},
8768 {"LOCK2", run_locktest2, 0},
8769 {"LOCK3", run_locktest3, 0},
8770 {"LOCK4", run_locktest4, 0},
8771 {"LOCK5", run_locktest5, 0},
8772 {"LOCK6", run_locktest6, 0},
8773 {"LOCK7", run_locktest7, 0},
8774 {"LOCK8", run_locktest8, 0},
8775 {"LOCK9", run_locktest9, 0},
8776 {"UNLINK", run_unlinktest, 0},
8777 {"BROWSE", run_browsetest, 0},
8778 {"ATTR", run_attrtest, 0},
8779 {"TRANS2", run_trans2test, 0},
8780 {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
8781 {"TORTURE",run_torture, FLAG_MULTIPROC},
8782 {"RANDOMIPC", run_randomipc, 0},
8783 {"NEGNOWAIT", run_negprot_nowait, 0},
8784 {"NBENCH", run_nbench, 0},
8785 {"NBENCH2", run_nbench2, 0},
8786 {"OPLOCK1", run_oplock1, 0},
8787 {"OPLOCK2", run_oplock2, 0},
8788 {"OPLOCK4", run_oplock4, 0},
8789 {"DIR", run_dirtest, 0},
8790 {"DIR1", run_dirtest1, 0},
8791 {"DIR-CREATETIME", run_dir_createtime, 0},
8792 {"DENY1", torture_denytest1, 0},
8793 {"DENY2", torture_denytest2, 0},
8794 {"TCON", run_tcon_test, 0},
8795 {"TCONDEV", run_tcon_devtype_test, 0},
8796 {"RW1", run_readwritetest, 0},
8797 {"RW2", run_readwritemulti, FLAG_MULTIPROC},
8798 {"RW3", run_readwritelarge, 0},
8799 {"RW-SIGNING", run_readwritelarge_signtest, 0},
8800 {"OPEN", run_opentest, 0},
8801 {"POSIX", run_simple_posix_open_test, 0},
8802 {"POSIX-APPEND", run_posix_append, 0},
8803 {"CASE-INSENSITIVE-CREATE", run_case_insensitive_create, 0},
8804 {"ASYNC-ECHO", run_async_echo, 0},
8805 { "UID-REGRESSION-TEST", run_uid_regression_test, 0},
8806 { "SHORTNAME-TEST", run_shortname_test, 0},
8807 { "ADDRCHANGE", run_addrchange, 0},
8808 #if 1
8809 {"OPENATTR", run_openattrtest, 0},
8810 #endif
8811 {"XCOPY", run_xcopy, 0},
8812 {"RENAME", run_rename, 0},
8813 {"DELETE", run_deletetest, 0},
8814 {"DELETE-LN", run_deletetest_ln, 0},
8815 {"PROPERTIES", run_properties, 0},
8816 {"MANGLE", torture_mangle, 0},
8817 {"MANGLE1", run_mangle1, 0},
8818 {"W2K", run_w2ktest, 0},
8819 {"TRANS2SCAN", torture_trans2_scan, 0},
8820 {"NTTRANSSCAN", torture_nttrans_scan, 0},
8821 {"UTABLE", torture_utable, 0},
8822 {"CASETABLE", torture_casetable, 0},
8823 {"ERRMAPEXTRACT", run_error_map_extract, 0},
8824 {"PIPE_NUMBER", run_pipe_number, 0},
8825 {"TCON2", run_tcon2_test, 0},
8826 {"IOCTL", torture_ioctl_test, 0},
8827 {"CHKPATH", torture_chkpath_test, 0},
8828 {"FDSESS", run_fdsesstest, 0},
8829 { "EATEST", run_eatest, 0},
8830 { "SESSSETUP_BENCH", run_sesssetup_bench, 0},
8831 { "CHAIN1", run_chain1, 0},
8832 { "CHAIN2", run_chain2, 0},
8833 { "WINDOWS-WRITE", run_windows_write, 0},
8834 { "NTTRANS-CREATE", run_nttrans_create, 0},
8835 { "CLI_ECHO", run_cli_echo, 0},
8836 { "GETADDRINFO", run_getaddrinfo_send, 0},
8837 { "TLDAP", run_tldap },
8838 { "STREAMERROR", run_streamerror },
8839 { "NOTIFY-BENCH", run_notify_bench },
8840 { "BAD-NBT-SESSION", run_bad_nbt_session },
8841 { "SMB-ANY-CONNECT", run_smb_any_connect },
8842 { "NOTIFY-ONLINE", run_notify_online },
8843 { "SMB2-BASIC", run_smb2_basic },
8844 { "LOCAL-SUBSTITUTE", run_local_substitute, 0},
8845 { "LOCAL-GENCACHE", run_local_gencache, 0},
8846 { "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0},
8847 { "LOCAL-BASE64", run_local_base64, 0},
8848 { "LOCAL-RBTREE", run_local_rbtree, 0},
8849 { "LOCAL-MEMCACHE", run_local_memcache, 0},
8850 { "LOCAL-STREAM-NAME", run_local_stream_name, 0},
8851 { "LOCAL-WBCLIENT", run_local_wbclient, 0},
8852 { "LOCAL-string_to_sid", run_local_string_to_sid, 0},
8853 { "LOCAL-binary_to_sid", run_local_binary_to_sid, 0},
8854 { "LOCAL-DBTRANS", run_local_dbtrans, 0},
8855 { "LOCAL-TEVENT-SELECT", run_local_tevent_select, 0},
8856 { "LOCAL-CONVERT-STRING", run_local_convert_string, 0},
8857 { "LOCAL-CONV-AUTH-INFO", run_local_conv_auth_info, 0},
8858 {NULL, NULL, 0}};
8862 /****************************************************************************
8863 run a specified test or "ALL"
8864 ****************************************************************************/
8865 static bool run_test(const char *name)
8867 bool ret = True;
8868 bool result = True;
8869 bool found = False;
8870 int i;
8871 double t;
8872 if (strequal(name,"ALL")) {
8873 for (i=0;torture_ops[i].name;i++) {
8874 run_test(torture_ops[i].name);
8876 found = True;
8879 for (i=0;torture_ops[i].name;i++) {
8880 fstr_sprintf(randomfname, "\\XX%x",
8881 (unsigned)random());
8883 if (strequal(name, torture_ops[i].name)) {
8884 found = True;
8885 printf("Running %s\n", name);
8886 if (torture_ops[i].flags & FLAG_MULTIPROC) {
8887 t = create_procs(torture_ops[i].fn, &result);
8888 if (!result) {
8889 ret = False;
8890 printf("TEST %s FAILED!\n", name);
8892 } else {
8893 struct timeval start;
8894 start = timeval_current();
8895 if (!torture_ops[i].fn(0)) {
8896 ret = False;
8897 printf("TEST %s FAILED!\n", name);
8899 t = timeval_elapsed(&start);
8901 printf("%s took %g secs\n\n", name, t);
8905 if (!found) {
8906 printf("Did not find a test named %s\n", name);
8907 ret = False;
8910 return ret;
8914 static void usage(void)
8916 int i;
8918 printf("WARNING samba4 test suite is much more complete nowadays.\n");
8919 printf("Please use samba4 torture.\n\n");
8921 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
8923 printf("\t-d debuglevel\n");
8924 printf("\t-U user%%pass\n");
8925 printf("\t-k use kerberos\n");
8926 printf("\t-N numprocs\n");
8927 printf("\t-n my_netbios_name\n");
8928 printf("\t-W workgroup\n");
8929 printf("\t-o num_operations\n");
8930 printf("\t-O socket_options\n");
8931 printf("\t-m maximum protocol\n");
8932 printf("\t-L use oplocks\n");
8933 printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
8934 printf("\t-A showall\n");
8935 printf("\t-p port\n");
8936 printf("\t-s seed\n");
8937 printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
8938 printf("\t-f filename filename to test\n");
8939 printf("\n\n");
8941 printf("tests are:");
8942 for (i=0;torture_ops[i].name;i++) {
8943 printf(" %s", torture_ops[i].name);
8945 printf("\n");
8947 printf("default test is ALL\n");
8949 exit(1);
8952 /****************************************************************************
8953 main program
8954 ****************************************************************************/
8955 int main(int argc,char *argv[])
8957 int opt, i;
8958 char *p;
8959 int gotuser = 0;
8960 int gotpass = 0;
8961 bool correct = True;
8962 TALLOC_CTX *frame = talloc_stackframe();
8963 int seed = time(NULL);
8965 #ifdef HAVE_SETBUFFER
8966 setbuffer(stdout, NULL, 0);
8967 #endif
8969 setup_logging("smbtorture", DEBUG_STDOUT);
8971 load_case_tables();
8973 if (is_default_dyn_CONFIGFILE()) {
8974 if(getenv("SMB_CONF_PATH")) {
8975 set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
8978 lp_load_global(get_dyn_CONFIGFILE());
8979 load_interfaces();
8981 if (argc < 2) {
8982 usage();
8985 for(p = argv[1]; *p; p++)
8986 if(*p == '\\')
8987 *p = '/';
8989 if (strncmp(argv[1], "//", 2)) {
8990 usage();
8993 fstrcpy(host, &argv[1][2]);
8994 p = strchr_m(&host[2],'/');
8995 if (!p) {
8996 usage();
8998 *p = 0;
8999 fstrcpy(share, p+1);
9001 fstrcpy(myname, get_myname(talloc_tos()));
9002 if (!*myname) {
9003 fprintf(stderr, "Failed to get my hostname.\n");
9004 return 1;
9007 if (*username == 0 && getenv("LOGNAME")) {
9008 fstrcpy(username,getenv("LOGNAME"));
9011 argc--;
9012 argv++;
9014 fstrcpy(workgroup, lp_workgroup());
9016 while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
9017 != EOF) {
9018 switch (opt) {
9019 case 'p':
9020 port_to_use = atoi(optarg);
9021 break;
9022 case 's':
9023 seed = atoi(optarg);
9024 break;
9025 case 'W':
9026 fstrcpy(workgroup,optarg);
9027 break;
9028 case 'm':
9029 max_protocol = interpret_protocol(optarg, max_protocol);
9030 break;
9031 case 'N':
9032 nprocs = atoi(optarg);
9033 break;
9034 case 'o':
9035 torture_numops = atoi(optarg);
9036 break;
9037 case 'd':
9038 lp_set_cmdline("log level", optarg);
9039 break;
9040 case 'O':
9041 sockops = optarg;
9042 break;
9043 case 'L':
9044 use_oplocks = True;
9045 break;
9046 case 'l':
9047 local_path = optarg;
9048 break;
9049 case 'A':
9050 torture_showall = True;
9051 break;
9052 case 'n':
9053 fstrcpy(myname, optarg);
9054 break;
9055 case 'c':
9056 client_txt = optarg;
9057 break;
9058 case 'e':
9059 do_encrypt = true;
9060 break;
9061 case 'k':
9062 #ifdef HAVE_KRB5
9063 use_kerberos = True;
9064 #else
9065 d_printf("No kerberos support compiled in\n");
9066 exit(1);
9067 #endif
9068 break;
9069 case 'U':
9070 gotuser = 1;
9071 fstrcpy(username,optarg);
9072 p = strchr_m(username,'%');
9073 if (p) {
9074 *p = 0;
9075 fstrcpy(password, p+1);
9076 gotpass = 1;
9078 break;
9079 case 'b':
9080 fstrcpy(multishare_conn_fname, optarg);
9081 use_multishare_conn = True;
9082 break;
9083 case 'B':
9084 torture_blocksize = atoi(optarg);
9085 break;
9086 case 'f':
9087 test_filename = SMB_STRDUP(optarg);
9088 break;
9089 default:
9090 printf("Unknown option %c (%d)\n", (char)opt, opt);
9091 usage();
9095 d_printf("using seed %d\n", seed);
9097 srandom(seed);
9099 if(use_kerberos && !gotuser) gotpass = True;
9101 while (!gotpass) {
9102 p = getpass("Password:");
9103 if (p) {
9104 fstrcpy(password, p);
9105 gotpass = 1;
9109 printf("host=%s share=%s user=%s myname=%s\n",
9110 host, share, username, myname);
9112 if (argc == optind) {
9113 correct = run_test("ALL");
9114 } else {
9115 for (i=optind;i<argc;i++) {
9116 if (!run_test(argv[i])) {
9117 correct = False;
9122 TALLOC_FREE(frame);
9124 if (correct) {
9125 return(0);
9126 } else {
9127 return(1);