s3:torture: make use of CLI_FULL_CONNECTION_FORCE_DOS_ERRORS
[Samba.git] / source3 / torture / torture.c
blob49f26a37a3687a5ffb9318785e50c7d4a7937636
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 use_kerberos;
60 static bool force_dos_errors;
61 static fstring multishare_conn_fname;
62 static bool use_multishare_conn = False;
63 static bool do_encrypt;
64 static const char *local_path = NULL;
65 static int signing_state = Undefined;
66 char *test_filename;
68 bool torture_showall = False;
70 static double create_procs(bool (*fn)(int), bool *result);
73 /* return a pointer to a anonymous shared memory segment of size "size"
74 which will persist across fork() but will disappear when all processes
75 exit
77 The memory is not zeroed
79 This function uses system5 shared memory. It takes advantage of a property
80 that the memory is not destroyed if it is attached when the id is removed
82 void *shm_setup(int size)
84 int shmid;
85 void *ret;
87 #ifdef __QNXNTO__
88 shmid = shm_open("private", O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
89 if (shmid == -1) {
90 printf("can't get shared memory\n");
91 exit(1);
93 shm_unlink("private");
94 if (ftruncate(shmid, size) == -1) {
95 printf("can't set shared memory size\n");
96 exit(1);
98 ret = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, shmid, 0);
99 if (ret == MAP_FAILED) {
100 printf("can't map shared memory\n");
101 exit(1);
103 #else
104 shmid = shmget(IPC_PRIVATE, size, S_IRUSR | S_IWUSR);
105 if (shmid == -1) {
106 printf("can't get shared memory\n");
107 exit(1);
109 ret = (void *)shmat(shmid, 0, 0);
110 if (!ret || ret == (void *)-1) {
111 printf("can't attach to shared memory\n");
112 return NULL;
114 /* the following releases the ipc, but note that this process
115 and all its children will still have access to the memory, its
116 just that the shmid is no longer valid for other shm calls. This
117 means we don't leave behind lots of shm segments after we exit
119 See Stevens "advanced programming in unix env" for details
121 shmctl(shmid, IPC_RMID, 0);
122 #endif
124 return ret;
127 /********************************************************************
128 Ensure a connection is encrypted.
129 ********************************************************************/
131 static bool force_cli_encryption(struct cli_state *c,
132 const char *sharename)
134 uint16 major, minor;
135 uint32 caplow, caphigh;
136 NTSTATUS status;
138 if (!SERVER_HAS_UNIX_CIFS(c)) {
139 d_printf("Encryption required and "
140 "server that doesn't support "
141 "UNIX extensions - failing connect\n");
142 return false;
145 status = cli_unix_extensions_version(c, &major, &minor, &caplow,
146 &caphigh);
147 if (!NT_STATUS_IS_OK(status)) {
148 d_printf("Encryption required and "
149 "can't get UNIX CIFS extensions "
150 "version from server: %s\n", nt_errstr(status));
151 return false;
154 if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
155 d_printf("Encryption required and "
156 "share %s doesn't support "
157 "encryption.\n", sharename);
158 return false;
161 if (c->use_kerberos) {
162 status = cli_gss_smb_encryption_start(c);
163 } else {
164 status = cli_raw_ntlm_smb_encryption_start(c,
165 username,
166 password,
167 workgroup);
170 if (!NT_STATUS_IS_OK(status)) {
171 d_printf("Encryption required and "
172 "setup failed with error %s.\n",
173 nt_errstr(status));
174 return false;
177 return true;
181 static struct cli_state *open_nbt_connection(void)
183 struct cli_state *c;
184 NTSTATUS status;
185 int flags = 0;
187 if (use_oplocks) {
188 flags |= CLI_FULL_CONNECTION_OPLOCKS;
191 if (use_level_II_oplocks) {
192 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
195 if (use_kerberos) {
196 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
199 if (force_dos_errors) {
200 flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
203 status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
204 signing_state, flags, &c);
205 if (!NT_STATUS_IS_OK(status)) {
206 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
207 return NULL;
210 cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
212 return c;
215 /****************************************************************************
216 Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
217 ****************************************************************************/
219 static bool cli_bad_session_request(int fd,
220 struct nmb_name *calling, struct nmb_name *called)
222 TALLOC_CTX *frame;
223 uint8_t len_buf[4];
224 struct iovec iov[3];
225 ssize_t len;
226 uint8_t *inbuf;
227 int err;
228 bool ret = false;
229 uint8_t message_type;
230 uint8_t error;
232 frame = talloc_stackframe();
234 iov[0].iov_base = len_buf;
235 iov[0].iov_len = sizeof(len_buf);
237 /* put in the destination name */
239 iov[1].iov_base = name_mangle(talloc_tos(), called->name,
240 called->name_type);
241 if (iov[1].iov_base == NULL) {
242 goto fail;
244 iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
245 talloc_get_size(iov[1].iov_base));
247 /* and my name */
249 iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
250 calling->name_type);
251 if (iov[2].iov_base == NULL) {
252 goto fail;
254 iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
255 talloc_get_size(iov[2].iov_base));
257 /* Deliberately corrupt the name len (first byte) */
258 *((uint8_t *)iov[2].iov_base) = 100;
260 /* send a session request (RFC 1002) */
261 /* setup the packet length
262 * Remove four bytes from the length count, since the length
263 * field in the NBT Session Service header counts the number
264 * of bytes which follow. The cli_send_smb() function knows
265 * about this and accounts for those four bytes.
266 * CRH.
269 _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
270 SCVAL(len_buf,0,0x81);
272 len = write_data_iov(fd, iov, 3);
273 if (len == -1) {
274 goto fail;
276 len = read_smb(fd, talloc_tos(), &inbuf, &err);
277 if (len == -1) {
278 errno = err;
279 goto fail;
282 message_type = CVAL(inbuf, 0);
283 if (message_type != 0x83) {
284 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
285 message_type);
286 goto fail;
289 if (smb_len(inbuf) != 1) {
290 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
291 (int)smb_len(inbuf));
292 goto fail;
295 error = CVAL(inbuf, 4);
296 if (error != 0x82) {
297 d_fprintf(stderr, "Expected error 0x82, got %d\n",
298 (int)error);
299 goto fail;
302 ret = true;
303 fail:
304 TALLOC_FREE(frame);
305 return ret;
308 /* Insert a NULL at the first separator of the given path and return a pointer
309 * to the remainder of the string.
311 static char *
312 terminate_path_at_separator(char * path)
314 char * p;
316 if (!path) {
317 return NULL;
320 if ((p = strchr_m(path, '/'))) {
321 *p = '\0';
322 return p + 1;
325 if ((p = strchr_m(path, '\\'))) {
326 *p = '\0';
327 return p + 1;
330 /* No separator. */
331 return NULL;
335 parse a //server/share type UNC name
337 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
338 char **hostname, char **sharename)
340 char *p;
342 *hostname = *sharename = NULL;
344 if (strncmp(unc_name, "\\\\", 2) &&
345 strncmp(unc_name, "//", 2)) {
346 return False;
349 *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
350 p = terminate_path_at_separator(*hostname);
352 if (p && *p) {
353 *sharename = talloc_strdup(mem_ctx, p);
354 terminate_path_at_separator(*sharename);
357 if (*hostname && *sharename) {
358 return True;
361 TALLOC_FREE(*hostname);
362 TALLOC_FREE(*sharename);
363 return False;
366 static bool torture_open_connection_share(struct cli_state **c,
367 const char *hostname,
368 const char *sharename)
370 int flags = 0;
371 NTSTATUS status;
373 if (use_kerberos)
374 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
375 if (use_oplocks)
376 flags |= CLI_FULL_CONNECTION_OPLOCKS;
377 if (use_level_II_oplocks)
378 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
380 status = cli_full_connection(c, myname,
381 hostname, NULL, port_to_use,
382 sharename, "?????",
383 username, workgroup,
384 password, flags, signing_state);
385 if (!NT_STATUS_IS_OK(status)) {
386 printf("failed to open share connection: //%s/%s port:%d - %s\n",
387 hostname, sharename, port_to_use, nt_errstr(status));
388 return False;
391 cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
393 if (do_encrypt) {
394 return force_cli_encryption(*c,
395 sharename);
397 return True;
400 bool torture_open_connection(struct cli_state **c, int conn_index)
402 char **unc_list = NULL;
403 int num_unc_names = 0;
404 bool result;
406 if (use_multishare_conn==True) {
407 char *h, *s;
408 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
409 if (!unc_list || num_unc_names <= 0) {
410 printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
411 exit(1);
414 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
415 NULL, &h, &s)) {
416 printf("Failed to parse UNC name %s\n",
417 unc_list[conn_index % num_unc_names]);
418 TALLOC_FREE(unc_list);
419 exit(1);
422 result = torture_open_connection_share(c, h, s);
424 /* h, s were copied earlier */
425 TALLOC_FREE(unc_list);
426 return result;
429 return torture_open_connection_share(c, host, share);
432 bool torture_init_connection(struct cli_state **pcli)
434 struct cli_state *cli;
436 cli = open_nbt_connection();
437 if (cli == NULL) {
438 return false;
441 *pcli = cli;
442 return true;
445 bool torture_cli_session_setup2(struct cli_state *cli, uint16 *new_vuid)
447 uint16_t old_vuid = cli_state_get_uid(cli);
448 fstring old_user_name;
449 size_t passlen = strlen(password);
450 NTSTATUS status;
451 bool ret;
453 fstrcpy(old_user_name, cli->user_name);
454 cli_state_set_uid(cli, 0);
455 ret = NT_STATUS_IS_OK(cli_session_setup(cli, username,
456 password, passlen,
457 password, passlen,
458 workgroup));
459 *new_vuid = cli_state_get_uid(cli);
460 cli_state_set_uid(cli, old_vuid);
461 status = cli_set_username(cli, old_user_name);
462 if (!NT_STATUS_IS_OK(status)) {
463 return false;
465 return ret;
469 bool torture_close_connection(struct cli_state *c)
471 bool ret = True;
472 NTSTATUS status;
474 status = cli_tdis(c);
475 if (!NT_STATUS_IS_OK(status)) {
476 printf("tdis failed (%s)\n", nt_errstr(status));
477 ret = False;
480 cli_shutdown(c);
482 return ret;
486 /* check if the server produced the expected dos or nt error code */
487 static bool check_both_error(int line, NTSTATUS status,
488 uint8 eclass, uint32 ecode, NTSTATUS nterr)
490 if (NT_STATUS_IS_DOS(status)) {
491 uint8 cclass;
492 uint32 num;
494 /* Check DOS error */
495 cclass = NT_STATUS_DOS_CLASS(status);
496 num = NT_STATUS_DOS_CODE(status);
498 if (eclass != cclass || ecode != num) {
499 printf("unexpected error code class=%d code=%d\n",
500 (int)cclass, (int)num);
501 printf(" expected %d/%d %s (line=%d)\n",
502 (int)eclass, (int)ecode, nt_errstr(nterr), line);
503 return false;
505 } else {
506 /* Check NT error */
507 if (!NT_STATUS_EQUAL(nterr, status)) {
508 printf("unexpected error code %s\n",
509 nt_errstr(status));
510 printf(" expected %s (line=%d)\n",
511 nt_errstr(nterr), line);
512 return false;
516 return true;
520 /* check if the server produced the expected error code */
521 static bool check_error(int line, NTSTATUS status,
522 uint8 eclass, uint32 ecode, NTSTATUS nterr)
524 if (NT_STATUS_IS_DOS(status)) {
525 uint8 cclass;
526 uint32 num;
528 /* Check DOS error */
530 cclass = NT_STATUS_DOS_CLASS(status);
531 num = NT_STATUS_DOS_CODE(status);
533 if (eclass != cclass || ecode != num) {
534 printf("unexpected error code class=%d code=%d\n",
535 (int)cclass, (int)num);
536 printf(" expected %d/%d %s (line=%d)\n",
537 (int)eclass, (int)ecode, nt_errstr(nterr),
538 line);
539 return False;
542 } else {
543 /* Check NT error */
545 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
546 printf("unexpected error code %s\n",
547 nt_errstr(status));
548 printf(" expected %s (line=%d)\n", nt_errstr(nterr),
549 line);
550 return False;
554 return True;
558 static bool wait_lock(struct cli_state *c, int fnum, uint32 offset, uint32 len)
560 NTSTATUS status;
562 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
564 while (!NT_STATUS_IS_OK(status)) {
565 if (!check_both_error(__LINE__, status, ERRDOS,
566 ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
567 return false;
570 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
573 return true;
577 static bool rw_torture(struct cli_state *c)
579 const char *lockfname = "\\torture.lck";
580 fstring fname;
581 uint16_t fnum;
582 uint16_t fnum2;
583 pid_t pid2, pid = getpid();
584 int i, j;
585 char buf[1024];
586 bool correct = True;
587 size_t nread = 0;
588 NTSTATUS status;
590 memset(buf, '\0', sizeof(buf));
592 status = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
593 DENY_NONE, &fnum2);
594 if (!NT_STATUS_IS_OK(status)) {
595 status = cli_open(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
597 if (!NT_STATUS_IS_OK(status)) {
598 printf("open of %s failed (%s)\n",
599 lockfname, nt_errstr(status));
600 return False;
603 for (i=0;i<torture_numops;i++) {
604 unsigned n = (unsigned)sys_random()%10;
606 if (i % 10 == 0) {
607 printf("%d\r", i); fflush(stdout);
609 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
611 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
612 return False;
615 status = cli_open(c, fname, O_RDWR | O_CREAT | O_TRUNC,
616 DENY_ALL, &fnum);
617 if (!NT_STATUS_IS_OK(status)) {
618 printf("open failed (%s)\n", nt_errstr(status));
619 correct = False;
620 break;
623 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
624 sizeof(pid), NULL);
625 if (!NT_STATUS_IS_OK(status)) {
626 printf("write failed (%s)\n", nt_errstr(status));
627 correct = False;
630 for (j=0;j<50;j++) {
631 status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
632 sizeof(pid)+(j*sizeof(buf)),
633 sizeof(buf), NULL);
634 if (!NT_STATUS_IS_OK(status)) {
635 printf("write failed (%s)\n",
636 nt_errstr(status));
637 correct = False;
641 pid2 = 0;
643 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
644 &nread);
645 if (!NT_STATUS_IS_OK(status)) {
646 printf("read failed (%s)\n", nt_errstr(status));
647 correct = false;
648 } else if (nread != sizeof(pid)) {
649 printf("read/write compare failed: "
650 "recv %ld req %ld\n", (unsigned long)nread,
651 (unsigned long)sizeof(pid));
652 correct = false;
655 if (pid2 != pid) {
656 printf("data corruption!\n");
657 correct = False;
660 status = cli_close(c, fnum);
661 if (!NT_STATUS_IS_OK(status)) {
662 printf("close failed (%s)\n", nt_errstr(status));
663 correct = False;
666 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
667 if (!NT_STATUS_IS_OK(status)) {
668 printf("unlink failed (%s)\n", nt_errstr(status));
669 correct = False;
672 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
673 if (!NT_STATUS_IS_OK(status)) {
674 printf("unlock failed (%s)\n", nt_errstr(status));
675 correct = False;
679 cli_close(c, fnum2);
680 cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
682 printf("%d\n", i);
684 return correct;
687 static bool run_torture(int dummy)
689 struct cli_state *cli;
690 bool ret;
692 cli = current_cli;
694 cli_sockopt(cli, sockops);
696 ret = rw_torture(cli);
698 if (!torture_close_connection(cli)) {
699 ret = False;
702 return ret;
705 static bool rw_torture3(struct cli_state *c, char *lockfname)
707 uint16_t fnum = (uint16_t)-1;
708 unsigned int i = 0;
709 char buf[131072];
710 char buf_rd[131072];
711 unsigned count;
712 unsigned countprev = 0;
713 size_t sent = 0;
714 bool correct = True;
715 NTSTATUS status = NT_STATUS_OK;
717 srandom(1);
718 for (i = 0; i < sizeof(buf); i += sizeof(uint32))
720 SIVAL(buf, i, sys_random());
723 if (procnum == 0)
725 status = cli_unlink(
726 c, lockfname,
727 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
728 if (!NT_STATUS_IS_OK(status)) {
729 printf("unlink failed (%s) (normal, this file should "
730 "not exist)\n", nt_errstr(status));
733 status = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
734 DENY_NONE, &fnum);
735 if (!NT_STATUS_IS_OK(status)) {
736 printf("first open read/write of %s failed (%s)\n",
737 lockfname, nt_errstr(status));
738 return False;
741 else
743 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
745 status = cli_open(c, lockfname, O_RDONLY,
746 DENY_NONE, &fnum);
747 if (!NT_STATUS_IS_OK(status)) {
748 break;
750 smb_msleep(10);
752 if (!NT_STATUS_IS_OK(status)) {
753 printf("second open read-only of %s failed (%s)\n",
754 lockfname, nt_errstr(status));
755 return False;
759 i = 0;
760 for (count = 0; count < sizeof(buf); count += sent)
762 if (count >= countprev) {
763 printf("%d %8d\r", i, count);
764 fflush(stdout);
765 i++;
766 countprev += (sizeof(buf) / 20);
769 if (procnum == 0)
771 sent = ((unsigned)sys_random()%(20))+ 1;
772 if (sent > sizeof(buf) - count)
774 sent = sizeof(buf) - count;
777 status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
778 count, sent, NULL);
779 if (!NT_STATUS_IS_OK(status)) {
780 printf("write failed (%s)\n",
781 nt_errstr(status));
782 correct = False;
785 else
787 status = cli_read(c, fnum, buf_rd+count, count,
788 sizeof(buf)-count, &sent);
789 if(!NT_STATUS_IS_OK(status)) {
790 printf("read failed offset:%d size:%ld (%s)\n",
791 count, (unsigned long)sizeof(buf)-count,
792 nt_errstr(status));
793 correct = False;
794 sent = 0;
795 } else if (sent > 0) {
796 if (memcmp(buf_rd+count, buf+count, sent) != 0)
798 printf("read/write compare failed\n");
799 printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
800 correct = False;
801 break;
808 status = cli_close(c, fnum);
809 if (!NT_STATUS_IS_OK(status)) {
810 printf("close failed (%s)\n", nt_errstr(status));
811 correct = False;
814 return correct;
817 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
819 const char *lockfname = "\\torture2.lck";
820 uint16_t fnum1;
821 uint16_t fnum2;
822 int i;
823 char buf[131072];
824 char buf_rd[131072];
825 bool correct = True;
826 size_t bytes_read;
827 NTSTATUS status;
829 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
830 if (!NT_STATUS_IS_OK(status)) {
831 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
834 status = cli_open(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
835 DENY_NONE, &fnum1);
836 if (!NT_STATUS_IS_OK(status)) {
837 printf("first open read/write of %s failed (%s)\n",
838 lockfname, nt_errstr(status));
839 return False;
842 status = cli_open(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
843 if (!NT_STATUS_IS_OK(status)) {
844 printf("second open read-only of %s failed (%s)\n",
845 lockfname, nt_errstr(status));
846 cli_close(c1, fnum1);
847 return False;
850 for (i = 0; i < torture_numops; i++)
852 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
853 if (i % 10 == 0) {
854 printf("%d\r", i); fflush(stdout);
857 generate_random_buffer((unsigned char *)buf, buf_size);
859 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
860 buf_size, NULL);
861 if (!NT_STATUS_IS_OK(status)) {
862 printf("write failed (%s)\n", nt_errstr(status));
863 correct = False;
864 break;
867 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
868 if(!NT_STATUS_IS_OK(status)) {
869 printf("read failed (%s)\n", nt_errstr(status));
870 correct = false;
871 break;
872 } else if (bytes_read != buf_size) {
873 printf("read failed\n");
874 printf("read %ld, expected %ld\n",
875 (unsigned long)bytes_read,
876 (unsigned long)buf_size);
877 correct = False;
878 break;
881 if (memcmp(buf_rd, buf, buf_size) != 0)
883 printf("read/write compare failed\n");
884 correct = False;
885 break;
889 status = cli_close(c2, fnum2);
890 if (!NT_STATUS_IS_OK(status)) {
891 printf("close failed (%s)\n", nt_errstr(status));
892 correct = False;
895 status = cli_close(c1, fnum1);
896 if (!NT_STATUS_IS_OK(status)) {
897 printf("close failed (%s)\n", nt_errstr(status));
898 correct = False;
901 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
902 if (!NT_STATUS_IS_OK(status)) {
903 printf("unlink failed (%s)\n", nt_errstr(status));
904 correct = False;
907 return correct;
910 static bool run_readwritetest(int dummy)
912 struct cli_state *cli1, *cli2;
913 bool test1, test2 = False;
915 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
916 return False;
918 cli_sockopt(cli1, sockops);
919 cli_sockopt(cli2, sockops);
921 printf("starting readwritetest\n");
923 test1 = rw_torture2(cli1, cli2);
924 printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
926 if (test1) {
927 test2 = rw_torture2(cli1, cli1);
928 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
931 if (!torture_close_connection(cli1)) {
932 test1 = False;
935 if (!torture_close_connection(cli2)) {
936 test2 = False;
939 return (test1 && test2);
942 static bool run_readwritemulti(int dummy)
944 struct cli_state *cli;
945 bool test;
947 cli = current_cli;
949 cli_sockopt(cli, sockops);
951 printf("run_readwritemulti: fname %s\n", randomfname);
952 test = rw_torture3(cli, randomfname);
954 if (!torture_close_connection(cli)) {
955 test = False;
958 return test;
961 static bool run_readwritelarge_internal(int max_xmit_k)
963 static struct cli_state *cli1;
964 uint16_t fnum1;
965 const char *lockfname = "\\large.dat";
966 SMB_OFF_T fsize;
967 char buf[126*1024];
968 bool correct = True;
969 NTSTATUS status;
971 if (!torture_open_connection(&cli1, 0)) {
972 return False;
974 cli_sockopt(cli1, sockops);
975 memset(buf,'\0',sizeof(buf));
977 cli1->max_xmit = max_xmit_k*1024;
979 if (signing_state == Required) {
980 /* Horrible cheat to force
981 multiple signed outstanding
982 packets against a Samba server.
984 cli1->is_samba = false;
987 printf("starting readwritelarge_internal\n");
989 cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
991 status = cli_open(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
992 DENY_NONE, &fnum1);
993 if (!NT_STATUS_IS_OK(status)) {
994 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
995 return False;
998 cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
1000 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1001 NULL, NULL, NULL);
1002 if (!NT_STATUS_IS_OK(status)) {
1003 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1004 correct = False;
1007 if (fsize == sizeof(buf))
1008 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
1009 (unsigned long)fsize);
1010 else {
1011 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
1012 (unsigned long)fsize);
1013 correct = False;
1016 status = cli_close(cli1, fnum1);
1017 if (!NT_STATUS_IS_OK(status)) {
1018 printf("close failed (%s)\n", nt_errstr(status));
1019 correct = False;
1022 status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1023 if (!NT_STATUS_IS_OK(status)) {
1024 printf("unlink failed (%s)\n", nt_errstr(status));
1025 correct = False;
1028 status = cli_open(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1029 DENY_NONE, &fnum1);
1030 if (!NT_STATUS_IS_OK(status)) {
1031 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1032 return False;
1035 cli1->max_xmit = 4*1024;
1037 cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1039 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1040 NULL, NULL, NULL);
1041 if (!NT_STATUS_IS_OK(status)) {
1042 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1043 correct = False;
1046 if (fsize == sizeof(buf))
1047 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1048 (unsigned long)fsize);
1049 else {
1050 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1051 (unsigned long)fsize);
1052 correct = False;
1055 #if 0
1056 /* ToDo - set allocation. JRA */
1057 if(!cli_set_allocation_size(cli1, fnum1, 0)) {
1058 printf("set allocation size to zero failed (%s)\n", cli_errstr(&cli1));
1059 return False;
1061 if (!cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL, NULL,
1062 NULL, NULL)) {
1063 printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
1064 correct = False;
1066 if (fsize != 0)
1067 printf("readwritelarge test 3 (truncate test) succeeded (size = %x)\n", fsize);
1068 #endif
1070 status = cli_close(cli1, fnum1);
1071 if (!NT_STATUS_IS_OK(status)) {
1072 printf("close failed (%s)\n", nt_errstr(status));
1073 correct = False;
1076 if (!torture_close_connection(cli1)) {
1077 correct = False;
1079 return correct;
1082 static bool run_readwritelarge(int dummy)
1084 return run_readwritelarge_internal(128);
1087 static bool run_readwritelarge_signtest(int dummy)
1089 bool ret;
1090 signing_state = Required;
1091 ret = run_readwritelarge_internal(2);
1092 signing_state = Undefined;
1093 return ret;
1096 int line_count = 0;
1097 int nbio_id;
1099 #define ival(s) strtol(s, NULL, 0)
1101 /* run a test that simulates an approximate netbench client load */
1102 static bool run_netbench(int client)
1104 struct cli_state *cli;
1105 int i;
1106 char line[1024];
1107 char cname[20];
1108 FILE *f;
1109 const char *params[20];
1110 bool correct = True;
1112 cli = current_cli;
1114 nbio_id = client;
1116 cli_sockopt(cli, sockops);
1118 nb_setup(cli);
1120 slprintf(cname,sizeof(cname)-1, "client%d", client);
1122 f = fopen(client_txt, "r");
1124 if (!f) {
1125 perror(client_txt);
1126 return False;
1129 while (fgets(line, sizeof(line)-1, f)) {
1130 char *saveptr;
1131 line_count++;
1133 line[strlen(line)-1] = 0;
1135 /* printf("[%d] %s\n", line_count, line); */
1137 all_string_sub(line,"client1", cname, sizeof(line));
1139 /* parse the command parameters */
1140 params[0] = strtok_r(line, " ", &saveptr);
1141 i = 0;
1142 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1144 params[i] = "";
1146 if (i < 2) continue;
1148 if (!strncmp(params[0],"SMB", 3)) {
1149 printf("ERROR: You are using a dbench 1 load file\n");
1150 exit(1);
1153 if (!strcmp(params[0],"NTCreateX")) {
1154 nb_createx(params[1], ival(params[2]), ival(params[3]),
1155 ival(params[4]));
1156 } else if (!strcmp(params[0],"Close")) {
1157 nb_close(ival(params[1]));
1158 } else if (!strcmp(params[0],"Rename")) {
1159 nb_rename(params[1], params[2]);
1160 } else if (!strcmp(params[0],"Unlink")) {
1161 nb_unlink(params[1]);
1162 } else if (!strcmp(params[0],"Deltree")) {
1163 nb_deltree(params[1]);
1164 } else if (!strcmp(params[0],"Rmdir")) {
1165 nb_rmdir(params[1]);
1166 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1167 nb_qpathinfo(params[1]);
1168 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1169 nb_qfileinfo(ival(params[1]));
1170 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1171 nb_qfsinfo(ival(params[1]));
1172 } else if (!strcmp(params[0],"FIND_FIRST")) {
1173 nb_findfirst(params[1]);
1174 } else if (!strcmp(params[0],"WriteX")) {
1175 nb_writex(ival(params[1]),
1176 ival(params[2]), ival(params[3]), ival(params[4]));
1177 } else if (!strcmp(params[0],"ReadX")) {
1178 nb_readx(ival(params[1]),
1179 ival(params[2]), ival(params[3]), ival(params[4]));
1180 } else if (!strcmp(params[0],"Flush")) {
1181 nb_flush(ival(params[1]));
1182 } else {
1183 printf("Unknown operation %s\n", params[0]);
1184 exit(1);
1187 fclose(f);
1189 nb_cleanup();
1191 if (!torture_close_connection(cli)) {
1192 correct = False;
1195 return correct;
1199 /* run a test that simulates an approximate netbench client load */
1200 static bool run_nbench(int dummy)
1202 double t;
1203 bool correct = True;
1205 nbio_shmem(nprocs);
1207 nbio_id = -1;
1209 signal(SIGALRM, nb_alarm);
1210 alarm(1);
1211 t = create_procs(run_netbench, &correct);
1212 alarm(0);
1214 printf("\nThroughput %g MB/sec\n",
1215 1.0e-6 * nbio_total() / t);
1216 return correct;
1221 This test checks for two things:
1223 1) correct support for retaining locks over a close (ie. the server
1224 must not use posix semantics)
1225 2) support for lock timeouts
1227 static bool run_locktest1(int dummy)
1229 struct cli_state *cli1, *cli2;
1230 const char *fname = "\\lockt1.lck";
1231 uint16_t fnum1, fnum2, fnum3;
1232 time_t t1, t2;
1233 unsigned lock_timeout;
1234 NTSTATUS status;
1236 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1237 return False;
1239 cli_sockopt(cli1, sockops);
1240 cli_sockopt(cli2, sockops);
1242 printf("starting locktest1\n");
1244 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1246 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1247 &fnum1);
1248 if (!NT_STATUS_IS_OK(status)) {
1249 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1250 return False;
1253 status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1254 if (!NT_STATUS_IS_OK(status)) {
1255 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1256 return False;
1259 status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1260 if (!NT_STATUS_IS_OK(status)) {
1261 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1262 return False;
1265 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1266 if (!NT_STATUS_IS_OK(status)) {
1267 printf("lock1 failed (%s)\n", nt_errstr(status));
1268 return false;
1271 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1272 if (NT_STATUS_IS_OK(status)) {
1273 printf("lock2 succeeded! This is a locking bug\n");
1274 return false;
1275 } else {
1276 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1277 NT_STATUS_LOCK_NOT_GRANTED)) {
1278 return false;
1282 lock_timeout = (1 + (random() % 20));
1283 printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1284 t1 = time(NULL);
1285 status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1286 if (NT_STATUS_IS_OK(status)) {
1287 printf("lock3 succeeded! This is a locking bug\n");
1288 return false;
1289 } else {
1290 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1291 NT_STATUS_FILE_LOCK_CONFLICT)) {
1292 return false;
1295 t2 = time(NULL);
1297 if (ABS(t2 - t1) < lock_timeout-1) {
1298 printf("error: This server appears not to support timed lock requests\n");
1301 printf("server slept for %u seconds for a %u second timeout\n",
1302 (unsigned int)(t2-t1), lock_timeout);
1304 status = cli_close(cli1, fnum2);
1305 if (!NT_STATUS_IS_OK(status)) {
1306 printf("close1 failed (%s)\n", nt_errstr(status));
1307 return False;
1310 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1311 if (NT_STATUS_IS_OK(status)) {
1312 printf("lock4 succeeded! This is a locking bug\n");
1313 return false;
1314 } else {
1315 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1316 NT_STATUS_FILE_LOCK_CONFLICT)) {
1317 return false;
1321 status = cli_close(cli1, fnum1);
1322 if (!NT_STATUS_IS_OK(status)) {
1323 printf("close2 failed (%s)\n", nt_errstr(status));
1324 return False;
1327 status = cli_close(cli2, fnum3);
1328 if (!NT_STATUS_IS_OK(status)) {
1329 printf("close3 failed (%s)\n", nt_errstr(status));
1330 return False;
1333 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1334 if (!NT_STATUS_IS_OK(status)) {
1335 printf("unlink failed (%s)\n", nt_errstr(status));
1336 return False;
1340 if (!torture_close_connection(cli1)) {
1341 return False;
1344 if (!torture_close_connection(cli2)) {
1345 return False;
1348 printf("Passed locktest1\n");
1349 return True;
1353 this checks to see if a secondary tconx can use open files from an
1354 earlier tconx
1356 static bool run_tcon_test(int dummy)
1358 static struct cli_state *cli;
1359 const char *fname = "\\tcontest.tmp";
1360 uint16 fnum1;
1361 uint16 cnum1, cnum2, cnum3;
1362 uint16 vuid1, vuid2;
1363 char buf[4];
1364 bool ret = True;
1365 NTSTATUS status;
1367 memset(buf, '\0', sizeof(buf));
1369 if (!torture_open_connection(&cli, 0)) {
1370 return False;
1372 cli_sockopt(cli, sockops);
1374 printf("starting tcontest\n");
1376 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1378 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1379 if (!NT_STATUS_IS_OK(status)) {
1380 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1381 return False;
1384 cnum1 = cli_state_get_tid(cli);
1385 vuid1 = cli_state_get_uid(cli);
1387 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1388 if (!NT_STATUS_IS_OK(status)) {
1389 printf("initial write failed (%s)", nt_errstr(status));
1390 return False;
1393 status = cli_tcon_andx(cli, share, "?????",
1394 password, strlen(password)+1);
1395 if (!NT_STATUS_IS_OK(status)) {
1396 printf("%s refused 2nd tree connect (%s)\n", host,
1397 nt_errstr(status));
1398 cli_shutdown(cli);
1399 return False;
1402 cnum2 = cli_state_get_tid(cli);
1403 cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1404 vuid2 = cli_state_get_uid(cli) + 1;
1406 /* try a write with the wrong tid */
1407 cli_state_set_tid(cli, cnum2);
1409 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1410 if (NT_STATUS_IS_OK(status)) {
1411 printf("* server allows write with wrong TID\n");
1412 ret = False;
1413 } else {
1414 printf("server fails write with wrong TID : %s\n",
1415 nt_errstr(status));
1419 /* try a write with an invalid tid */
1420 cli_state_set_tid(cli, cnum3);
1422 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1423 if (NT_STATUS_IS_OK(status)) {
1424 printf("* server allows write with invalid TID\n");
1425 ret = False;
1426 } else {
1427 printf("server fails write with invalid TID : %s\n",
1428 nt_errstr(status));
1431 /* try a write with an invalid vuid */
1432 cli_state_set_uid(cli, vuid2);
1433 cli_state_set_tid(cli, cnum1);
1435 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1436 if (NT_STATUS_IS_OK(status)) {
1437 printf("* server allows write with invalid VUID\n");
1438 ret = False;
1439 } else {
1440 printf("server fails write with invalid VUID : %s\n",
1441 nt_errstr(status));
1444 cli_state_set_tid(cli, cnum1);
1445 cli_state_set_uid(cli, vuid1);
1447 status = cli_close(cli, fnum1);
1448 if (!NT_STATUS_IS_OK(status)) {
1449 printf("close failed (%s)\n", nt_errstr(status));
1450 return False;
1453 cli_state_set_tid(cli, cnum2);
1455 status = cli_tdis(cli);
1456 if (!NT_STATUS_IS_OK(status)) {
1457 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1458 return False;
1461 cli_state_set_tid(cli, cnum1);
1463 if (!torture_close_connection(cli)) {
1464 return False;
1467 return ret;
1472 checks for old style tcon support
1474 static bool run_tcon2_test(int dummy)
1476 static struct cli_state *cli;
1477 uint16 cnum, max_xmit;
1478 char *service;
1479 NTSTATUS status;
1481 if (!torture_open_connection(&cli, 0)) {
1482 return False;
1484 cli_sockopt(cli, sockops);
1486 printf("starting tcon2 test\n");
1488 if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1489 return false;
1492 status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1494 SAFE_FREE(service);
1496 if (!NT_STATUS_IS_OK(status)) {
1497 printf("tcon2 failed : %s\n", nt_errstr(status));
1498 } else {
1499 printf("tcon OK : max_xmit=%d cnum=%d\n",
1500 (int)max_xmit, (int)cnum);
1503 if (!torture_close_connection(cli)) {
1504 return False;
1507 printf("Passed tcon2 test\n");
1508 return True;
1511 static bool tcon_devtest(struct cli_state *cli,
1512 const char *myshare, const char *devtype,
1513 const char *return_devtype,
1514 NTSTATUS expected_error)
1516 NTSTATUS status;
1517 bool ret;
1519 status = cli_tcon_andx(cli, myshare, devtype,
1520 password, strlen(password)+1);
1522 if (NT_STATUS_IS_OK(expected_error)) {
1523 if (NT_STATUS_IS_OK(status)) {
1524 if (strcmp(cli->dev, return_devtype) == 0) {
1525 ret = True;
1526 } else {
1527 printf("tconX to share %s with type %s "
1528 "succeeded but returned the wrong "
1529 "device type (got [%s] but should have got [%s])\n",
1530 myshare, devtype, cli->dev, return_devtype);
1531 ret = False;
1533 } else {
1534 printf("tconX to share %s with type %s "
1535 "should have succeeded but failed\n",
1536 myshare, devtype);
1537 ret = False;
1539 cli_tdis(cli);
1540 } else {
1541 if (NT_STATUS_IS_OK(status)) {
1542 printf("tconx to share %s with type %s "
1543 "should have failed but succeeded\n",
1544 myshare, devtype);
1545 ret = False;
1546 } else {
1547 if (NT_STATUS_EQUAL(cli_nt_error(cli),
1548 expected_error)) {
1549 ret = True;
1550 } else {
1551 printf("Returned unexpected error\n");
1552 ret = False;
1556 return ret;
1560 checks for correct tconX support
1562 static bool run_tcon_devtype_test(int dummy)
1564 static struct cli_state *cli1 = NULL;
1565 int flags = 0;
1566 NTSTATUS status;
1567 bool ret = True;
1569 status = cli_full_connection(&cli1, myname,
1570 host, NULL, port_to_use,
1571 NULL, NULL,
1572 username, workgroup,
1573 password, flags, signing_state);
1575 if (!NT_STATUS_IS_OK(status)) {
1576 printf("could not open connection\n");
1577 return False;
1580 if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1581 ret = False;
1583 if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1584 ret = False;
1586 if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1587 ret = False;
1589 if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1590 ret = False;
1592 if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1593 ret = False;
1595 if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1596 ret = False;
1598 if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1599 ret = False;
1601 if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1602 ret = False;
1604 if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1605 ret = False;
1607 if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1608 ret = False;
1610 cli_shutdown(cli1);
1612 if (ret)
1613 printf("Passed tcondevtest\n");
1615 return ret;
1620 This test checks that
1622 1) the server supports multiple locking contexts on the one SMB
1623 connection, distinguished by PID.
1625 2) the server correctly fails overlapping locks made by the same PID (this
1626 goes against POSIX behaviour, which is why it is tricky to implement)
1628 3) the server denies unlock requests by an incorrect client PID
1630 static bool run_locktest2(int dummy)
1632 static struct cli_state *cli;
1633 const char *fname = "\\lockt2.lck";
1634 uint16_t fnum1, fnum2, fnum3;
1635 bool correct = True;
1636 NTSTATUS status;
1638 if (!torture_open_connection(&cli, 0)) {
1639 return False;
1642 cli_sockopt(cli, sockops);
1644 printf("starting locktest2\n");
1646 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1648 cli_setpid(cli, 1);
1650 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1651 if (!NT_STATUS_IS_OK(status)) {
1652 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1653 return False;
1656 status = cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1657 if (!NT_STATUS_IS_OK(status)) {
1658 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1659 return False;
1662 cli_setpid(cli, 2);
1664 status = cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1665 if (!NT_STATUS_IS_OK(status)) {
1666 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1667 return False;
1670 cli_setpid(cli, 1);
1672 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1673 if (!NT_STATUS_IS_OK(status)) {
1674 printf("lock1 failed (%s)\n", nt_errstr(status));
1675 return false;
1678 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1679 if (NT_STATUS_IS_OK(status)) {
1680 printf("WRITE lock1 succeeded! This is a locking bug\n");
1681 correct = false;
1682 } else {
1683 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1684 NT_STATUS_LOCK_NOT_GRANTED)) {
1685 return false;
1689 status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1690 if (NT_STATUS_IS_OK(status)) {
1691 printf("WRITE lock2 succeeded! This is a locking bug\n");
1692 correct = false;
1693 } else {
1694 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1695 NT_STATUS_LOCK_NOT_GRANTED)) {
1696 return false;
1700 status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1701 if (NT_STATUS_IS_OK(status)) {
1702 printf("READ lock2 succeeded! This is a locking bug\n");
1703 correct = false;
1704 } else {
1705 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1706 NT_STATUS_FILE_LOCK_CONFLICT)) {
1707 return false;
1711 status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1712 if (!NT_STATUS_IS_OK(status)) {
1713 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1715 cli_setpid(cli, 2);
1716 if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1717 printf("unlock at 100 succeeded! This is a locking bug\n");
1718 correct = False;
1721 status = cli_unlock(cli, fnum1, 0, 4);
1722 if (NT_STATUS_IS_OK(status)) {
1723 printf("unlock1 succeeded! This is a locking bug\n");
1724 correct = false;
1725 } else {
1726 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1727 NT_STATUS_RANGE_NOT_LOCKED)) {
1728 return false;
1732 status = cli_unlock(cli, fnum1, 0, 8);
1733 if (NT_STATUS_IS_OK(status)) {
1734 printf("unlock2 succeeded! This is a locking bug\n");
1735 correct = false;
1736 } else {
1737 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1738 NT_STATUS_RANGE_NOT_LOCKED)) {
1739 return false;
1743 status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1744 if (NT_STATUS_IS_OK(status)) {
1745 printf("lock3 succeeded! This is a locking bug\n");
1746 correct = false;
1747 } else {
1748 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1749 NT_STATUS_LOCK_NOT_GRANTED)) {
1750 return false;
1754 cli_setpid(cli, 1);
1756 status = cli_close(cli, fnum1);
1757 if (!NT_STATUS_IS_OK(status)) {
1758 printf("close1 failed (%s)\n", nt_errstr(status));
1759 return False;
1762 status = cli_close(cli, fnum2);
1763 if (!NT_STATUS_IS_OK(status)) {
1764 printf("close2 failed (%s)\n", nt_errstr(status));
1765 return False;
1768 status = cli_close(cli, fnum3);
1769 if (!NT_STATUS_IS_OK(status)) {
1770 printf("close3 failed (%s)\n", nt_errstr(status));
1771 return False;
1774 if (!torture_close_connection(cli)) {
1775 correct = False;
1778 printf("locktest2 finished\n");
1780 return correct;
1785 This test checks that
1787 1) the server supports the full offset range in lock requests
1789 static bool run_locktest3(int dummy)
1791 static struct cli_state *cli1, *cli2;
1792 const char *fname = "\\lockt3.lck";
1793 uint16_t fnum1, fnum2;
1794 int i;
1795 uint32 offset;
1796 bool correct = True;
1797 NTSTATUS status;
1799 #define NEXT_OFFSET offset += (~(uint32)0) / torture_numops
1801 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1802 return False;
1804 cli_sockopt(cli1, sockops);
1805 cli_sockopt(cli2, sockops);
1807 printf("starting locktest3\n");
1809 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1811 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1812 &fnum1);
1813 if (!NT_STATUS_IS_OK(status)) {
1814 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1815 return False;
1818 status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1819 if (!NT_STATUS_IS_OK(status)) {
1820 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1821 return False;
1824 for (offset=i=0;i<torture_numops;i++) {
1825 NEXT_OFFSET;
1827 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1828 if (!NT_STATUS_IS_OK(status)) {
1829 printf("lock1 %d failed (%s)\n",
1831 nt_errstr(status));
1832 return False;
1835 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1836 if (!NT_STATUS_IS_OK(status)) {
1837 printf("lock2 %d failed (%s)\n",
1839 nt_errstr(status));
1840 return False;
1844 for (offset=i=0;i<torture_numops;i++) {
1845 NEXT_OFFSET;
1847 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1848 if (NT_STATUS_IS_OK(status)) {
1849 printf("error: lock1 %d succeeded!\n", i);
1850 return False;
1853 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1854 if (NT_STATUS_IS_OK(status)) {
1855 printf("error: lock2 %d succeeded!\n", i);
1856 return False;
1859 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1860 if (NT_STATUS_IS_OK(status)) {
1861 printf("error: lock3 %d succeeded!\n", i);
1862 return False;
1865 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1866 if (NT_STATUS_IS_OK(status)) {
1867 printf("error: lock4 %d succeeded!\n", i);
1868 return False;
1872 for (offset=i=0;i<torture_numops;i++) {
1873 NEXT_OFFSET;
1875 status = cli_unlock(cli1, fnum1, offset-1, 1);
1876 if (!NT_STATUS_IS_OK(status)) {
1877 printf("unlock1 %d failed (%s)\n",
1879 nt_errstr(status));
1880 return False;
1883 status = cli_unlock(cli2, fnum2, offset-2, 1);
1884 if (!NT_STATUS_IS_OK(status)) {
1885 printf("unlock2 %d failed (%s)\n",
1887 nt_errstr(status));
1888 return False;
1892 status = cli_close(cli1, fnum1);
1893 if (!NT_STATUS_IS_OK(status)) {
1894 printf("close1 failed (%s)\n", nt_errstr(status));
1895 return False;
1898 status = cli_close(cli2, fnum2);
1899 if (!NT_STATUS_IS_OK(status)) {
1900 printf("close2 failed (%s)\n", nt_errstr(status));
1901 return False;
1904 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1905 if (!NT_STATUS_IS_OK(status)) {
1906 printf("unlink failed (%s)\n", nt_errstr(status));
1907 return False;
1910 if (!torture_close_connection(cli1)) {
1911 correct = False;
1914 if (!torture_close_connection(cli2)) {
1915 correct = False;
1918 printf("finished locktest3\n");
1920 return correct;
1923 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
1924 char *buf, off_t offset, size_t size,
1925 size_t *nread, size_t expect)
1927 NTSTATUS status;
1928 size_t l_nread;
1930 status = cli_read(cli, fnum, buf, offset, size, &l_nread);
1932 if(!NT_STATUS_IS_OK(status)) {
1933 return false;
1934 } else if (l_nread != expect) {
1935 return false;
1938 if (nread) {
1939 *nread = l_nread;
1942 return true;
1945 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1946 printf("** "); correct = False; \
1950 looks at overlapping locks
1952 static bool run_locktest4(int dummy)
1954 static struct cli_state *cli1, *cli2;
1955 const char *fname = "\\lockt4.lck";
1956 uint16_t fnum1, fnum2, f;
1957 bool ret;
1958 char buf[1000];
1959 bool correct = True;
1960 NTSTATUS status;
1962 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1963 return False;
1966 cli_sockopt(cli1, sockops);
1967 cli_sockopt(cli2, sockops);
1969 printf("starting locktest4\n");
1971 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1973 cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1974 cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1976 memset(buf, 0, sizeof(buf));
1978 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
1979 NULL);
1980 if (!NT_STATUS_IS_OK(status)) {
1981 printf("Failed to create file: %s\n", nt_errstr(status));
1982 correct = False;
1983 goto fail;
1986 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1987 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
1988 EXPECTED(ret, False);
1989 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1991 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
1992 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
1993 EXPECTED(ret, True);
1994 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1996 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
1997 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
1998 EXPECTED(ret, False);
1999 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
2001 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
2002 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
2003 EXPECTED(ret, True);
2004 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
2006 ret = (cli_setpid(cli1, 1),
2007 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
2008 (cli_setpid(cli1, 2),
2009 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
2010 EXPECTED(ret, False);
2011 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
2013 ret = (cli_setpid(cli1, 1),
2014 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
2015 (cli_setpid(cli1, 2),
2016 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
2017 EXPECTED(ret, True);
2018 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
2020 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
2021 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
2022 EXPECTED(ret, True);
2023 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
2025 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
2026 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
2027 EXPECTED(ret, False);
2028 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
2030 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
2031 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
2032 EXPECTED(ret, False);
2033 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
2035 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
2036 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2037 EXPECTED(ret, True);
2038 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2040 ret = (cli_setpid(cli1, 1),
2041 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2042 (cli_setpid(cli1, 2),
2043 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2044 EXPECTED(ret, False);
2045 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2047 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2048 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2049 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2050 EXPECTED(ret, False);
2051 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2054 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2055 test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2056 EXPECTED(ret, False);
2057 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2059 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2060 ret = NT_STATUS_IS_OK(status);
2061 if (ret) {
2062 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2063 NULL);
2064 ret = NT_STATUS_IS_OK(status);
2066 EXPECTED(ret, False);
2067 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2070 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2071 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2072 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2073 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2074 EXPECTED(ret, True);
2075 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2078 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2079 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2080 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2081 test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2082 !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2083 150, 4, NULL))) &&
2084 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2085 EXPECTED(ret, True);
2086 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2088 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2089 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2090 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2091 160, 4, NULL)) &&
2092 test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2093 EXPECTED(ret, True);
2094 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2096 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2097 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2098 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2099 170, 4, NULL)) &&
2100 test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2101 EXPECTED(ret, True);
2102 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2104 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2105 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2106 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2107 !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2108 190, 4, NULL)) &&
2109 test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2110 EXPECTED(ret, True);
2111 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2113 cli_close(cli1, fnum1);
2114 cli_close(cli2, fnum2);
2115 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2116 cli_open(cli1, fname, O_RDWR, DENY_NONE, &f);
2117 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2118 NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2119 NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2120 NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2121 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2122 cli_close(cli1, f);
2123 cli_close(cli1, fnum1);
2124 EXPECTED(ret, True);
2125 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2127 fail:
2128 cli_close(cli1, fnum1);
2129 cli_close(cli2, fnum2);
2130 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2131 torture_close_connection(cli1);
2132 torture_close_connection(cli2);
2134 printf("finished locktest4\n");
2135 return correct;
2139 looks at lock upgrade/downgrade.
2141 static bool run_locktest5(int dummy)
2143 static struct cli_state *cli1, *cli2;
2144 const char *fname = "\\lockt5.lck";
2145 uint16_t fnum1, fnum2, fnum3;
2146 bool ret;
2147 char buf[1000];
2148 bool correct = True;
2149 NTSTATUS status;
2151 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2152 return False;
2155 cli_sockopt(cli1, sockops);
2156 cli_sockopt(cli2, sockops);
2158 printf("starting locktest5\n");
2160 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2162 cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2163 cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2164 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2166 memset(buf, 0, sizeof(buf));
2168 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2169 NULL);
2170 if (!NT_STATUS_IS_OK(status)) {
2171 printf("Failed to create file: %s\n", nt_errstr(status));
2172 correct = False;
2173 goto fail;
2176 /* Check for NT bug... */
2177 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2178 NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2179 cli_close(cli1, fnum1);
2180 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2181 status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2182 ret = NT_STATUS_IS_OK(status);
2183 EXPECTED(ret, True);
2184 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2185 cli_close(cli1, fnum1);
2186 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2187 cli_unlock(cli1, fnum3, 0, 1);
2189 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2190 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2191 EXPECTED(ret, True);
2192 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2194 status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2195 ret = NT_STATUS_IS_OK(status);
2196 EXPECTED(ret, False);
2198 printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2200 /* Unlock the process 2 lock. */
2201 cli_unlock(cli2, fnum2, 0, 4);
2203 status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2204 ret = NT_STATUS_IS_OK(status);
2205 EXPECTED(ret, False);
2207 printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
2209 /* Unlock the process 1 fnum3 lock. */
2210 cli_unlock(cli1, fnum3, 0, 4);
2212 /* Stack 2 more locks here. */
2213 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2214 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2216 EXPECTED(ret, True);
2217 printf("the same process %s stack read locks\n", ret?"can":"cannot");
2219 /* Unlock the first process lock, then check this was the WRITE lock that was
2220 removed. */
2222 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2223 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2225 EXPECTED(ret, True);
2226 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2228 /* Unlock the process 2 lock. */
2229 cli_unlock(cli2, fnum2, 0, 4);
2231 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2233 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2234 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2235 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2237 EXPECTED(ret, True);
2238 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2240 /* Ensure the next unlock fails. */
2241 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2242 EXPECTED(ret, False);
2243 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2245 /* Ensure connection 2 can get a write lock. */
2246 status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2247 ret = NT_STATUS_IS_OK(status);
2248 EXPECTED(ret, True);
2250 printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2253 fail:
2254 cli_close(cli1, fnum1);
2255 cli_close(cli2, fnum2);
2256 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2257 if (!torture_close_connection(cli1)) {
2258 correct = False;
2260 if (!torture_close_connection(cli2)) {
2261 correct = False;
2264 printf("finished locktest5\n");
2266 return correct;
2270 tries the unusual lockingX locktype bits
2272 static bool run_locktest6(int dummy)
2274 static struct cli_state *cli;
2275 const char *fname[1] = { "\\lock6.txt" };
2276 int i;
2277 uint16_t fnum;
2278 NTSTATUS status;
2280 if (!torture_open_connection(&cli, 0)) {
2281 return False;
2284 cli_sockopt(cli, sockops);
2286 printf("starting locktest6\n");
2288 for (i=0;i<1;i++) {
2289 printf("Testing %s\n", fname[i]);
2291 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2293 cli_open(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2294 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2295 cli_close(cli, fnum);
2296 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2298 cli_open(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2299 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2300 cli_close(cli, fnum);
2301 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2303 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2306 torture_close_connection(cli);
2308 printf("finished locktest6\n");
2309 return True;
2312 static bool run_locktest7(int dummy)
2314 struct cli_state *cli1;
2315 const char *fname = "\\lockt7.lck";
2316 uint16_t fnum1;
2317 char buf[200];
2318 bool correct = False;
2319 size_t nread;
2320 NTSTATUS status;
2322 if (!torture_open_connection(&cli1, 0)) {
2323 return False;
2326 cli_sockopt(cli1, sockops);
2328 printf("starting locktest7\n");
2330 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2332 cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2334 memset(buf, 0, sizeof(buf));
2336 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2337 NULL);
2338 if (!NT_STATUS_IS_OK(status)) {
2339 printf("Failed to create file: %s\n", nt_errstr(status));
2340 goto fail;
2343 cli_setpid(cli1, 1);
2345 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2346 if (!NT_STATUS_IS_OK(status)) {
2347 printf("Unable to apply read lock on range 130:4, "
2348 "error was %s\n", nt_errstr(status));
2349 goto fail;
2350 } else {
2351 printf("pid1 successfully locked range 130:4 for READ\n");
2354 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2355 if (!NT_STATUS_IS_OK(status)) {
2356 printf("pid1 unable to read the range 130:4, error was %s\n",
2357 nt_errstr(status));
2358 goto fail;
2359 } else if (nread != 4) {
2360 printf("pid1 unable to read the range 130:4, "
2361 "recv %ld req %d\n", (unsigned long)nread, 4);
2362 goto fail;
2363 } else {
2364 printf("pid1 successfully read the range 130:4\n");
2367 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2368 if (!NT_STATUS_IS_OK(status)) {
2369 printf("pid1 unable to write to the range 130:4, error was "
2370 "%s\n", nt_errstr(status));
2371 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2372 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2373 goto fail;
2375 } else {
2376 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2377 goto fail;
2380 cli_setpid(cli1, 2);
2382 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2383 if (!NT_STATUS_IS_OK(status)) {
2384 printf("pid2 unable to read the range 130:4, error was %s\n",
2385 nt_errstr(status));
2386 goto fail;
2387 } else if (nread != 4) {
2388 printf("pid2 unable to read the range 130:4, "
2389 "recv %ld req %d\n", (unsigned long)nread, 4);
2390 goto fail;
2391 } else {
2392 printf("pid2 successfully read the range 130:4\n");
2395 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2396 if (!NT_STATUS_IS_OK(status)) {
2397 printf("pid2 unable to write to the range 130:4, error was "
2398 "%s\n", nt_errstr(status));
2399 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2400 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2401 goto fail;
2403 } else {
2404 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2405 goto fail;
2408 cli_setpid(cli1, 1);
2409 cli_unlock(cli1, fnum1, 130, 4);
2411 status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2412 if (!NT_STATUS_IS_OK(status)) {
2413 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2414 goto fail;
2415 } else {
2416 printf("pid1 successfully locked range 130:4 for WRITE\n");
2419 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2420 if (!NT_STATUS_IS_OK(status)) {
2421 printf("pid1 unable to read the range 130:4, error was %s\n",
2422 nt_errstr(status));
2423 goto fail;
2424 } else if (nread != 4) {
2425 printf("pid1 unable to read the range 130:4, "
2426 "recv %ld req %d\n", (unsigned long)nread, 4);
2427 goto fail;
2428 } else {
2429 printf("pid1 successfully read the range 130:4\n");
2432 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2433 if (!NT_STATUS_IS_OK(status)) {
2434 printf("pid1 unable to write to the range 130:4, error was "
2435 "%s\n", nt_errstr(status));
2436 goto fail;
2437 } else {
2438 printf("pid1 successfully wrote to the range 130:4\n");
2441 cli_setpid(cli1, 2);
2443 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2444 if (!NT_STATUS_IS_OK(status)) {
2445 printf("pid2 unable to read the range 130:4, error was "
2446 "%s\n", nt_errstr(status));
2447 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2448 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2449 goto fail;
2451 } else {
2452 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2453 (unsigned long)nread);
2454 goto fail;
2457 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2458 if (!NT_STATUS_IS_OK(status)) {
2459 printf("pid2 unable to write to the range 130:4, error was "
2460 "%s\n", nt_errstr(status));
2461 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2462 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2463 goto fail;
2465 } else {
2466 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2467 goto fail;
2470 cli_unlock(cli1, fnum1, 130, 0);
2471 correct = True;
2473 fail:
2474 cli_close(cli1, fnum1);
2475 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2476 torture_close_connection(cli1);
2478 printf("finished locktest7\n");
2479 return correct;
2483 * This demonstrates a problem with our use of GPFS share modes: A file
2484 * descriptor sitting in the pending close queue holding a GPFS share mode
2485 * blocks opening a file another time. Happens with Word 2007 temp files.
2486 * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2487 * open is denied with NT_STATUS_SHARING_VIOLATION.
2490 static bool run_locktest8(int dummy)
2492 struct cli_state *cli1;
2493 const char *fname = "\\lockt8.lck";
2494 uint16_t fnum1, fnum2;
2495 char buf[200];
2496 bool correct = False;
2497 NTSTATUS status;
2499 if (!torture_open_connection(&cli1, 0)) {
2500 return False;
2503 cli_sockopt(cli1, sockops);
2505 printf("starting locktest8\n");
2507 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2509 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2510 &fnum1);
2511 if (!NT_STATUS_IS_OK(status)) {
2512 d_fprintf(stderr, "cli_open returned %s\n", nt_errstr(status));
2513 return false;
2516 memset(buf, 0, sizeof(buf));
2518 status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2519 if (!NT_STATUS_IS_OK(status)) {
2520 d_fprintf(stderr, "cli_open second time returned %s\n",
2521 nt_errstr(status));
2522 goto fail;
2525 status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2526 if (!NT_STATUS_IS_OK(status)) {
2527 printf("Unable to apply read lock on range 1:1, error was "
2528 "%s\n", nt_errstr(status));
2529 goto fail;
2532 status = cli_close(cli1, fnum1);
2533 if (!NT_STATUS_IS_OK(status)) {
2534 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2535 goto fail;
2538 status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2539 if (!NT_STATUS_IS_OK(status)) {
2540 d_fprintf(stderr, "cli_open third time returned %s\n",
2541 nt_errstr(status));
2542 goto fail;
2545 correct = true;
2547 fail:
2548 cli_close(cli1, fnum1);
2549 cli_close(cli1, fnum2);
2550 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2551 torture_close_connection(cli1);
2553 printf("finished locktest8\n");
2554 return correct;
2558 * This test is designed to be run in conjunction with
2559 * external NFS or POSIX locks taken in the filesystem.
2560 * It checks that the smbd server will block until the
2561 * lock is released and then acquire it. JRA.
2564 static bool got_alarm;
2565 static struct cli_state *alarm_cli;
2567 static void alarm_handler(int dummy)
2569 got_alarm = True;
2572 static void alarm_handler_parent(int dummy)
2574 cli_state_disconnect(alarm_cli);
2577 static void do_local_lock(int read_fd, int write_fd)
2579 int fd;
2580 char c = '\0';
2581 struct flock lock;
2582 const char *local_pathname = NULL;
2583 int ret;
2585 local_pathname = talloc_asprintf(talloc_tos(),
2586 "%s/lockt9.lck", local_path);
2587 if (!local_pathname) {
2588 printf("child: alloc fail\n");
2589 exit(1);
2592 unlink(local_pathname);
2593 fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2594 if (fd == -1) {
2595 printf("child: open of %s failed %s.\n",
2596 local_pathname, strerror(errno));
2597 exit(1);
2600 /* Now take a fcntl lock. */
2601 lock.l_type = F_WRLCK;
2602 lock.l_whence = SEEK_SET;
2603 lock.l_start = 0;
2604 lock.l_len = 4;
2605 lock.l_pid = getpid();
2607 ret = fcntl(fd,F_SETLK,&lock);
2608 if (ret == -1) {
2609 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2610 local_pathname, strerror(errno));
2611 exit(1);
2612 } else {
2613 printf("child: got lock 0:4 on file %s.\n",
2614 local_pathname );
2615 fflush(stdout);
2618 CatchSignal(SIGALRM, alarm_handler);
2619 alarm(5);
2620 /* Signal the parent. */
2621 if (write(write_fd, &c, 1) != 1) {
2622 printf("child: start signal fail %s.\n",
2623 strerror(errno));
2624 exit(1);
2626 alarm(0);
2628 alarm(10);
2629 /* Wait for the parent to be ready. */
2630 if (read(read_fd, &c, 1) != 1) {
2631 printf("child: reply signal fail %s.\n",
2632 strerror(errno));
2633 exit(1);
2635 alarm(0);
2637 sleep(5);
2638 close(fd);
2639 printf("child: released lock 0:4 on file %s.\n",
2640 local_pathname );
2641 fflush(stdout);
2642 exit(0);
2645 static bool run_locktest9(int dummy)
2647 struct cli_state *cli1;
2648 const char *fname = "\\lockt9.lck";
2649 uint16_t fnum;
2650 bool correct = False;
2651 int pipe_in[2], pipe_out[2];
2652 pid_t child_pid;
2653 char c = '\0';
2654 int ret;
2655 struct timeval start;
2656 double seconds;
2657 NTSTATUS status;
2659 printf("starting locktest9\n");
2661 if (local_path == NULL) {
2662 d_fprintf(stderr, "locktest9 must be given a local path via -l <localpath>\n");
2663 return false;
2666 if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2667 return false;
2670 child_pid = fork();
2671 if (child_pid == -1) {
2672 return false;
2675 if (child_pid == 0) {
2676 /* Child. */
2677 do_local_lock(pipe_out[0], pipe_in[1]);
2678 exit(0);
2681 close(pipe_out[0]);
2682 close(pipe_in[1]);
2683 pipe_out[0] = -1;
2684 pipe_in[1] = -1;
2686 /* Parent. */
2687 ret = read(pipe_in[0], &c, 1);
2688 if (ret != 1) {
2689 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2690 strerror(errno));
2691 return false;
2694 if (!torture_open_connection(&cli1, 0)) {
2695 return false;
2698 cli_sockopt(cli1, sockops);
2700 status = cli_open(cli1, fname, O_RDWR, DENY_NONE,
2701 &fnum);
2702 if (!NT_STATUS_IS_OK(status)) {
2703 d_fprintf(stderr, "cli_open returned %s\n", nt_errstr(status));
2704 return false;
2707 /* Ensure the child has the lock. */
2708 status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2709 if (NT_STATUS_IS_OK(status)) {
2710 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2711 goto fail;
2712 } else {
2713 d_printf("Child has the lock.\n");
2716 /* Tell the child to wait 5 seconds then exit. */
2717 ret = write(pipe_out[1], &c, 1);
2718 if (ret != 1) {
2719 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2720 strerror(errno));
2721 goto fail;
2724 /* Wait 20 seconds for the lock. */
2725 alarm_cli = cli1;
2726 CatchSignal(SIGALRM, alarm_handler_parent);
2727 alarm(20);
2729 start = timeval_current();
2731 status = cli_lock32(cli1, fnum, 0, 4, -1, WRITE_LOCK);
2732 if (!NT_STATUS_IS_OK(status)) {
2733 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2734 "%s\n", nt_errstr(status));
2735 goto fail_nofd;
2737 alarm(0);
2739 seconds = timeval_elapsed(&start);
2741 printf("Parent got the lock after %.2f seconds.\n",
2742 seconds);
2744 status = cli_close(cli1, fnum);
2745 if (!NT_STATUS_IS_OK(status)) {
2746 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2747 goto fail;
2750 correct = true;
2752 fail:
2753 cli_close(cli1, fnum);
2754 torture_close_connection(cli1);
2756 fail_nofd:
2758 printf("finished locktest9\n");
2759 return correct;
2763 test whether fnums and tids open on one VC are available on another (a major
2764 security hole)
2766 static bool run_fdpasstest(int dummy)
2768 struct cli_state *cli1, *cli2;
2769 const char *fname = "\\fdpass.tst";
2770 uint16_t fnum1;
2771 char buf[1024];
2772 NTSTATUS status;
2774 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2775 return False;
2777 cli_sockopt(cli1, sockops);
2778 cli_sockopt(cli2, sockops);
2780 printf("starting fdpasstest\n");
2782 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2784 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
2785 &fnum1);
2786 if (!NT_STATUS_IS_OK(status)) {
2787 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2788 return False;
2791 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
2792 13, NULL);
2793 if (!NT_STATUS_IS_OK(status)) {
2794 printf("write failed (%s)\n", nt_errstr(status));
2795 return False;
2798 cli_state_set_uid(cli2, cli_state_get_uid(cli1));
2799 cli_state_set_tid(cli2, cli_state_get_tid(cli1));
2800 cli_setpid(cli2, cli_getpid(cli1));
2802 if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
2803 printf("read succeeded! nasty security hole [%s]\n", buf);
2804 return false;
2807 cli_close(cli1, fnum1);
2808 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2810 torture_close_connection(cli1);
2811 torture_close_connection(cli2);
2813 printf("finished fdpasstest\n");
2814 return True;
2817 static bool run_fdsesstest(int dummy)
2819 struct cli_state *cli;
2820 uint16 new_vuid;
2821 uint16 saved_vuid;
2822 uint16 new_cnum;
2823 uint16 saved_cnum;
2824 const char *fname = "\\fdsess.tst";
2825 const char *fname1 = "\\fdsess1.tst";
2826 uint16_t fnum1;
2827 uint16_t fnum2;
2828 char buf[1024];
2829 bool ret = True;
2830 NTSTATUS status;
2832 if (!torture_open_connection(&cli, 0))
2833 return False;
2834 cli_sockopt(cli, sockops);
2836 if (!torture_cli_session_setup2(cli, &new_vuid))
2837 return False;
2839 saved_cnum = cli_state_get_tid(cli);
2840 if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, share, "?????", "", 1)))
2841 return False;
2842 new_cnum = cli_state_get_tid(cli);
2843 cli_state_set_tid(cli, saved_cnum);
2845 printf("starting fdsesstest\n");
2847 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2848 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2850 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2851 if (!NT_STATUS_IS_OK(status)) {
2852 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2853 return False;
2856 status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
2857 NULL);
2858 if (!NT_STATUS_IS_OK(status)) {
2859 printf("write failed (%s)\n", nt_errstr(status));
2860 return False;
2863 saved_vuid = cli_state_get_uid(cli);
2864 cli_state_set_uid(cli, new_vuid);
2866 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2867 printf("read succeeded with different vuid! "
2868 "nasty security hole [%s]\n", buf);
2869 ret = false;
2871 /* Try to open a file with different vuid, samba cnum. */
2872 if (NT_STATUS_IS_OK(cli_open(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
2873 printf("create with different vuid, same cnum succeeded.\n");
2874 cli_close(cli, fnum2);
2875 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2876 } else {
2877 printf("create with different vuid, same cnum failed.\n");
2878 printf("This will cause problems with service clients.\n");
2879 ret = False;
2882 cli_state_set_uid(cli, saved_vuid);
2884 /* Try with same vuid, different cnum. */
2885 cli_state_set_tid(cli, new_cnum);
2887 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2888 printf("read succeeded with different cnum![%s]\n", buf);
2889 ret = false;
2892 cli_state_set_tid(cli, saved_cnum);
2893 cli_close(cli, fnum1);
2894 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2896 torture_close_connection(cli);
2898 printf("finished fdsesstest\n");
2899 return ret;
2903 This test checks that
2905 1) the server does not allow an unlink on a file that is open
2907 static bool run_unlinktest(int dummy)
2909 struct cli_state *cli;
2910 const char *fname = "\\unlink.tst";
2911 uint16_t fnum;
2912 bool correct = True;
2913 NTSTATUS status;
2915 if (!torture_open_connection(&cli, 0)) {
2916 return False;
2919 cli_sockopt(cli, sockops);
2921 printf("starting unlink test\n");
2923 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2925 cli_setpid(cli, 1);
2927 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2928 if (!NT_STATUS_IS_OK(status)) {
2929 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2930 return False;
2933 status = cli_unlink(cli, fname,
2934 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2935 if (NT_STATUS_IS_OK(status)) {
2936 printf("error: server allowed unlink on an open file\n");
2937 correct = False;
2938 } else {
2939 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
2940 NT_STATUS_SHARING_VIOLATION);
2943 cli_close(cli, fnum);
2944 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2946 if (!torture_close_connection(cli)) {
2947 correct = False;
2950 printf("unlink test finished\n");
2952 return correct;
2957 test how many open files this server supports on the one socket
2959 static bool run_maxfidtest(int dummy)
2961 struct cli_state *cli;
2962 fstring fname;
2963 uint16_t fnums[0x11000];
2964 int i;
2965 int retries=4;
2966 bool correct = True;
2967 NTSTATUS status;
2969 cli = current_cli;
2971 if (retries <= 0) {
2972 printf("failed to connect\n");
2973 return False;
2976 cli_sockopt(cli, sockops);
2978 for (i=0; i<0x11000; i++) {
2979 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2980 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
2981 &fnums[i]);
2982 if (!NT_STATUS_IS_OK(status)) {
2983 printf("open of %s failed (%s)\n",
2984 fname, nt_errstr(status));
2985 printf("maximum fnum is %d\n", i);
2986 break;
2988 printf("%6d\r", i);
2990 printf("%6d\n", i);
2991 i--;
2993 printf("cleaning up\n");
2994 for (;i>=0;i--) {
2995 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2996 cli_close(cli, fnums[i]);
2998 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2999 if (!NT_STATUS_IS_OK(status)) {
3000 printf("unlink of %s failed (%s)\n",
3001 fname, nt_errstr(status));
3002 correct = False;
3004 printf("%6d\r", i);
3006 printf("%6d\n", 0);
3008 printf("maxfid test finished\n");
3009 if (!torture_close_connection(cli)) {
3010 correct = False;
3012 return correct;
3015 /* generate a random buffer */
3016 static void rand_buf(char *buf, int len)
3018 while (len--) {
3019 *buf = (char)sys_random();
3020 buf++;
3024 /* send smb negprot commands, not reading the response */
3025 static bool run_negprot_nowait(int dummy)
3027 struct tevent_context *ev;
3028 int i;
3029 struct cli_state *cli;
3030 bool correct = True;
3032 printf("starting negprot nowait test\n");
3034 ev = tevent_context_init(talloc_tos());
3035 if (ev == NULL) {
3036 return false;
3039 if (!(cli = open_nbt_connection())) {
3040 TALLOC_FREE(ev);
3041 return False;
3044 for (i=0;i<50000;i++) {
3045 struct tevent_req *req;
3047 req = cli_negprot_send(ev, ev, cli);
3048 if (req == NULL) {
3049 TALLOC_FREE(ev);
3050 return false;
3052 if (!tevent_req_poll(req, ev)) {
3053 d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3054 strerror(errno));
3055 TALLOC_FREE(ev);
3056 return false;
3058 TALLOC_FREE(req);
3061 if (torture_close_connection(cli)) {
3062 correct = False;
3065 printf("finished negprot nowait test\n");
3067 return correct;
3070 /* send smb negprot commands, not reading the response */
3071 static bool run_bad_nbt_session(int dummy)
3073 struct nmb_name called, calling;
3074 struct sockaddr_storage ss;
3075 NTSTATUS status;
3076 int fd;
3077 bool ret;
3079 printf("starting bad nbt session test\n");
3081 make_nmb_name(&calling, myname, 0x0);
3082 make_nmb_name(&called , host, 0x20);
3084 if (!resolve_name(host, &ss, 0x20, true)) {
3085 d_fprintf(stderr, "Could not resolve name %s\n", host);
3086 return false;
3089 status = open_socket_out(&ss, 139, 10000, &fd);
3090 if (!NT_STATUS_IS_OK(status)) {
3091 d_fprintf(stderr, "open_socket_out failed: %s\n",
3092 nt_errstr(status));
3093 return false;
3096 ret = cli_bad_session_request(fd, &calling, &called);
3097 close(fd);
3098 if (!ret) {
3099 d_fprintf(stderr, "open_socket_out failed: %s\n",
3100 nt_errstr(status));
3101 return false;
3104 printf("finished bad nbt session test\n");
3105 return true;
3108 /* send random IPC commands */
3109 static bool run_randomipc(int dummy)
3111 char *rparam = NULL;
3112 char *rdata = NULL;
3113 unsigned int rdrcnt,rprcnt;
3114 char param[1024];
3115 int api, param_len, i;
3116 struct cli_state *cli;
3117 bool correct = True;
3118 int count = 50000;
3120 printf("starting random ipc test\n");
3122 if (!torture_open_connection(&cli, 0)) {
3123 return False;
3126 for (i=0;i<count;i++) {
3127 api = sys_random() % 500;
3128 param_len = (sys_random() % 64);
3130 rand_buf(param, param_len);
3132 SSVAL(param,0,api);
3134 cli_api(cli,
3135 param, param_len, 8,
3136 NULL, 0, BUFFER_SIZE,
3137 &rparam, &rprcnt,
3138 &rdata, &rdrcnt);
3139 if (i % 100 == 0) {
3140 printf("%d/%d\r", i,count);
3143 printf("%d/%d\n", i, count);
3145 if (!torture_close_connection(cli)) {
3146 correct = False;
3149 printf("finished random ipc test\n");
3151 return correct;
3156 static void browse_callback(const char *sname, uint32 stype,
3157 const char *comment, void *state)
3159 printf("\t%20.20s %08x %s\n", sname, stype, comment);
3165 This test checks the browse list code
3168 static bool run_browsetest(int dummy)
3170 static struct cli_state *cli;
3171 bool correct = True;
3173 printf("starting browse test\n");
3175 if (!torture_open_connection(&cli, 0)) {
3176 return False;
3179 printf("domain list:\n");
3180 cli_NetServerEnum(cli, cli->server_domain,
3181 SV_TYPE_DOMAIN_ENUM,
3182 browse_callback, NULL);
3184 printf("machine list:\n");
3185 cli_NetServerEnum(cli, cli->server_domain,
3186 SV_TYPE_ALL,
3187 browse_callback, NULL);
3189 if (!torture_close_connection(cli)) {
3190 correct = False;
3193 printf("browse test finished\n");
3195 return correct;
3201 This checks how the getatr calls works
3203 static bool run_attrtest(int dummy)
3205 struct cli_state *cli;
3206 uint16_t fnum;
3207 time_t t, t2;
3208 const char *fname = "\\attrib123456789.tst";
3209 bool correct = True;
3210 NTSTATUS status;
3212 printf("starting attrib test\n");
3214 if (!torture_open_connection(&cli, 0)) {
3215 return False;
3218 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3219 cli_open(cli, fname,
3220 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3221 cli_close(cli, fnum);
3223 status = cli_getatr(cli, fname, NULL, NULL, &t);
3224 if (!NT_STATUS_IS_OK(status)) {
3225 printf("getatr failed (%s)\n", nt_errstr(status));
3226 correct = False;
3229 if (abs(t - time(NULL)) > 60*60*24*10) {
3230 printf("ERROR: SMBgetatr bug. time is %s",
3231 ctime(&t));
3232 t = time(NULL);
3233 correct = True;
3236 t2 = t-60*60*24; /* 1 day ago */
3238 status = cli_setatr(cli, fname, 0, t2);
3239 if (!NT_STATUS_IS_OK(status)) {
3240 printf("setatr failed (%s)\n", nt_errstr(status));
3241 correct = True;
3244 status = cli_getatr(cli, fname, NULL, NULL, &t);
3245 if (!NT_STATUS_IS_OK(status)) {
3246 printf("getatr failed (%s)\n", nt_errstr(status));
3247 correct = True;
3250 if (t != t2) {
3251 printf("ERROR: getatr/setatr bug. times are\n%s",
3252 ctime(&t));
3253 printf("%s", ctime(&t2));
3254 correct = True;
3257 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3259 if (!torture_close_connection(cli)) {
3260 correct = False;
3263 printf("attrib test finished\n");
3265 return correct;
3270 This checks a couple of trans2 calls
3272 static bool run_trans2test(int dummy)
3274 struct cli_state *cli;
3275 uint16_t fnum;
3276 SMB_OFF_T size;
3277 time_t c_time, a_time, m_time;
3278 struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
3279 const char *fname = "\\trans2.tst";
3280 const char *dname = "\\trans2";
3281 const char *fname2 = "\\trans2\\trans2.tst";
3282 char *pname;
3283 bool correct = True;
3284 NTSTATUS status;
3285 uint32_t fs_attr;
3287 printf("starting trans2 test\n");
3289 if (!torture_open_connection(&cli, 0)) {
3290 return False;
3293 status = cli_get_fs_attr_info(cli, &fs_attr);
3294 if (!NT_STATUS_IS_OK(status)) {
3295 printf("ERROR: cli_get_fs_attr_info returned %s\n",
3296 nt_errstr(status));
3297 correct = false;
3300 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3301 cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3302 status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
3303 &a_time_ts, &w_time_ts, &m_time_ts, NULL);
3304 if (!NT_STATUS_IS_OK(status)) {
3305 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
3306 correct = False;
3309 status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
3310 if (!NT_STATUS_IS_OK(status)) {
3311 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
3312 correct = False;
3315 if (strcmp(pname, fname)) {
3316 printf("qfilename gave different name? [%s] [%s]\n",
3317 fname, pname);
3318 correct = False;
3321 cli_close(cli, fnum);
3323 sleep(2);
3325 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3326 status = cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
3327 &fnum);
3328 if (!NT_STATUS_IS_OK(status)) {
3329 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3330 return False;
3332 cli_close(cli, fnum);
3334 status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
3335 NULL);
3336 if (!NT_STATUS_IS_OK(status)) {
3337 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
3338 correct = False;
3339 } else {
3340 time_t t = time(NULL);
3342 if (c_time != m_time) {
3343 printf("create time=%s", ctime(&c_time));
3344 printf("modify time=%s", ctime(&m_time));
3345 printf("This system appears to have sticky create times\n");
3347 if ((abs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
3348 printf("access time=%s", ctime(&a_time));
3349 printf("This system appears to set a midnight access time\n");
3350 correct = False;
3353 if (abs(m_time - t) > 60*60*24*7) {
3354 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
3355 correct = False;
3360 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3361 cli_open(cli, fname,
3362 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3363 cli_close(cli, fnum);
3364 status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
3365 &m_time_ts, &size, NULL, NULL);
3366 if (!NT_STATUS_IS_OK(status)) {
3367 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3368 correct = False;
3369 } else {
3370 if (w_time_ts.tv_sec < 60*60*24*2) {
3371 printf("write time=%s", ctime(&w_time_ts.tv_sec));
3372 printf("This system appears to set a initial 0 write time\n");
3373 correct = False;
3377 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3380 /* check if the server updates the directory modification time
3381 when creating a new file */
3382 status = cli_mkdir(cli, dname);
3383 if (!NT_STATUS_IS_OK(status)) {
3384 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
3385 correct = False;
3387 sleep(3);
3388 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3389 &w_time_ts, &m_time_ts, &size, NULL, NULL);
3390 if (!NT_STATUS_IS_OK(status)) {
3391 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3392 correct = False;
3395 cli_open(cli, fname2,
3396 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3397 cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
3398 cli_close(cli, fnum);
3399 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3400 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
3401 if (!NT_STATUS_IS_OK(status)) {
3402 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3403 correct = False;
3404 } else {
3405 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
3406 == 0) {
3407 printf("This system does not update directory modification times\n");
3408 correct = False;
3411 cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3412 cli_rmdir(cli, dname);
3414 if (!torture_close_connection(cli)) {
3415 correct = False;
3418 printf("trans2 test finished\n");
3420 return correct;
3424 This checks new W2K calls.
3427 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
3429 uint8_t *buf = NULL;
3430 uint32 len;
3431 NTSTATUS status;
3433 status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
3434 pcli->max_xmit, NULL, &buf, &len);
3435 if (!NT_STATUS_IS_OK(status)) {
3436 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
3437 nt_errstr(status));
3438 } else {
3439 printf("qfileinfo: level %d, len = %u\n", level, len);
3440 dump_data(0, (uint8 *)buf, len);
3441 printf("\n");
3443 TALLOC_FREE(buf);
3444 return status;
3447 static bool run_w2ktest(int dummy)
3449 struct cli_state *cli;
3450 uint16_t fnum;
3451 const char *fname = "\\w2ktest\\w2k.tst";
3452 int level;
3453 bool correct = True;
3455 printf("starting w2k test\n");
3457 if (!torture_open_connection(&cli, 0)) {
3458 return False;
3461 cli_open(cli, fname,
3462 O_RDWR | O_CREAT , DENY_NONE, &fnum);
3464 for (level = 1004; level < 1040; level++) {
3465 new_trans(cli, fnum, level);
3468 cli_close(cli, fnum);
3470 if (!torture_close_connection(cli)) {
3471 correct = False;
3474 printf("w2k test finished\n");
3476 return correct;
3481 this is a harness for some oplock tests
3483 static bool run_oplock1(int dummy)
3485 struct cli_state *cli1;
3486 const char *fname = "\\lockt1.lck";
3487 uint16_t fnum1;
3488 bool correct = True;
3489 NTSTATUS status;
3491 printf("starting oplock test 1\n");
3493 if (!torture_open_connection(&cli1, 0)) {
3494 return False;
3497 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3499 cli_sockopt(cli1, sockops);
3501 cli1->use_oplocks = True;
3503 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3504 &fnum1);
3505 if (!NT_STATUS_IS_OK(status)) {
3506 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3507 return False;
3510 cli1->use_oplocks = False;
3512 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3513 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3515 status = cli_close(cli1, fnum1);
3516 if (!NT_STATUS_IS_OK(status)) {
3517 printf("close2 failed (%s)\n", nt_errstr(status));
3518 return False;
3521 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3522 if (!NT_STATUS_IS_OK(status)) {
3523 printf("unlink failed (%s)\n", nt_errstr(status));
3524 return False;
3527 if (!torture_close_connection(cli1)) {
3528 correct = False;
3531 printf("finished oplock test 1\n");
3533 return correct;
3536 static bool run_oplock2(int dummy)
3538 struct cli_state *cli1, *cli2;
3539 const char *fname = "\\lockt2.lck";
3540 uint16_t fnum1, fnum2;
3541 int saved_use_oplocks = use_oplocks;
3542 char buf[4];
3543 bool correct = True;
3544 volatile bool *shared_correct;
3545 size_t nread;
3546 NTSTATUS status;
3548 shared_correct = (volatile bool *)shm_setup(sizeof(bool));
3549 *shared_correct = True;
3551 use_level_II_oplocks = True;
3552 use_oplocks = True;
3554 printf("starting oplock test 2\n");
3556 if (!torture_open_connection(&cli1, 0)) {
3557 use_level_II_oplocks = False;
3558 use_oplocks = saved_use_oplocks;
3559 return False;
3562 if (!torture_open_connection(&cli2, 1)) {
3563 use_level_II_oplocks = False;
3564 use_oplocks = saved_use_oplocks;
3565 return False;
3568 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3570 cli_sockopt(cli1, sockops);
3571 cli_sockopt(cli2, sockops);
3573 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3574 &fnum1);
3575 if (!NT_STATUS_IS_OK(status)) {
3576 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3577 return False;
3580 /* Don't need the globals any more. */
3581 use_level_II_oplocks = False;
3582 use_oplocks = saved_use_oplocks;
3584 if (fork() == 0) {
3585 /* Child code */
3586 status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
3587 if (!NT_STATUS_IS_OK(status)) {
3588 printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
3589 *shared_correct = False;
3590 exit(0);
3593 sleep(2);
3595 status = cli_close(cli2, fnum2);
3596 if (!NT_STATUS_IS_OK(status)) {
3597 printf("close2 failed (%s)\n", nt_errstr(status));
3598 *shared_correct = False;
3601 exit(0);
3604 sleep(2);
3606 /* Ensure cli1 processes the break. Empty file should always return 0
3607 * bytes. */
3608 status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
3609 if (!NT_STATUS_IS_OK(status)) {
3610 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
3611 correct = false;
3612 } else if (nread != 0) {
3613 printf("read on empty fnum1 failed. recv %ld expected %d\n",
3614 (unsigned long)nread, 0);
3615 correct = false;
3618 /* Should now be at level II. */
3619 /* Test if sending a write locks causes a break to none. */
3620 status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
3621 if (!NT_STATUS_IS_OK(status)) {
3622 printf("lock failed (%s)\n", nt_errstr(status));
3623 correct = False;
3626 cli_unlock(cli1, fnum1, 0, 4);
3628 sleep(2);
3630 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
3631 if (!NT_STATUS_IS_OK(status)) {
3632 printf("lock failed (%s)\n", nt_errstr(status));
3633 correct = False;
3636 cli_unlock(cli1, fnum1, 0, 4);
3638 sleep(2);
3640 cli_read(cli1, fnum1, buf, 0, 4, NULL);
3642 status = cli_close(cli1, fnum1);
3643 if (!NT_STATUS_IS_OK(status)) {
3644 printf("close1 failed (%s)\n", nt_errstr(status));
3645 correct = False;
3648 sleep(4);
3650 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3651 if (!NT_STATUS_IS_OK(status)) {
3652 printf("unlink failed (%s)\n", nt_errstr(status));
3653 correct = False;
3656 if (!torture_close_connection(cli1)) {
3657 correct = False;
3660 if (!*shared_correct) {
3661 correct = False;
3664 printf("finished oplock test 2\n");
3666 return correct;
3669 struct oplock4_state {
3670 struct tevent_context *ev;
3671 struct cli_state *cli;
3672 bool *got_break;
3673 uint16_t *fnum2;
3676 static void oplock4_got_break(struct tevent_req *req);
3677 static void oplock4_got_open(struct tevent_req *req);
3679 static bool run_oplock4(int dummy)
3681 struct tevent_context *ev;
3682 struct cli_state *cli1, *cli2;
3683 struct tevent_req *oplock_req, *open_req;
3684 const char *fname = "\\lockt4.lck";
3685 const char *fname_ln = "\\lockt4_ln.lck";
3686 uint16_t fnum1, fnum2;
3687 int saved_use_oplocks = use_oplocks;
3688 NTSTATUS status;
3689 bool correct = true;
3691 bool got_break;
3693 struct oplock4_state *state;
3695 printf("starting oplock test 4\n");
3697 if (!torture_open_connection(&cli1, 0)) {
3698 use_level_II_oplocks = false;
3699 use_oplocks = saved_use_oplocks;
3700 return false;
3703 if (!torture_open_connection(&cli2, 1)) {
3704 use_level_II_oplocks = false;
3705 use_oplocks = saved_use_oplocks;
3706 return false;
3709 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3710 cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3712 cli_sockopt(cli1, sockops);
3713 cli_sockopt(cli2, sockops);
3715 /* Create the file. */
3716 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3717 &fnum1);
3718 if (!NT_STATUS_IS_OK(status)) {
3719 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3720 return false;
3723 status = cli_close(cli1, fnum1);
3724 if (!NT_STATUS_IS_OK(status)) {
3725 printf("close1 failed (%s)\n", nt_errstr(status));
3726 return false;
3729 /* Now create a hardlink. */
3730 status = cli_nt_hardlink(cli1, fname, fname_ln);
3731 if (!NT_STATUS_IS_OK(status)) {
3732 printf("nt hardlink failed (%s)\n", nt_errstr(status));
3733 return false;
3736 /* Prove that opening hardlinks cause deny modes to conflict. */
3737 status = cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
3738 if (!NT_STATUS_IS_OK(status)) {
3739 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3740 return false;
3743 status = cli_open(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
3744 if (NT_STATUS_IS_OK(status)) {
3745 printf("open of %s succeeded - should fail with sharing violation.\n",
3746 fname_ln);
3747 return false;
3750 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3751 printf("open of %s should fail with sharing violation. Got %s\n",
3752 fname_ln, nt_errstr(status));
3753 return false;
3756 status = cli_close(cli1, fnum1);
3757 if (!NT_STATUS_IS_OK(status)) {
3758 printf("close1 failed (%s)\n", nt_errstr(status));
3759 return false;
3762 cli1->use_oplocks = true;
3763 cli1->use_level_II_oplocks = true;
3765 cli2->use_oplocks = true;
3766 cli2->use_level_II_oplocks = true;
3768 status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3769 if (!NT_STATUS_IS_OK(status)) {
3770 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3771 return false;
3774 ev = tevent_context_init(talloc_tos());
3775 if (ev == NULL) {
3776 printf("tevent_req_create failed\n");
3777 return false;
3780 state = talloc(ev, struct oplock4_state);
3781 if (state == NULL) {
3782 printf("talloc failed\n");
3783 return false;
3785 state->ev = ev;
3786 state->cli = cli1;
3787 state->got_break = &got_break;
3788 state->fnum2 = &fnum2;
3790 oplock_req = cli_smb_oplock_break_waiter_send(
3791 talloc_tos(), ev, cli1);
3792 if (oplock_req == NULL) {
3793 printf("cli_smb_oplock_break_waiter_send failed\n");
3794 return false;
3796 tevent_req_set_callback(oplock_req, oplock4_got_break, state);
3798 open_req = cli_open_send(
3799 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
3800 if (oplock_req == NULL) {
3801 printf("cli_open_send failed\n");
3802 return false;
3804 tevent_req_set_callback(open_req, oplock4_got_open, state);
3806 got_break = false;
3807 fnum2 = 0xffff;
3809 while (!got_break || fnum2 == 0xffff) {
3810 int ret;
3811 ret = tevent_loop_once(ev);
3812 if (ret == -1) {
3813 printf("tevent_loop_once failed: %s\n",
3814 strerror(errno));
3815 return false;
3819 status = cli_close(cli2, fnum2);
3820 if (!NT_STATUS_IS_OK(status)) {
3821 printf("close2 failed (%s)\n", nt_errstr(status));
3822 correct = false;
3825 status = cli_close(cli1, fnum1);
3826 if (!NT_STATUS_IS_OK(status)) {
3827 printf("close1 failed (%s)\n", nt_errstr(status));
3828 correct = false;
3831 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3832 if (!NT_STATUS_IS_OK(status)) {
3833 printf("unlink failed (%s)\n", nt_errstr(status));
3834 correct = false;
3837 status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3838 if (!NT_STATUS_IS_OK(status)) {
3839 printf("unlink failed (%s)\n", nt_errstr(status));
3840 correct = false;
3843 if (!torture_close_connection(cli1)) {
3844 correct = false;
3847 if (!got_break) {
3848 correct = false;
3851 printf("finished oplock test 4\n");
3853 return correct;
3856 static void oplock4_got_break(struct tevent_req *req)
3858 struct oplock4_state *state = tevent_req_callback_data(
3859 req, struct oplock4_state);
3860 uint16_t fnum;
3861 uint8_t level;
3862 NTSTATUS status;
3864 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
3865 TALLOC_FREE(req);
3866 if (!NT_STATUS_IS_OK(status)) {
3867 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
3868 nt_errstr(status));
3869 return;
3871 *state->got_break = true;
3873 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
3874 NO_OPLOCK);
3875 if (req == NULL) {
3876 printf("cli_oplock_ack_send failed\n");
3877 return;
3881 static void oplock4_got_open(struct tevent_req *req)
3883 struct oplock4_state *state = tevent_req_callback_data(
3884 req, struct oplock4_state);
3885 NTSTATUS status;
3887 status = cli_open_recv(req, state->fnum2);
3888 if (!NT_STATUS_IS_OK(status)) {
3889 printf("cli_open_recv returned %s\n", nt_errstr(status));
3890 *state->fnum2 = 0xffff;
3895 Test delete on close semantics.
3897 static bool run_deletetest(int dummy)
3899 struct cli_state *cli1 = NULL;
3900 struct cli_state *cli2 = NULL;
3901 const char *fname = "\\delete.file";
3902 uint16_t fnum1 = (uint16_t)-1;
3903 uint16_t fnum2 = (uint16_t)-1;
3904 bool correct = True;
3905 NTSTATUS status;
3907 printf("starting delete test\n");
3909 if (!torture_open_connection(&cli1, 0)) {
3910 return False;
3913 cli_sockopt(cli1, sockops);
3915 /* Test 1 - this should delete the file on close. */
3917 cli_setatr(cli1, fname, 0, 0);
3918 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3920 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
3921 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
3922 FILE_DELETE_ON_CLOSE, 0, &fnum1);
3923 if (!NT_STATUS_IS_OK(status)) {
3924 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
3925 correct = False;
3926 goto fail;
3929 status = cli_close(cli1, fnum1);
3930 if (!NT_STATUS_IS_OK(status)) {
3931 printf("[1] close failed (%s)\n", nt_errstr(status));
3932 correct = False;
3933 goto fail;
3936 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1))) {
3937 printf("[1] open of %s succeeded (should fail)\n", fname);
3938 correct = False;
3939 goto fail;
3942 printf("first delete on close test succeeded.\n");
3944 /* Test 2 - this should delete the file on close. */
3946 cli_setatr(cli1, fname, 0, 0);
3947 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3949 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3950 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
3951 FILE_OVERWRITE_IF, 0, 0, &fnum1);
3952 if (!NT_STATUS_IS_OK(status)) {
3953 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
3954 correct = False;
3955 goto fail;
3958 status = cli_nt_delete_on_close(cli1, fnum1, true);
3959 if (!NT_STATUS_IS_OK(status)) {
3960 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
3961 correct = False;
3962 goto fail;
3965 status = cli_close(cli1, fnum1);
3966 if (!NT_STATUS_IS_OK(status)) {
3967 printf("[2] close failed (%s)\n", nt_errstr(status));
3968 correct = False;
3969 goto fail;
3972 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3973 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
3974 status = cli_close(cli1, fnum1);
3975 if (!NT_STATUS_IS_OK(status)) {
3976 printf("[2] close failed (%s)\n", nt_errstr(status));
3977 correct = False;
3978 goto fail;
3980 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3981 } else
3982 printf("second delete on close test succeeded.\n");
3984 /* Test 3 - ... */
3985 cli_setatr(cli1, fname, 0, 0);
3986 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3988 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3989 FILE_ATTRIBUTE_NORMAL,
3990 FILE_SHARE_READ|FILE_SHARE_WRITE,
3991 FILE_OVERWRITE_IF, 0, 0, &fnum1);
3992 if (!NT_STATUS_IS_OK(status)) {
3993 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
3994 correct = False;
3995 goto fail;
3998 /* This should fail with a sharing violation - open for delete is only compatible
3999 with SHARE_DELETE. */
4001 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4002 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, 0, &fnum2))) {
4003 printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
4004 correct = False;
4005 goto fail;
4008 /* This should succeed. */
4009 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4010 FILE_ATTRIBUTE_NORMAL,
4011 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4012 FILE_OPEN, 0, 0, &fnum2);
4013 if (!NT_STATUS_IS_OK(status)) {
4014 printf("[3] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
4015 correct = False;
4016 goto fail;
4019 status = cli_nt_delete_on_close(cli1, fnum1, true);
4020 if (!NT_STATUS_IS_OK(status)) {
4021 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
4022 correct = False;
4023 goto fail;
4026 status = cli_close(cli1, fnum1);
4027 if (!NT_STATUS_IS_OK(status)) {
4028 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
4029 correct = False;
4030 goto fail;
4033 status = cli_close(cli1, fnum2);
4034 if (!NT_STATUS_IS_OK(status)) {
4035 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
4036 correct = False;
4037 goto fail;
4040 /* This should fail - file should no longer be there. */
4042 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
4043 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
4044 status = cli_close(cli1, fnum1);
4045 if (!NT_STATUS_IS_OK(status)) {
4046 printf("[3] close failed (%s)\n", nt_errstr(status));
4048 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4049 correct = False;
4050 goto fail;
4051 } else
4052 printf("third delete on close test succeeded.\n");
4054 /* Test 4 ... */
4055 cli_setatr(cli1, fname, 0, 0);
4056 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4058 status = cli_ntcreate(cli1, fname, 0,
4059 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4060 FILE_ATTRIBUTE_NORMAL,
4061 FILE_SHARE_READ|FILE_SHARE_WRITE,
4062 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4063 if (!NT_STATUS_IS_OK(status)) {
4064 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
4065 correct = False;
4066 goto fail;
4069 /* This should succeed. */
4070 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4071 FILE_ATTRIBUTE_NORMAL,
4072 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4073 FILE_OPEN, 0, 0, &fnum2);
4074 if (!NT_STATUS_IS_OK(status)) {
4075 printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
4076 correct = False;
4077 goto fail;
4080 status = cli_close(cli1, fnum2);
4081 if (!NT_STATUS_IS_OK(status)) {
4082 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
4083 correct = False;
4084 goto fail;
4087 status = cli_nt_delete_on_close(cli1, fnum1, true);
4088 if (!NT_STATUS_IS_OK(status)) {
4089 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
4090 correct = False;
4091 goto fail;
4094 /* This should fail - no more opens once delete on close set. */
4095 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4096 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4097 FILE_OPEN, 0, 0, &fnum2))) {
4098 printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
4099 correct = False;
4100 goto fail;
4101 } else
4102 printf("fourth delete on close test succeeded.\n");
4104 status = cli_close(cli1, fnum1);
4105 if (!NT_STATUS_IS_OK(status)) {
4106 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
4107 correct = False;
4108 goto fail;
4111 /* Test 5 ... */
4112 cli_setatr(cli1, fname, 0, 0);
4113 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4115 status = cli_open(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
4116 if (!NT_STATUS_IS_OK(status)) {
4117 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4118 correct = False;
4119 goto fail;
4122 /* This should fail - only allowed on NT opens with DELETE access. */
4124 if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4125 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
4126 correct = False;
4127 goto fail;
4130 status = cli_close(cli1, fnum1);
4131 if (!NT_STATUS_IS_OK(status)) {
4132 printf("[5] close - 2 failed (%s)\n", nt_errstr(status));
4133 correct = False;
4134 goto fail;
4137 printf("fifth delete on close test succeeded.\n");
4139 /* Test 6 ... */
4140 cli_setatr(cli1, fname, 0, 0);
4141 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4143 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4144 FILE_ATTRIBUTE_NORMAL,
4145 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4146 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4147 if (!NT_STATUS_IS_OK(status)) {
4148 printf("[6] open of %s failed (%s)\n", fname,
4149 nt_errstr(status));
4150 correct = False;
4151 goto fail;
4154 /* This should fail - only allowed on NT opens with DELETE access. */
4156 if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4157 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
4158 correct = False;
4159 goto fail;
4162 status = cli_close(cli1, fnum1);
4163 if (!NT_STATUS_IS_OK(status)) {
4164 printf("[6] close - 2 failed (%s)\n", nt_errstr(status));
4165 correct = False;
4166 goto fail;
4169 printf("sixth delete on close test succeeded.\n");
4171 /* Test 7 ... */
4172 cli_setatr(cli1, fname, 0, 0);
4173 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4175 status = cli_ntcreate(cli1, fname, 0,
4176 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4177 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
4178 0, 0, &fnum1);
4179 if (!NT_STATUS_IS_OK(status)) {
4180 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4181 correct = False;
4182 goto fail;
4185 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4186 printf("[7] setting delete_on_close on file failed !\n");
4187 correct = False;
4188 goto fail;
4191 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, false))) {
4192 printf("[7] unsetting delete_on_close on file failed !\n");
4193 correct = False;
4194 goto fail;
4197 status = cli_close(cli1, fnum1);
4198 if (!NT_STATUS_IS_OK(status)) {
4199 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4200 correct = False;
4201 goto fail;
4204 /* This next open should succeed - we reset the flag. */
4205 status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4206 if (!NT_STATUS_IS_OK(status)) {
4207 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4208 correct = False;
4209 goto fail;
4212 status = cli_close(cli1, fnum1);
4213 if (!NT_STATUS_IS_OK(status)) {
4214 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4215 correct = False;
4216 goto fail;
4219 printf("seventh delete on close test succeeded.\n");
4221 /* Test 7 ... */
4222 cli_setatr(cli1, fname, 0, 0);
4223 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4225 if (!torture_open_connection(&cli2, 1)) {
4226 printf("[8] failed to open second connection.\n");
4227 correct = False;
4228 goto fail;
4231 cli_sockopt(cli1, sockops);
4233 status = cli_ntcreate(cli1, fname, 0,
4234 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4235 FILE_ATTRIBUTE_NORMAL,
4236 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4237 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4238 if (!NT_STATUS_IS_OK(status)) {
4239 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4240 correct = False;
4241 goto fail;
4244 status = cli_ntcreate(cli2, fname, 0,
4245 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4246 FILE_ATTRIBUTE_NORMAL,
4247 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4248 FILE_OPEN, 0, 0, &fnum2);
4249 if (!NT_STATUS_IS_OK(status)) {
4250 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4251 correct = False;
4252 goto fail;
4255 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4256 printf("[8] setting delete_on_close on file failed !\n");
4257 correct = False;
4258 goto fail;
4261 status = cli_close(cli1, fnum1);
4262 if (!NT_STATUS_IS_OK(status)) {
4263 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
4264 correct = False;
4265 goto fail;
4268 status = cli_close(cli2, fnum2);
4269 if (!NT_STATUS_IS_OK(status)) {
4270 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
4271 correct = False;
4272 goto fail;
4275 /* This should fail.. */
4276 status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4277 if (NT_STATUS_IS_OK(status)) {
4278 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
4279 goto fail;
4280 correct = False;
4281 } else
4282 printf("eighth delete on close test succeeded.\n");
4284 /* This should fail - we need to set DELETE_ACCESS. */
4285 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0,FILE_READ_DATA|FILE_WRITE_DATA,
4286 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE, 0, &fnum1))) {
4287 printf("[9] open of %s succeeded should have failed!\n", fname);
4288 correct = False;
4289 goto fail;
4292 printf("ninth delete on close test succeeded.\n");
4294 status = cli_ntcreate(cli1, fname, 0,
4295 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4296 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4297 FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
4298 0, &fnum1);
4299 if (!NT_STATUS_IS_OK(status)) {
4300 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
4301 correct = False;
4302 goto fail;
4305 /* This should delete the file. */
4306 status = cli_close(cli1, fnum1);
4307 if (!NT_STATUS_IS_OK(status)) {
4308 printf("[10] close failed (%s)\n", nt_errstr(status));
4309 correct = False;
4310 goto fail;
4313 /* This should fail.. */
4314 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
4315 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
4316 goto fail;
4317 correct = False;
4318 } else
4319 printf("tenth delete on close test succeeded.\n");
4321 cli_setatr(cli1, fname, 0, 0);
4322 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4324 /* What error do we get when attempting to open a read-only file with
4325 delete access ? */
4327 /* Create a readonly file. */
4328 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4329 FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
4330 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4331 if (!NT_STATUS_IS_OK(status)) {
4332 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
4333 correct = False;
4334 goto fail;
4337 status = cli_close(cli1, fnum1);
4338 if (!NT_STATUS_IS_OK(status)) {
4339 printf("[11] close failed (%s)\n", nt_errstr(status));
4340 correct = False;
4341 goto fail;
4344 /* Now try open for delete access. */
4345 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES|DELETE_ACCESS,
4346 0, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4347 FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4348 printf("[11] open of %s succeeded should have been denied with ACCESS_DENIED!\n", fname);
4349 cli_close(cli1, fnum1);
4350 goto fail;
4351 correct = False;
4352 } else {
4353 NTSTATUS nterr = cli_nt_error(cli1);
4354 if (!NT_STATUS_EQUAL(nterr,NT_STATUS_ACCESS_DENIED)) {
4355 printf("[11] open of %s should have been denied with ACCESS_DENIED! Got error %s\n", fname, nt_errstr(nterr));
4356 goto fail;
4357 correct = False;
4358 } else {
4359 printf("eleventh delete on close test succeeded.\n");
4363 printf("finished delete test\n");
4365 fail:
4366 /* FIXME: This will crash if we aborted before cli2 got
4367 * intialized, because these functions don't handle
4368 * uninitialized connections. */
4370 if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
4371 if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
4372 cli_setatr(cli1, fname, 0, 0);
4373 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4375 if (cli1 && !torture_close_connection(cli1)) {
4376 correct = False;
4378 if (cli2 && !torture_close_connection(cli2)) {
4379 correct = False;
4381 return correct;
4384 static bool run_deletetest_ln(int dummy)
4386 struct cli_state *cli;
4387 const char *fname = "\\delete1";
4388 const char *fname_ln = "\\delete1_ln";
4389 uint16_t fnum;
4390 uint16_t fnum1;
4391 NTSTATUS status;
4392 bool correct = true;
4393 time_t t;
4395 printf("starting deletetest-ln\n");
4397 if (!torture_open_connection(&cli, 0)) {
4398 return false;
4401 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4402 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4404 cli_sockopt(cli, sockops);
4406 /* Create the file. */
4407 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
4408 if (!NT_STATUS_IS_OK(status)) {
4409 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4410 return false;
4413 status = cli_close(cli, fnum);
4414 if (!NT_STATUS_IS_OK(status)) {
4415 printf("close1 failed (%s)\n", nt_errstr(status));
4416 return false;
4419 /* Now create a hardlink. */
4420 status = cli_nt_hardlink(cli, fname, fname_ln);
4421 if (!NT_STATUS_IS_OK(status)) {
4422 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4423 return false;
4426 /* Open the original file. */
4427 status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
4428 FILE_ATTRIBUTE_NORMAL,
4429 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4430 FILE_OPEN_IF, 0, 0, &fnum);
4431 if (!NT_STATUS_IS_OK(status)) {
4432 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
4433 return false;
4436 /* Unlink the hard link path. */
4437 status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
4438 FILE_ATTRIBUTE_NORMAL,
4439 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4440 FILE_OPEN_IF, 0, 0, &fnum1);
4441 if (!NT_STATUS_IS_OK(status)) {
4442 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
4443 return false;
4445 status = cli_nt_delete_on_close(cli, fnum1, true);
4446 if (!NT_STATUS_IS_OK(status)) {
4447 d_printf("(%s) failed to set delete_on_close %s: %s\n",
4448 __location__, fname_ln, nt_errstr(status));
4449 return false;
4452 status = cli_close(cli, fnum1);
4453 if (!NT_STATUS_IS_OK(status)) {
4454 printf("close %s failed (%s)\n",
4455 fname_ln, nt_errstr(status));
4456 return false;
4459 status = cli_close(cli, fnum);
4460 if (!NT_STATUS_IS_OK(status)) {
4461 printf("close %s failed (%s)\n",
4462 fname, nt_errstr(status));
4463 return false;
4466 /* Ensure the original file is still there. */
4467 status = cli_getatr(cli, fname, NULL, NULL, &t);
4468 if (!NT_STATUS_IS_OK(status)) {
4469 printf("%s getatr on file %s failed (%s)\n",
4470 __location__,
4471 fname,
4472 nt_errstr(status));
4473 correct = False;
4476 /* Ensure the link path is gone. */
4477 status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
4478 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4479 printf("%s, getatr for file %s returned wrong error code %s "
4480 "- should have been deleted\n",
4481 __location__,
4482 fname_ln, nt_errstr(status));
4483 correct = False;
4486 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4487 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4489 if (!torture_close_connection(cli)) {
4490 correct = false;
4493 printf("finished deletetest-ln\n");
4495 return correct;
4499 print out server properties
4501 static bool run_properties(int dummy)
4503 struct cli_state *cli;
4504 bool correct = True;
4506 printf("starting properties test\n");
4508 ZERO_STRUCT(cli);
4510 if (!torture_open_connection(&cli, 0)) {
4511 return False;
4514 cli_sockopt(cli, sockops);
4516 d_printf("Capabilities 0x%08x\n", cli_state_capabilities(cli));
4518 if (!torture_close_connection(cli)) {
4519 correct = False;
4522 return correct;
4527 /* FIRST_DESIRED_ACCESS 0xf019f */
4528 #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
4529 FILE_READ_EA| /* 0xf */ \
4530 FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
4531 FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
4532 DELETE_ACCESS|READ_CONTROL_ACCESS|\
4533 WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
4534 /* SECOND_DESIRED_ACCESS 0xe0080 */
4535 #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
4536 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4537 WRITE_OWNER_ACCESS /* 0xe0000 */
4539 #if 0
4540 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
4541 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4542 FILE_READ_DATA|\
4543 WRITE_OWNER_ACCESS /* */
4544 #endif
4547 Test ntcreate calls made by xcopy
4549 static bool run_xcopy(int dummy)
4551 static struct cli_state *cli1;
4552 const char *fname = "\\test.txt";
4553 bool correct = True;
4554 uint16_t fnum1, fnum2;
4555 NTSTATUS status;
4557 printf("starting xcopy test\n");
4559 if (!torture_open_connection(&cli1, 0)) {
4560 return False;
4563 status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
4564 FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
4565 FILE_OVERWRITE_IF, 0x4044, 0, &fnum1);
4566 if (!NT_STATUS_IS_OK(status)) {
4567 printf("First open failed - %s\n", nt_errstr(status));
4568 return False;
4571 status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
4572 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4573 FILE_OPEN, 0x200000, 0, &fnum2);
4574 if (!NT_STATUS_IS_OK(status)) {
4575 printf("second open failed - %s\n", nt_errstr(status));
4576 return False;
4579 if (!torture_close_connection(cli1)) {
4580 correct = False;
4583 return correct;
4587 Test rename on files open with share delete and no share delete.
4589 static bool run_rename(int dummy)
4591 static struct cli_state *cli1;
4592 const char *fname = "\\test.txt";
4593 const char *fname1 = "\\test1.txt";
4594 bool correct = True;
4595 uint16_t fnum1;
4596 uint16_t attr;
4597 NTSTATUS status;
4599 printf("starting rename test\n");
4601 if (!torture_open_connection(&cli1, 0)) {
4602 return False;
4605 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4606 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4608 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4609 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
4610 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4611 if (!NT_STATUS_IS_OK(status)) {
4612 printf("First open failed - %s\n", nt_errstr(status));
4613 return False;
4616 status = cli_rename(cli1, fname, fname1);
4617 if (!NT_STATUS_IS_OK(status)) {
4618 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
4619 } else {
4620 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
4621 correct = False;
4624 status = cli_close(cli1, fnum1);
4625 if (!NT_STATUS_IS_OK(status)) {
4626 printf("close - 1 failed (%s)\n", nt_errstr(status));
4627 return False;
4630 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4631 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4632 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4633 #if 0
4634 FILE_SHARE_DELETE|FILE_SHARE_NONE,
4635 #else
4636 FILE_SHARE_DELETE|FILE_SHARE_READ,
4637 #endif
4638 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4639 if (!NT_STATUS_IS_OK(status)) {
4640 printf("Second open failed - %s\n", nt_errstr(status));
4641 return False;
4644 status = cli_rename(cli1, fname, fname1);
4645 if (!NT_STATUS_IS_OK(status)) {
4646 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
4647 correct = False;
4648 } else {
4649 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
4652 status = cli_close(cli1, fnum1);
4653 if (!NT_STATUS_IS_OK(status)) {
4654 printf("close - 2 failed (%s)\n", nt_errstr(status));
4655 return False;
4658 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4659 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4661 status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
4662 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4663 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4664 if (!NT_STATUS_IS_OK(status)) {
4665 printf("Third open failed - %s\n", nt_errstr(status));
4666 return False;
4670 #if 0
4672 uint16_t fnum2;
4674 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
4675 FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4676 printf("Fourth open failed - %s\n", cli_errstr(cli1));
4677 return False;
4679 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum2, true))) {
4680 printf("[8] setting delete_on_close on file failed !\n");
4681 return False;
4684 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
4685 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
4686 return False;
4689 #endif
4691 status = cli_rename(cli1, fname, fname1);
4692 if (!NT_STATUS_IS_OK(status)) {
4693 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
4694 correct = False;
4695 } else {
4696 printf("Third rename succeeded (SHARE_NONE)\n");
4699 status = cli_close(cli1, fnum1);
4700 if (!NT_STATUS_IS_OK(status)) {
4701 printf("close - 3 failed (%s)\n", nt_errstr(status));
4702 return False;
4705 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4706 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4708 /*----*/
4710 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4711 FILE_ATTRIBUTE_NORMAL,
4712 FILE_SHARE_READ | FILE_SHARE_WRITE,
4713 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4714 if (!NT_STATUS_IS_OK(status)) {
4715 printf("Fourth open failed - %s\n", nt_errstr(status));
4716 return False;
4719 status = cli_rename(cli1, fname, fname1);
4720 if (!NT_STATUS_IS_OK(status)) {
4721 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
4722 } else {
4723 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
4724 correct = False;
4727 status = cli_close(cli1, fnum1);
4728 if (!NT_STATUS_IS_OK(status)) {
4729 printf("close - 4 failed (%s)\n", nt_errstr(status));
4730 return False;
4733 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4734 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4736 /*--*/
4738 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4739 FILE_ATTRIBUTE_NORMAL,
4740 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4741 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4742 if (!NT_STATUS_IS_OK(status)) {
4743 printf("Fifth open failed - %s\n", nt_errstr(status));
4744 return False;
4747 status = cli_rename(cli1, fname, fname1);
4748 if (!NT_STATUS_IS_OK(status)) {
4749 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
4750 correct = False;
4751 } else {
4752 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
4756 * Now check if the first name still exists ...
4759 /* if (!NT_STATUS_OP(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4760 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4761 printf("Opening original file after rename of open file fails: %s\n",
4762 cli_errstr(cli1));
4764 else {
4765 printf("Opening original file after rename of open file works ...\n");
4766 (void)cli_close(cli1, fnum2);
4767 } */
4769 /*--*/
4770 status = cli_close(cli1, fnum1);
4771 if (!NT_STATUS_IS_OK(status)) {
4772 printf("close - 5 failed (%s)\n", nt_errstr(status));
4773 return False;
4776 /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
4777 status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
4778 if (!NT_STATUS_IS_OK(status)) {
4779 printf("getatr on file %s failed - %s ! \n",
4780 fname1, nt_errstr(status));
4781 correct = False;
4782 } else {
4783 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
4784 printf("Renamed file %s has wrong attr 0x%x "
4785 "(should be 0x%x)\n",
4786 fname1,
4787 attr,
4788 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
4789 correct = False;
4790 } else {
4791 printf("Renamed file %s has archive bit set\n", fname1);
4795 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4796 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4798 if (!torture_close_connection(cli1)) {
4799 correct = False;
4802 return correct;
4805 static bool run_pipe_number(int dummy)
4807 struct cli_state *cli1;
4808 const char *pipe_name = "\\SPOOLSS";
4809 uint16_t fnum;
4810 int num_pipes = 0;
4811 NTSTATUS status;
4813 printf("starting pipenumber test\n");
4814 if (!torture_open_connection(&cli1, 0)) {
4815 return False;
4818 cli_sockopt(cli1, sockops);
4819 while(1) {
4820 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
4821 FILE_ATTRIBUTE_NORMAL,
4822 FILE_SHARE_READ|FILE_SHARE_WRITE,
4823 FILE_OPEN_IF, 0, 0, &fnum);
4824 if (!NT_STATUS_IS_OK(status)) {
4825 printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
4826 break;
4828 num_pipes++;
4829 printf("\r%6d", num_pipes);
4832 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
4833 torture_close_connection(cli1);
4834 return True;
4838 Test open mode returns on read-only files.
4840 static bool run_opentest(int dummy)
4842 static struct cli_state *cli1;
4843 static struct cli_state *cli2;
4844 const char *fname = "\\readonly.file";
4845 uint16_t fnum1, fnum2;
4846 char buf[20];
4847 SMB_OFF_T fsize;
4848 bool correct = True;
4849 char *tmp_path;
4850 NTSTATUS status;
4852 printf("starting open test\n");
4854 if (!torture_open_connection(&cli1, 0)) {
4855 return False;
4858 cli_setatr(cli1, fname, 0, 0);
4859 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4861 cli_sockopt(cli1, sockops);
4863 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4864 if (!NT_STATUS_IS_OK(status)) {
4865 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4866 return False;
4869 status = cli_close(cli1, fnum1);
4870 if (!NT_STATUS_IS_OK(status)) {
4871 printf("close2 failed (%s)\n", nt_errstr(status));
4872 return False;
4875 status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
4876 if (!NT_STATUS_IS_OK(status)) {
4877 printf("cli_setatr failed (%s)\n", nt_errstr(status));
4878 return False;
4881 status = cli_open(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4882 if (!NT_STATUS_IS_OK(status)) {
4883 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4884 return False;
4887 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
4888 status = cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4890 if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
4891 NT_STATUS_ACCESS_DENIED)) {
4892 printf("correct error code ERRDOS/ERRnoaccess returned\n");
4895 printf("finished open test 1\n");
4897 cli_close(cli1, fnum1);
4899 /* Now try not readonly and ensure ERRbadshare is returned. */
4901 cli_setatr(cli1, fname, 0, 0);
4903 status = cli_open(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4904 if (!NT_STATUS_IS_OK(status)) {
4905 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4906 return False;
4909 /* This will fail - but the error should be ERRshare. */
4910 status = cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4912 if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
4913 NT_STATUS_SHARING_VIOLATION)) {
4914 printf("correct error code ERRDOS/ERRbadshare returned\n");
4917 status = cli_close(cli1, fnum1);
4918 if (!NT_STATUS_IS_OK(status)) {
4919 printf("close2 failed (%s)\n", nt_errstr(status));
4920 return False;
4923 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4925 printf("finished open test 2\n");
4927 /* Test truncate open disposition on file opened for read. */
4928 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4929 if (!NT_STATUS_IS_OK(status)) {
4930 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
4931 return False;
4934 /* write 20 bytes. */
4936 memset(buf, '\0', 20);
4938 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
4939 if (!NT_STATUS_IS_OK(status)) {
4940 printf("write failed (%s)\n", nt_errstr(status));
4941 correct = False;
4944 status = cli_close(cli1, fnum1);
4945 if (!NT_STATUS_IS_OK(status)) {
4946 printf("(3) close1 failed (%s)\n", nt_errstr(status));
4947 return False;
4950 /* Ensure size == 20. */
4951 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
4952 if (!NT_STATUS_IS_OK(status)) {
4953 printf("(3) getatr failed (%s)\n", nt_errstr(status));
4954 return False;
4957 if (fsize != 20) {
4958 printf("(3) file size != 20\n");
4959 return False;
4962 /* Now test if we can truncate a file opened for readonly. */
4963 status = cli_open(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
4964 if (!NT_STATUS_IS_OK(status)) {
4965 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
4966 return False;
4969 status = cli_close(cli1, fnum1);
4970 if (!NT_STATUS_IS_OK(status)) {
4971 printf("close2 failed (%s)\n", nt_errstr(status));
4972 return False;
4975 /* Ensure size == 0. */
4976 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
4977 if (!NT_STATUS_IS_OK(status)) {
4978 printf("(3) getatr failed (%s)\n", nt_errstr(status));
4979 return False;
4982 if (fsize != 0) {
4983 printf("(3) file size != 0\n");
4984 return False;
4986 printf("finished open test 3\n");
4988 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4990 printf("Do ctemp tests\n");
4991 status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
4992 if (!NT_STATUS_IS_OK(status)) {
4993 printf("ctemp failed (%s)\n", nt_errstr(status));
4994 return False;
4997 printf("ctemp gave path %s\n", tmp_path);
4998 status = cli_close(cli1, fnum1);
4999 if (!NT_STATUS_IS_OK(status)) {
5000 printf("close of temp failed (%s)\n", nt_errstr(status));
5003 status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5004 if (!NT_STATUS_IS_OK(status)) {
5005 printf("unlink of temp failed (%s)\n", nt_errstr(status));
5008 /* Test the non-io opens... */
5010 if (!torture_open_connection(&cli2, 1)) {
5011 return False;
5014 cli_setatr(cli2, fname, 0, 0);
5015 cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5017 cli_sockopt(cli2, sockops);
5019 printf("TEST #1 testing 2 non-io opens (no delete)\n");
5020 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5021 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5022 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5023 if (!NT_STATUS_IS_OK(status)) {
5024 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5025 return False;
5028 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5029 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5030 FILE_OPEN_IF, 0, 0, &fnum2);
5031 if (!NT_STATUS_IS_OK(status)) {
5032 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5033 return False;
5036 status = cli_close(cli1, fnum1);
5037 if (!NT_STATUS_IS_OK(status)) {
5038 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5039 return False;
5042 status = cli_close(cli2, fnum2);
5043 if (!NT_STATUS_IS_OK(status)) {
5044 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5045 return False;
5048 printf("non-io open test #1 passed.\n");
5050 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5052 printf("TEST #2 testing 2 non-io opens (first with delete)\n");
5054 status = cli_ntcreate(cli1, fname, 0,
5055 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5056 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5057 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5058 if (!NT_STATUS_IS_OK(status)) {
5059 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5060 return False;
5063 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5064 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5065 FILE_OPEN_IF, 0, 0, &fnum2);
5066 if (!NT_STATUS_IS_OK(status)) {
5067 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5068 return False;
5071 status = cli_close(cli1, fnum1);
5072 if (!NT_STATUS_IS_OK(status)) {
5073 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5074 return False;
5077 status = cli_close(cli2, fnum2);
5078 if (!NT_STATUS_IS_OK(status)) {
5079 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5080 return False;
5083 printf("non-io open test #2 passed.\n");
5085 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5087 printf("TEST #3 testing 2 non-io opens (second with delete)\n");
5089 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5090 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5091 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5092 if (!NT_STATUS_IS_OK(status)) {
5093 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5094 return False;
5097 status = cli_ntcreate(cli2, fname, 0,
5098 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5099 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5100 FILE_OPEN_IF, 0, 0, &fnum2);
5101 if (!NT_STATUS_IS_OK(status)) {
5102 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5103 return False;
5106 status = cli_close(cli1, fnum1);
5107 if (!NT_STATUS_IS_OK(status)) {
5108 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5109 return False;
5112 status = cli_close(cli2, fnum2);
5113 if (!NT_STATUS_IS_OK(status)) {
5114 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5115 return False;
5118 printf("non-io open test #3 passed.\n");
5120 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5122 printf("TEST #4 testing 2 non-io opens (both with delete)\n");
5124 status = cli_ntcreate(cli1, fname, 0,
5125 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5126 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5127 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5128 if (!NT_STATUS_IS_OK(status)) {
5129 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5130 return False;
5133 status = cli_ntcreate(cli2, fname, 0,
5134 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5135 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5136 FILE_OPEN_IF, 0, 0, &fnum2);
5137 if (NT_STATUS_IS_OK(status)) {
5138 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5139 return False;
5142 printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5144 status = cli_close(cli1, fnum1);
5145 if (!NT_STATUS_IS_OK(status)) {
5146 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5147 return False;
5150 printf("non-io open test #4 passed.\n");
5152 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5154 printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
5156 status = cli_ntcreate(cli1, fname, 0,
5157 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5158 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5159 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5160 if (!NT_STATUS_IS_OK(status)) {
5161 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5162 return False;
5165 status = cli_ntcreate(cli2, fname, 0,
5166 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5167 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5168 FILE_OPEN_IF, 0, 0, &fnum2);
5169 if (!NT_STATUS_IS_OK(status)) {
5170 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5171 return False;
5174 status = cli_close(cli1, fnum1);
5175 if (!NT_STATUS_IS_OK(status)) {
5176 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5177 return False;
5180 status = cli_close(cli2, fnum2);
5181 if (!NT_STATUS_IS_OK(status)) {
5182 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5183 return False;
5186 printf("non-io open test #5 passed.\n");
5188 printf("TEST #6 testing 1 non-io open, one io open\n");
5190 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5192 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5193 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5194 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5195 if (!NT_STATUS_IS_OK(status)) {
5196 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5197 return False;
5200 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5201 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
5202 FILE_OPEN_IF, 0, 0, &fnum2);
5203 if (!NT_STATUS_IS_OK(status)) {
5204 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5205 return False;
5208 status = cli_close(cli1, fnum1);
5209 if (!NT_STATUS_IS_OK(status)) {
5210 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5211 return False;
5214 status = cli_close(cli2, fnum2);
5215 if (!NT_STATUS_IS_OK(status)) {
5216 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5217 return False;
5220 printf("non-io open test #6 passed.\n");
5222 printf("TEST #7 testing 1 non-io open, one io open with delete\n");
5224 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5226 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5227 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5228 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5229 if (!NT_STATUS_IS_OK(status)) {
5230 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5231 return False;
5234 status = cli_ntcreate(cli2, fname, 0,
5235 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5236 FILE_ATTRIBUTE_NORMAL,
5237 FILE_SHARE_READ|FILE_SHARE_DELETE,
5238 FILE_OPEN_IF, 0, 0, &fnum2);
5239 if (NT_STATUS_IS_OK(status)) {
5240 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5241 return False;
5244 printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5246 status = cli_close(cli1, fnum1);
5247 if (!NT_STATUS_IS_OK(status)) {
5248 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5249 return False;
5252 printf("non-io open test #7 passed.\n");
5254 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5256 printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
5257 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
5258 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5259 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5260 if (!NT_STATUS_IS_OK(status)) {
5261 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
5262 correct = false;
5263 goto out;
5266 /* Write to ensure we have to update the file time. */
5267 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5268 NULL);
5269 if (!NT_STATUS_IS_OK(status)) {
5270 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
5271 correct = false;
5272 goto out;
5275 status = cli_close(cli1, fnum1);
5276 if (!NT_STATUS_IS_OK(status)) {
5277 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
5278 correct = false;
5281 out:
5283 if (!torture_close_connection(cli1)) {
5284 correct = False;
5286 if (!torture_close_connection(cli2)) {
5287 correct = False;
5290 return correct;
5293 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
5295 uint16 major, minor;
5296 uint32 caplow, caphigh;
5297 NTSTATUS status;
5299 if (!SERVER_HAS_UNIX_CIFS(cli)) {
5300 printf("Server doesn't support UNIX CIFS extensions.\n");
5301 return NT_STATUS_NOT_SUPPORTED;
5304 status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
5305 &caphigh);
5306 if (!NT_STATUS_IS_OK(status)) {
5307 printf("Server didn't return UNIX CIFS extensions: %s\n",
5308 nt_errstr(status));
5309 return status;
5312 status = cli_set_unix_extensions_capabilities(cli, major, minor,
5313 caplow, caphigh);
5314 if (!NT_STATUS_IS_OK(status)) {
5315 printf("Server doesn't support setting UNIX CIFS extensions: "
5316 "%s.\n", nt_errstr(status));
5317 return status;
5320 return NT_STATUS_OK;
5324 Test POSIX open /mkdir calls.
5326 static bool run_simple_posix_open_test(int dummy)
5328 static struct cli_state *cli1;
5329 const char *fname = "posix:file";
5330 const char *hname = "posix:hlink";
5331 const char *sname = "posix:symlink";
5332 const char *dname = "posix:dir";
5333 char buf[10];
5334 char namebuf[11];
5335 uint16_t fnum1 = (uint16_t)-1;
5336 SMB_STRUCT_STAT sbuf;
5337 bool correct = false;
5338 NTSTATUS status;
5339 size_t nread;
5341 printf("Starting simple POSIX open test\n");
5343 if (!torture_open_connection(&cli1, 0)) {
5344 return false;
5347 cli_sockopt(cli1, sockops);
5349 status = torture_setup_unix_extensions(cli1);
5350 if (!NT_STATUS_IS_OK(status)) {
5351 return false;
5354 cli_setatr(cli1, fname, 0, 0);
5355 cli_posix_unlink(cli1, fname);
5356 cli_setatr(cli1, dname, 0, 0);
5357 cli_posix_rmdir(cli1, dname);
5358 cli_setatr(cli1, hname, 0, 0);
5359 cli_posix_unlink(cli1, hname);
5360 cli_setatr(cli1, sname, 0, 0);
5361 cli_posix_unlink(cli1, sname);
5363 /* Create a directory. */
5364 status = cli_posix_mkdir(cli1, dname, 0777);
5365 if (!NT_STATUS_IS_OK(status)) {
5366 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
5367 goto out;
5370 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5371 0600, &fnum1);
5372 if (!NT_STATUS_IS_OK(status)) {
5373 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5374 goto out;
5377 /* Test ftruncate - set file size. */
5378 status = cli_ftruncate(cli1, fnum1, 1000);
5379 if (!NT_STATUS_IS_OK(status)) {
5380 printf("ftruncate failed (%s)\n", nt_errstr(status));
5381 goto out;
5384 /* Ensure st_size == 1000 */
5385 status = cli_posix_stat(cli1, fname, &sbuf);
5386 if (!NT_STATUS_IS_OK(status)) {
5387 printf("stat failed (%s)\n", nt_errstr(status));
5388 goto out;
5391 if (sbuf.st_ex_size != 1000) {
5392 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5393 goto out;
5396 /* Test ftruncate - set file size back to zero. */
5397 status = cli_ftruncate(cli1, fnum1, 0);
5398 if (!NT_STATUS_IS_OK(status)) {
5399 printf("ftruncate failed (%s)\n", nt_errstr(status));
5400 goto out;
5403 status = cli_close(cli1, fnum1);
5404 if (!NT_STATUS_IS_OK(status)) {
5405 printf("close failed (%s)\n", nt_errstr(status));
5406 goto out;
5409 /* Now open the file again for read only. */
5410 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5411 if (!NT_STATUS_IS_OK(status)) {
5412 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
5413 goto out;
5416 /* Now unlink while open. */
5417 status = cli_posix_unlink(cli1, fname);
5418 if (!NT_STATUS_IS_OK(status)) {
5419 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5420 goto out;
5423 status = cli_close(cli1, fnum1);
5424 if (!NT_STATUS_IS_OK(status)) {
5425 printf("close(2) failed (%s)\n", nt_errstr(status));
5426 goto out;
5429 /* Ensure the file has gone. */
5430 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5431 if (NT_STATUS_IS_OK(status)) {
5432 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
5433 goto out;
5436 /* Create again to test open with O_TRUNC. */
5437 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
5438 if (!NT_STATUS_IS_OK(status)) {
5439 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5440 goto out;
5443 /* Test ftruncate - set file size. */
5444 status = cli_ftruncate(cli1, fnum1, 1000);
5445 if (!NT_STATUS_IS_OK(status)) {
5446 printf("ftruncate failed (%s)\n", nt_errstr(status));
5447 goto out;
5450 /* Ensure st_size == 1000 */
5451 status = cli_posix_stat(cli1, fname, &sbuf);
5452 if (!NT_STATUS_IS_OK(status)) {
5453 printf("stat failed (%s)\n", nt_errstr(status));
5454 goto out;
5457 if (sbuf.st_ex_size != 1000) {
5458 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5459 goto out;
5462 status = cli_close(cli1, fnum1);
5463 if (!NT_STATUS_IS_OK(status)) {
5464 printf("close(2) failed (%s)\n", nt_errstr(status));
5465 goto out;
5468 /* Re-open with O_TRUNC. */
5469 status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
5470 if (!NT_STATUS_IS_OK(status)) {
5471 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5472 goto out;
5475 /* Ensure st_size == 0 */
5476 status = cli_posix_stat(cli1, fname, &sbuf);
5477 if (!NT_STATUS_IS_OK(status)) {
5478 printf("stat failed (%s)\n", nt_errstr(status));
5479 goto out;
5482 if (sbuf.st_ex_size != 0) {
5483 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
5484 goto out;
5487 status = cli_close(cli1, fnum1);
5488 if (!NT_STATUS_IS_OK(status)) {
5489 printf("close failed (%s)\n", nt_errstr(status));
5490 goto out;
5493 status = cli_posix_unlink(cli1, fname);
5494 if (!NT_STATUS_IS_OK(status)) {
5495 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5496 goto out;
5499 status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
5500 if (!NT_STATUS_IS_OK(status)) {
5501 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
5502 dname, nt_errstr(status));
5503 goto out;
5506 cli_close(cli1, fnum1);
5508 /* What happens when we try and POSIX open a directory for write ? */
5509 status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
5510 if (NT_STATUS_IS_OK(status)) {
5511 printf("POSIX open of directory %s succeeded, should have failed.\n", fname);
5512 goto out;
5513 } else {
5514 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
5515 NT_STATUS_FILE_IS_A_DIRECTORY)) {
5516 goto out;
5520 /* Create the file. */
5521 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5522 0600, &fnum1);
5523 if (!NT_STATUS_IS_OK(status)) {
5524 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5525 goto out;
5528 /* Write some data into it. */
5529 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5530 NULL);
5531 if (!NT_STATUS_IS_OK(status)) {
5532 printf("cli_write failed: %s\n", nt_errstr(status));
5533 goto out;
5536 cli_close(cli1, fnum1);
5538 /* Now create a hardlink. */
5539 status = cli_posix_hardlink(cli1, fname, hname);
5540 if (!NT_STATUS_IS_OK(status)) {
5541 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
5542 goto out;
5545 /* Now create a symlink. */
5546 status = cli_posix_symlink(cli1, fname, sname);
5547 if (!NT_STATUS_IS_OK(status)) {
5548 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
5549 goto out;
5552 /* Open the hardlink for read. */
5553 status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
5554 if (!NT_STATUS_IS_OK(status)) {
5555 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
5556 goto out;
5559 status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
5560 if (!NT_STATUS_IS_OK(status)) {
5561 printf("POSIX read of %s failed (%s)\n", hname,
5562 nt_errstr(status));
5563 goto out;
5564 } else if (nread != 10) {
5565 printf("POSIX read of %s failed. Received %ld, expected %d\n",
5566 hname, (unsigned long)nread, 10);
5567 goto out;
5570 if (memcmp(buf, "TEST DATA\n", 10)) {
5571 printf("invalid data read from hardlink\n");
5572 goto out;
5575 /* Do a POSIX lock/unlock. */
5576 status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
5577 if (!NT_STATUS_IS_OK(status)) {
5578 printf("POSIX lock failed %s\n", nt_errstr(status));
5579 goto out;
5582 /* Punch a hole in the locked area. */
5583 status = cli_posix_unlock(cli1, fnum1, 10, 80);
5584 if (!NT_STATUS_IS_OK(status)) {
5585 printf("POSIX unlock failed %s\n", nt_errstr(status));
5586 goto out;
5589 cli_close(cli1, fnum1);
5591 /* Open the symlink for read - this should fail. A POSIX
5592 client should not be doing opens on a symlink. */
5593 status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
5594 if (NT_STATUS_IS_OK(status)) {
5595 printf("POSIX open of %s succeeded (should have failed)\n", sname);
5596 goto out;
5597 } else {
5598 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
5599 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
5600 printf("POSIX open of %s should have failed "
5601 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
5602 "failed with %s instead.\n",
5603 sname, nt_errstr(status));
5604 goto out;
5608 status = cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf));
5609 if (!NT_STATUS_IS_OK(status)) {
5610 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
5611 goto out;
5614 if (strcmp(namebuf, fname) != 0) {
5615 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
5616 sname, fname, namebuf);
5617 goto out;
5620 status = cli_posix_rmdir(cli1, dname);
5621 if (!NT_STATUS_IS_OK(status)) {
5622 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
5623 goto out;
5626 printf("Simple POSIX open test passed\n");
5627 correct = true;
5629 out:
5631 if (fnum1 != (uint16_t)-1) {
5632 cli_close(cli1, fnum1);
5633 fnum1 = (uint16_t)-1;
5636 cli_setatr(cli1, sname, 0, 0);
5637 cli_posix_unlink(cli1, sname);
5638 cli_setatr(cli1, hname, 0, 0);
5639 cli_posix_unlink(cli1, hname);
5640 cli_setatr(cli1, fname, 0, 0);
5641 cli_posix_unlink(cli1, fname);
5642 cli_setatr(cli1, dname, 0, 0);
5643 cli_posix_rmdir(cli1, dname);
5645 if (!torture_close_connection(cli1)) {
5646 correct = false;
5649 return correct;
5653 static uint32 open_attrs_table[] = {
5654 FILE_ATTRIBUTE_NORMAL,
5655 FILE_ATTRIBUTE_ARCHIVE,
5656 FILE_ATTRIBUTE_READONLY,
5657 FILE_ATTRIBUTE_HIDDEN,
5658 FILE_ATTRIBUTE_SYSTEM,
5660 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
5661 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
5662 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
5663 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5664 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5665 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5667 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5668 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5669 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5670 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
5673 struct trunc_open_results {
5674 unsigned int num;
5675 uint32 init_attr;
5676 uint32 trunc_attr;
5677 uint32 result_attr;
5680 static struct trunc_open_results attr_results[] = {
5681 { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5682 { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5683 { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5684 { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5685 { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5686 { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5687 { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5688 { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5689 { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5690 { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5691 { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5692 { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
5693 { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5694 { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5695 { 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 },
5696 { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5697 { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5698 { 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 },
5699 { 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 },
5700 { 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 },
5701 { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5702 { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5703 { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5704 { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5705 { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5706 { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
5709 static bool run_openattrtest(int dummy)
5711 static struct cli_state *cli1;
5712 const char *fname = "\\openattr.file";
5713 uint16_t fnum1;
5714 bool correct = True;
5715 uint16 attr;
5716 unsigned int i, j, k, l;
5717 NTSTATUS status;
5719 printf("starting open attr test\n");
5721 if (!torture_open_connection(&cli1, 0)) {
5722 return False;
5725 cli_sockopt(cli1, sockops);
5727 for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32); i++) {
5728 cli_setatr(cli1, fname, 0, 0);
5729 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5731 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
5732 open_attrs_table[i], FILE_SHARE_NONE,
5733 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5734 if (!NT_STATUS_IS_OK(status)) {
5735 printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5736 return False;
5739 status = cli_close(cli1, fnum1);
5740 if (!NT_STATUS_IS_OK(status)) {
5741 printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5742 return False;
5745 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32); j++) {
5746 status = cli_ntcreate(cli1, fname, 0,
5747 FILE_READ_DATA|FILE_WRITE_DATA,
5748 open_attrs_table[j],
5749 FILE_SHARE_NONE, FILE_OVERWRITE,
5750 0, 0, &fnum1);
5751 if (!NT_STATUS_IS_OK(status)) {
5752 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5753 if (attr_results[l].num == k) {
5754 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
5755 k, open_attrs_table[i],
5756 open_attrs_table[j],
5757 fname, NT_STATUS_V(status), nt_errstr(status));
5758 correct = False;
5762 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5763 printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
5764 k, open_attrs_table[i], open_attrs_table[j],
5765 nt_errstr(status));
5766 correct = False;
5768 #if 0
5769 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
5770 #endif
5771 k++;
5772 continue;
5775 status = cli_close(cli1, fnum1);
5776 if (!NT_STATUS_IS_OK(status)) {
5777 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
5778 return False;
5781 status = cli_getatr(cli1, fname, &attr, NULL, NULL);
5782 if (!NT_STATUS_IS_OK(status)) {
5783 printf("getatr(2) failed (%s)\n", nt_errstr(status));
5784 return False;
5787 #if 0
5788 printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
5789 k, open_attrs_table[i], open_attrs_table[j], attr );
5790 #endif
5792 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5793 if (attr_results[l].num == k) {
5794 if (attr != attr_results[l].result_attr ||
5795 open_attrs_table[i] != attr_results[l].init_attr ||
5796 open_attrs_table[j] != attr_results[l].trunc_attr) {
5797 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
5798 open_attrs_table[i],
5799 open_attrs_table[j],
5800 (unsigned int)attr,
5801 attr_results[l].result_attr);
5802 correct = False;
5804 break;
5807 k++;
5811 cli_setatr(cli1, fname, 0, 0);
5812 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5814 printf("open attr test %s.\n", correct ? "passed" : "failed");
5816 if (!torture_close_connection(cli1)) {
5817 correct = False;
5819 return correct;
5822 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
5823 const char *name, void *state)
5825 int *matched = (int *)state;
5826 if (matched != NULL) {
5827 *matched += 1;
5829 return NT_STATUS_OK;
5833 test directory listing speed
5835 static bool run_dirtest(int dummy)
5837 int i;
5838 static struct cli_state *cli;
5839 uint16_t fnum;
5840 struct timeval core_start;
5841 bool correct = True;
5842 int matched;
5844 printf("starting directory test\n");
5846 if (!torture_open_connection(&cli, 0)) {
5847 return False;
5850 cli_sockopt(cli, sockops);
5852 srandom(0);
5853 for (i=0;i<torture_numops;i++) {
5854 fstring fname;
5855 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5856 if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
5857 fprintf(stderr,"Failed to open %s\n", fname);
5858 return False;
5860 cli_close(cli, fnum);
5863 core_start = timeval_current();
5865 matched = 0;
5866 cli_list(cli, "a*.*", 0, list_fn, &matched);
5867 printf("Matched %d\n", matched);
5869 matched = 0;
5870 cli_list(cli, "b*.*", 0, list_fn, &matched);
5871 printf("Matched %d\n", matched);
5873 matched = 0;
5874 cli_list(cli, "xyzabc", 0, list_fn, &matched);
5875 printf("Matched %d\n", matched);
5877 printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
5879 srandom(0);
5880 for (i=0;i<torture_numops;i++) {
5881 fstring fname;
5882 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5883 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5886 if (!torture_close_connection(cli)) {
5887 correct = False;
5890 printf("finished dirtest\n");
5892 return correct;
5895 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
5896 void *state)
5898 struct cli_state *pcli = (struct cli_state *)state;
5899 fstring fname;
5900 slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
5902 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
5903 return NT_STATUS_OK;
5905 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
5906 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
5907 printf("del_fn: failed to rmdir %s\n,", fname );
5908 } else {
5909 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
5910 printf("del_fn: failed to unlink %s\n,", fname );
5912 return NT_STATUS_OK;
5917 sees what IOCTLs are supported
5919 bool torture_ioctl_test(int dummy)
5921 static struct cli_state *cli;
5922 uint16_t device, function;
5923 uint16_t fnum;
5924 const char *fname = "\\ioctl.dat";
5925 DATA_BLOB blob;
5926 NTSTATUS status;
5928 if (!torture_open_connection(&cli, 0)) {
5929 return False;
5932 printf("starting ioctl test\n");
5934 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5936 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5937 if (!NT_STATUS_IS_OK(status)) {
5938 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5939 return False;
5942 status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
5943 printf("ioctl device info: %s\n", nt_errstr(status));
5945 status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
5946 printf("ioctl job info: %s\n", nt_errstr(status));
5948 for (device=0;device<0x100;device++) {
5949 printf("ioctl test with device = 0x%x\n", device);
5950 for (function=0;function<0x100;function++) {
5951 uint32 code = (device<<16) | function;
5953 status = cli_raw_ioctl(cli, fnum, code, &blob);
5955 if (NT_STATUS_IS_OK(status)) {
5956 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
5957 (int)blob.length);
5958 data_blob_free(&blob);
5963 if (!torture_close_connection(cli)) {
5964 return False;
5967 return True;
5972 tries varients of chkpath
5974 bool torture_chkpath_test(int dummy)
5976 static struct cli_state *cli;
5977 uint16_t fnum;
5978 bool ret;
5979 NTSTATUS status;
5981 if (!torture_open_connection(&cli, 0)) {
5982 return False;
5985 printf("starting chkpath test\n");
5987 /* cleanup from an old run */
5988 cli_rmdir(cli, "\\chkpath.dir\\dir2");
5989 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5990 cli_rmdir(cli, "\\chkpath.dir");
5992 status = cli_mkdir(cli, "\\chkpath.dir");
5993 if (!NT_STATUS_IS_OK(status)) {
5994 printf("mkdir1 failed : %s\n", nt_errstr(status));
5995 return False;
5998 status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
5999 if (!NT_STATUS_IS_OK(status)) {
6000 printf("mkdir2 failed : %s\n", nt_errstr(status));
6001 return False;
6004 status = cli_open(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
6005 DENY_NONE, &fnum);
6006 if (!NT_STATUS_IS_OK(status)) {
6007 printf("open1 failed (%s)\n", nt_errstr(status));
6008 return False;
6010 cli_close(cli, fnum);
6012 status = cli_chkpath(cli, "\\chkpath.dir");
6013 if (!NT_STATUS_IS_OK(status)) {
6014 printf("chkpath1 failed: %s\n", nt_errstr(status));
6015 ret = False;
6018 status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
6019 if (!NT_STATUS_IS_OK(status)) {
6020 printf("chkpath2 failed: %s\n", nt_errstr(status));
6021 ret = False;
6024 status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
6025 if (!NT_STATUS_IS_OK(status)) {
6026 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
6027 NT_STATUS_NOT_A_DIRECTORY);
6028 } else {
6029 printf("* chkpath on a file should fail\n");
6030 ret = False;
6033 status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
6034 if (!NT_STATUS_IS_OK(status)) {
6035 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
6036 NT_STATUS_OBJECT_NAME_NOT_FOUND);
6037 } else {
6038 printf("* chkpath on a non existant file should fail\n");
6039 ret = False;
6042 status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
6043 if (!NT_STATUS_IS_OK(status)) {
6044 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
6045 NT_STATUS_OBJECT_PATH_NOT_FOUND);
6046 } else {
6047 printf("* chkpath on a non existent component should fail\n");
6048 ret = False;
6051 cli_rmdir(cli, "\\chkpath.dir\\dir2");
6052 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6053 cli_rmdir(cli, "\\chkpath.dir");
6055 if (!torture_close_connection(cli)) {
6056 return False;
6059 return ret;
6062 static bool run_eatest(int dummy)
6064 static struct cli_state *cli;
6065 const char *fname = "\\eatest.txt";
6066 bool correct = True;
6067 uint16_t fnum;
6068 int i;
6069 size_t num_eas;
6070 struct ea_struct *ea_list = NULL;
6071 TALLOC_CTX *mem_ctx = talloc_init("eatest");
6072 NTSTATUS status;
6074 printf("starting eatest\n");
6076 if (!torture_open_connection(&cli, 0)) {
6077 talloc_destroy(mem_ctx);
6078 return False;
6081 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6083 status = cli_ntcreate(cli, fname, 0,
6084 FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6085 FILE_SHARE_NONE, FILE_OVERWRITE_IF,
6086 0x4044, 0, &fnum);
6087 if (!NT_STATUS_IS_OK(status)) {
6088 printf("open failed - %s\n", nt_errstr(status));
6089 talloc_destroy(mem_ctx);
6090 return False;
6093 for (i = 0; i < 10; i++) {
6094 fstring ea_name, ea_val;
6096 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
6097 memset(ea_val, (char)i+1, i+1);
6098 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
6099 if (!NT_STATUS_IS_OK(status)) {
6100 printf("ea_set of name %s failed - %s\n", ea_name,
6101 nt_errstr(status));
6102 talloc_destroy(mem_ctx);
6103 return False;
6107 cli_close(cli, fnum);
6108 for (i = 0; i < 10; i++) {
6109 fstring ea_name, ea_val;
6111 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
6112 memset(ea_val, (char)i+1, i+1);
6113 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
6114 if (!NT_STATUS_IS_OK(status)) {
6115 printf("ea_set of name %s failed - %s\n", ea_name,
6116 nt_errstr(status));
6117 talloc_destroy(mem_ctx);
6118 return False;
6122 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6123 if (!NT_STATUS_IS_OK(status)) {
6124 printf("ea_get list failed - %s\n", nt_errstr(status));
6125 correct = False;
6128 printf("num_eas = %d\n", (int)num_eas);
6130 if (num_eas != 20) {
6131 printf("Should be 20 EA's stored... failing.\n");
6132 correct = False;
6135 for (i = 0; i < num_eas; i++) {
6136 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6137 dump_data(0, ea_list[i].value.data,
6138 ea_list[i].value.length);
6141 /* Setting EA's to zero length deletes them. Test this */
6142 printf("Now deleting all EA's - case indepenent....\n");
6144 #if 1
6145 cli_set_ea_path(cli, fname, "", "", 0);
6146 #else
6147 for (i = 0; i < 20; i++) {
6148 fstring ea_name;
6149 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
6150 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
6151 if (!NT_STATUS_IS_OK(status)) {
6152 printf("ea_set of name %s failed - %s\n", ea_name,
6153 nt_errstr(status));
6154 talloc_destroy(mem_ctx);
6155 return False;
6158 #endif
6160 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6161 if (!NT_STATUS_IS_OK(status)) {
6162 printf("ea_get list failed - %s\n", nt_errstr(status));
6163 correct = False;
6166 printf("num_eas = %d\n", (int)num_eas);
6167 for (i = 0; i < num_eas; i++) {
6168 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6169 dump_data(0, ea_list[i].value.data,
6170 ea_list[i].value.length);
6173 if (num_eas != 0) {
6174 printf("deleting EA's failed.\n");
6175 correct = False;
6178 /* Try and delete a non existant EA. */
6179 status = cli_set_ea_path(cli, fname, "foo", "", 0);
6180 if (!NT_STATUS_IS_OK(status)) {
6181 printf("deleting non-existant EA 'foo' should succeed. %s\n",
6182 nt_errstr(status));
6183 correct = False;
6186 talloc_destroy(mem_ctx);
6187 if (!torture_close_connection(cli)) {
6188 correct = False;
6191 return correct;
6194 static bool run_dirtest1(int dummy)
6196 int i;
6197 static struct cli_state *cli;
6198 uint16_t fnum;
6199 int num_seen;
6200 bool correct = True;
6202 printf("starting directory test\n");
6204 if (!torture_open_connection(&cli, 0)) {
6205 return False;
6208 cli_sockopt(cli, sockops);
6210 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6211 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6212 cli_rmdir(cli, "\\LISTDIR");
6213 cli_mkdir(cli, "\\LISTDIR");
6215 /* Create 1000 files and 1000 directories. */
6216 for (i=0;i<1000;i++) {
6217 fstring fname;
6218 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
6219 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6220 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum))) {
6221 fprintf(stderr,"Failed to open %s\n", fname);
6222 return False;
6224 cli_close(cli, fnum);
6226 for (i=0;i<1000;i++) {
6227 fstring fname;
6228 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
6229 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
6230 fprintf(stderr,"Failed to open %s\n", fname);
6231 return False;
6235 /* Now ensure that doing an old list sees both files and directories. */
6236 num_seen = 0;
6237 cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6238 printf("num_seen = %d\n", num_seen );
6239 /* We should see 100 files + 1000 directories + . and .. */
6240 if (num_seen != 2002)
6241 correct = False;
6243 /* Ensure if we have the "must have" bits we only see the
6244 * relevent entries.
6246 num_seen = 0;
6247 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6248 printf("num_seen = %d\n", num_seen );
6249 if (num_seen != 1002)
6250 correct = False;
6252 num_seen = 0;
6253 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6254 printf("num_seen = %d\n", num_seen );
6255 if (num_seen != 1000)
6256 correct = False;
6258 /* Delete everything. */
6259 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6260 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6261 cli_rmdir(cli, "\\LISTDIR");
6263 #if 0
6264 printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
6265 printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
6266 printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
6267 #endif
6269 if (!torture_close_connection(cli)) {
6270 correct = False;
6273 printf("finished dirtest1\n");
6275 return correct;
6278 static bool run_error_map_extract(int dummy) {
6280 static struct cli_state *c_dos;
6281 static struct cli_state *c_nt;
6282 NTSTATUS status;
6284 uint32 error;
6286 uint32 errnum;
6287 uint8 errclass;
6289 NTSTATUS nt_status;
6291 fstring user;
6293 /* NT-Error connection */
6295 if (!(c_nt = open_nbt_connection())) {
6296 return False;
6299 c_nt->use_spnego = False;
6301 status = cli_negprot(c_nt);
6303 if (!NT_STATUS_IS_OK(status)) {
6304 printf("%s rejected the NT-error negprot (%s)\n", host,
6305 nt_errstr(status));
6306 cli_shutdown(c_nt);
6307 return False;
6310 status = cli_session_setup(c_nt, "", "", 0, "", 0, workgroup);
6311 if (!NT_STATUS_IS_OK(status)) {
6312 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
6313 return False;
6316 /* DOS-Error connection */
6318 force_dos_errors = true;
6319 if (!(c_dos = open_nbt_connection())) {
6320 force_dos_errors = false;
6321 return False;
6323 force_dos_errors = false;
6325 c_dos->use_spnego = False;
6327 status = cli_negprot(c_dos);
6328 if (!NT_STATUS_IS_OK(status)) {
6329 printf("%s rejected the DOS-error negprot (%s)\n", host,
6330 nt_errstr(status));
6331 cli_shutdown(c_dos);
6332 return False;
6335 status = cli_session_setup(c_dos, "", "", 0, "", 0, workgroup);
6336 if (!NT_STATUS_IS_OK(status)) {
6337 printf("%s rejected the DOS-error initial session setup (%s)\n",
6338 host, nt_errstr(status));
6339 return False;
6342 for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
6343 fstr_sprintf(user, "%X", error);
6345 status = cli_session_setup(c_nt, user,
6346 password, strlen(password),
6347 password, strlen(password),
6348 workgroup);
6349 if (NT_STATUS_IS_OK(status)) {
6350 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
6353 /* Case #1: 32-bit NT errors */
6354 if (cli_is_nt_error(c_nt)) {
6355 nt_status = cli_nt_error(c_nt);
6356 } else {
6357 printf("/** Dos error on NT connection! (%s) */\n",
6358 cli_errstr(c_nt));
6359 nt_status = NT_STATUS(0xc0000000);
6362 status = cli_session_setup(c_dos, user,
6363 password, strlen(password),
6364 password, strlen(password),
6365 workgroup);
6366 if (NT_STATUS_IS_OK(status)) {
6367 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
6370 /* Case #1: 32-bit NT errors */
6371 if (!cli_is_dos_error(c_dos)) {
6372 printf("/** NT error on DOS connection! (%s) */\n",
6373 cli_errstr(c_dos));
6374 errnum = errclass = 0;
6375 } else {
6376 cli_dos_error(c_dos, &errclass, &errnum);
6379 if (NT_STATUS_V(nt_status) != error) {
6380 printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
6381 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
6382 get_nt_error_c_code(talloc_tos(), nt_status));
6385 printf("\t{%s,\t%s,\t%s},\n",
6386 smb_dos_err_class(errclass),
6387 smb_dos_err_name(errclass, errnum),
6388 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
6390 return True;
6393 static bool run_sesssetup_bench(int dummy)
6395 static struct cli_state *c;
6396 const char *fname = "\\file.dat";
6397 uint16_t fnum;
6398 NTSTATUS status;
6399 int i;
6401 if (!torture_open_connection(&c, 0)) {
6402 return false;
6405 status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6406 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6407 FILE_DELETE_ON_CLOSE, 0, &fnum);
6408 if (!NT_STATUS_IS_OK(status)) {
6409 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
6410 return false;
6413 for (i=0; i<torture_numops; i++) {
6414 status = cli_session_setup(
6415 c, username,
6416 password, strlen(password),
6417 password, strlen(password),
6418 workgroup);
6419 if (!NT_STATUS_IS_OK(status)) {
6420 d_printf("(%s) cli_session_setup failed: %s\n",
6421 __location__, nt_errstr(status));
6422 return false;
6425 d_printf("\r%d ", (int)cli_state_get_uid(c));
6427 status = cli_ulogoff(c);
6428 if (!NT_STATUS_IS_OK(status)) {
6429 d_printf("(%s) cli_ulogoff failed: %s\n",
6430 __location__, nt_errstr(status));
6431 return false;
6435 return true;
6438 static bool subst_test(const char *str, const char *user, const char *domain,
6439 uid_t uid, gid_t gid, const char *expected)
6441 char *subst;
6442 bool result = true;
6444 subst = talloc_sub_specified(talloc_tos(), str, user, domain, uid, gid);
6446 if (strcmp(subst, expected) != 0) {
6447 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
6448 "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
6449 expected);
6450 result = false;
6453 TALLOC_FREE(subst);
6454 return result;
6457 static void chain1_open_completion(struct tevent_req *req)
6459 uint16_t fnum;
6460 NTSTATUS status;
6461 status = cli_open_recv(req, &fnum);
6462 TALLOC_FREE(req);
6464 d_printf("cli_open_recv returned %s: %d\n",
6465 nt_errstr(status),
6466 NT_STATUS_IS_OK(status) ? fnum : -1);
6469 static void chain1_write_completion(struct tevent_req *req)
6471 size_t written;
6472 NTSTATUS status;
6473 status = cli_write_andx_recv(req, &written);
6474 TALLOC_FREE(req);
6476 d_printf("cli_write_andx_recv returned %s: %d\n",
6477 nt_errstr(status),
6478 NT_STATUS_IS_OK(status) ? (int)written : -1);
6481 static void chain1_close_completion(struct tevent_req *req)
6483 NTSTATUS status;
6484 bool *done = (bool *)tevent_req_callback_data_void(req);
6486 status = cli_close_recv(req);
6487 *done = true;
6489 TALLOC_FREE(req);
6491 d_printf("cli_close returned %s\n", nt_errstr(status));
6494 static bool run_chain1(int dummy)
6496 struct cli_state *cli1;
6497 struct event_context *evt = event_context_init(NULL);
6498 struct tevent_req *reqs[3], *smbreqs[3];
6499 bool done = false;
6500 const char *str = "foobar";
6501 NTSTATUS status;
6503 printf("starting chain1 test\n");
6504 if (!torture_open_connection(&cli1, 0)) {
6505 return False;
6508 cli_sockopt(cli1, sockops);
6510 reqs[0] = cli_open_create(talloc_tos(), evt, cli1, "\\test",
6511 O_CREAT|O_RDWR, 0, &smbreqs[0]);
6512 if (reqs[0] == NULL) return false;
6513 tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
6516 reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
6517 (const uint8_t *)str, 0, strlen(str)+1,
6518 smbreqs, 1, &smbreqs[1]);
6519 if (reqs[1] == NULL) return false;
6520 tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
6522 reqs[2] = cli_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
6523 if (reqs[2] == NULL) return false;
6524 tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
6526 status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
6527 if (!NT_STATUS_IS_OK(status)) {
6528 return false;
6531 while (!done) {
6532 tevent_loop_once(evt);
6535 torture_close_connection(cli1);
6536 return True;
6539 static void chain2_sesssetup_completion(struct tevent_req *req)
6541 NTSTATUS status;
6542 status = cli_session_setup_guest_recv(req);
6543 d_printf("sesssetup returned %s\n", nt_errstr(status));
6546 static void chain2_tcon_completion(struct tevent_req *req)
6548 bool *done = (bool *)tevent_req_callback_data_void(req);
6549 NTSTATUS status;
6550 status = cli_tcon_andx_recv(req);
6551 d_printf("tcon_and_x returned %s\n", nt_errstr(status));
6552 *done = true;
6555 static bool run_chain2(int dummy)
6557 struct cli_state *cli1;
6558 struct event_context *evt = event_context_init(NULL);
6559 struct tevent_req *reqs[2], *smbreqs[2];
6560 bool done = false;
6561 NTSTATUS status;
6563 printf("starting chain2 test\n");
6564 status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
6565 port_to_use, Undefined, 0);
6566 if (!NT_STATUS_IS_OK(status)) {
6567 return False;
6570 cli_sockopt(cli1, sockops);
6572 reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
6573 &smbreqs[0]);
6574 if (reqs[0] == NULL) return false;
6575 tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
6577 reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
6578 "?????", NULL, 0, &smbreqs[1]);
6579 if (reqs[1] == NULL) return false;
6580 tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
6582 status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
6583 if (!NT_STATUS_IS_OK(status)) {
6584 return false;
6587 while (!done) {
6588 tevent_loop_once(evt);
6591 torture_close_connection(cli1);
6592 return True;
6596 struct torture_createdel_state {
6597 struct tevent_context *ev;
6598 struct cli_state *cli;
6601 static void torture_createdel_created(struct tevent_req *subreq);
6602 static void torture_createdel_closed(struct tevent_req *subreq);
6604 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
6605 struct tevent_context *ev,
6606 struct cli_state *cli,
6607 const char *name)
6609 struct tevent_req *req, *subreq;
6610 struct torture_createdel_state *state;
6612 req = tevent_req_create(mem_ctx, &state,
6613 struct torture_createdel_state);
6614 if (req == NULL) {
6615 return NULL;
6617 state->ev = ev;
6618 state->cli = cli;
6620 subreq = cli_ntcreate_send(
6621 state, ev, cli, name, 0,
6622 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
6623 FILE_ATTRIBUTE_NORMAL,
6624 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6625 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
6627 if (tevent_req_nomem(subreq, req)) {
6628 return tevent_req_post(req, ev);
6630 tevent_req_set_callback(subreq, torture_createdel_created, req);
6631 return req;
6634 static void torture_createdel_created(struct tevent_req *subreq)
6636 struct tevent_req *req = tevent_req_callback_data(
6637 subreq, struct tevent_req);
6638 struct torture_createdel_state *state = tevent_req_data(
6639 req, struct torture_createdel_state);
6640 NTSTATUS status;
6641 uint16_t fnum;
6643 status = cli_ntcreate_recv(subreq, &fnum);
6644 TALLOC_FREE(subreq);
6645 if (!NT_STATUS_IS_OK(status)) {
6646 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
6647 nt_errstr(status)));
6648 tevent_req_nterror(req, status);
6649 return;
6652 subreq = cli_close_send(state, state->ev, state->cli, fnum);
6653 if (tevent_req_nomem(subreq, req)) {
6654 return;
6656 tevent_req_set_callback(subreq, torture_createdel_closed, req);
6659 static void torture_createdel_closed(struct tevent_req *subreq)
6661 struct tevent_req *req = tevent_req_callback_data(
6662 subreq, struct tevent_req);
6663 NTSTATUS status;
6665 status = cli_close_recv(subreq);
6666 if (!NT_STATUS_IS_OK(status)) {
6667 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
6668 tevent_req_nterror(req, status);
6669 return;
6671 tevent_req_done(req);
6674 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
6676 return tevent_req_simple_recv_ntstatus(req);
6679 struct torture_createdels_state {
6680 struct tevent_context *ev;
6681 struct cli_state *cli;
6682 const char *base_name;
6683 int sent;
6684 int received;
6685 int num_files;
6686 struct tevent_req **reqs;
6689 static void torture_createdels_done(struct tevent_req *subreq);
6691 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
6692 struct tevent_context *ev,
6693 struct cli_state *cli,
6694 const char *base_name,
6695 int num_parallel,
6696 int num_files)
6698 struct tevent_req *req;
6699 struct torture_createdels_state *state;
6700 int i;
6702 req = tevent_req_create(mem_ctx, &state,
6703 struct torture_createdels_state);
6704 if (req == NULL) {
6705 return NULL;
6707 state->ev = ev;
6708 state->cli = cli;
6709 state->base_name = talloc_strdup(state, base_name);
6710 if (tevent_req_nomem(state->base_name, req)) {
6711 return tevent_req_post(req, ev);
6713 state->num_files = MAX(num_parallel, num_files);
6714 state->sent = 0;
6715 state->received = 0;
6717 state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
6718 if (tevent_req_nomem(state->reqs, req)) {
6719 return tevent_req_post(req, ev);
6722 for (i=0; i<num_parallel; i++) {
6723 char *name;
6725 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6726 state->sent);
6727 if (tevent_req_nomem(name, req)) {
6728 return tevent_req_post(req, ev);
6730 state->reqs[i] = torture_createdel_send(
6731 state->reqs, state->ev, state->cli, name);
6732 if (tevent_req_nomem(state->reqs[i], req)) {
6733 return tevent_req_post(req, ev);
6735 name = talloc_move(state->reqs[i], &name);
6736 tevent_req_set_callback(state->reqs[i],
6737 torture_createdels_done, req);
6738 state->sent += 1;
6740 return req;
6743 static void torture_createdels_done(struct tevent_req *subreq)
6745 struct tevent_req *req = tevent_req_callback_data(
6746 subreq, struct tevent_req);
6747 struct torture_createdels_state *state = tevent_req_data(
6748 req, struct torture_createdels_state);
6749 size_t num_parallel = talloc_array_length(state->reqs);
6750 NTSTATUS status;
6751 char *name;
6752 int i;
6754 status = torture_createdel_recv(subreq);
6755 if (!NT_STATUS_IS_OK(status)){
6756 DEBUG(10, ("torture_createdel_recv returned %s\n",
6757 nt_errstr(status)));
6758 TALLOC_FREE(subreq);
6759 tevent_req_nterror(req, status);
6760 return;
6763 for (i=0; i<num_parallel; i++) {
6764 if (subreq == state->reqs[i]) {
6765 break;
6768 if (i == num_parallel) {
6769 DEBUG(10, ("received something we did not send\n"));
6770 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
6771 return;
6773 TALLOC_FREE(state->reqs[i]);
6775 if (state->sent >= state->num_files) {
6776 tevent_req_done(req);
6777 return;
6780 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6781 state->sent);
6782 if (tevent_req_nomem(name, req)) {
6783 return;
6785 state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
6786 state->cli, name);
6787 if (tevent_req_nomem(state->reqs[i], req)) {
6788 return;
6790 name = talloc_move(state->reqs[i], &name);
6791 tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
6792 state->sent += 1;
6795 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
6797 return tevent_req_simple_recv_ntstatus(req);
6800 struct swallow_notify_state {
6801 struct tevent_context *ev;
6802 struct cli_state *cli;
6803 uint16_t fnum;
6804 uint32_t completion_filter;
6805 bool recursive;
6806 bool (*fn)(uint32_t action, const char *name, void *priv);
6807 void *priv;
6810 static void swallow_notify_done(struct tevent_req *subreq);
6812 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
6813 struct tevent_context *ev,
6814 struct cli_state *cli,
6815 uint16_t fnum,
6816 uint32_t completion_filter,
6817 bool recursive,
6818 bool (*fn)(uint32_t action,
6819 const char *name,
6820 void *priv),
6821 void *priv)
6823 struct tevent_req *req, *subreq;
6824 struct swallow_notify_state *state;
6826 req = tevent_req_create(mem_ctx, &state,
6827 struct swallow_notify_state);
6828 if (req == NULL) {
6829 return NULL;
6831 state->ev = ev;
6832 state->cli = cli;
6833 state->fnum = fnum;
6834 state->completion_filter = completion_filter;
6835 state->recursive = recursive;
6836 state->fn = fn;
6837 state->priv = priv;
6839 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6840 0xffff, state->completion_filter,
6841 state->recursive);
6842 if (tevent_req_nomem(subreq, req)) {
6843 return tevent_req_post(req, ev);
6845 tevent_req_set_callback(subreq, swallow_notify_done, req);
6846 return req;
6849 static void swallow_notify_done(struct tevent_req *subreq)
6851 struct tevent_req *req = tevent_req_callback_data(
6852 subreq, struct tevent_req);
6853 struct swallow_notify_state *state = tevent_req_data(
6854 req, struct swallow_notify_state);
6855 NTSTATUS status;
6856 uint32_t i, num_changes;
6857 struct notify_change *changes;
6859 status = cli_notify_recv(subreq, state, &num_changes, &changes);
6860 TALLOC_FREE(subreq);
6861 if (!NT_STATUS_IS_OK(status)) {
6862 DEBUG(10, ("cli_notify_recv returned %s\n",
6863 nt_errstr(status)));
6864 tevent_req_nterror(req, status);
6865 return;
6868 for (i=0; i<num_changes; i++) {
6869 state->fn(changes[i].action, changes[i].name, state->priv);
6871 TALLOC_FREE(changes);
6873 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6874 0xffff, state->completion_filter,
6875 state->recursive);
6876 if (tevent_req_nomem(subreq, req)) {
6877 return;
6879 tevent_req_set_callback(subreq, swallow_notify_done, req);
6882 static bool print_notifies(uint32_t action, const char *name, void *priv)
6884 if (DEBUGLEVEL > 5) {
6885 d_printf("%d %s\n", (int)action, name);
6887 return true;
6890 static void notify_bench_done(struct tevent_req *req)
6892 int *num_finished = (int *)tevent_req_callback_data_void(req);
6893 *num_finished += 1;
6896 static bool run_notify_bench(int dummy)
6898 const char *dname = "\\notify-bench";
6899 struct tevent_context *ev;
6900 NTSTATUS status;
6901 uint16_t dnum;
6902 struct tevent_req *req1;
6903 struct tevent_req *req2 = NULL;
6904 int i, num_unc_names;
6905 int num_finished = 0;
6907 printf("starting notify-bench test\n");
6909 if (use_multishare_conn) {
6910 char **unc_list;
6911 unc_list = file_lines_load(multishare_conn_fname,
6912 &num_unc_names, 0, NULL);
6913 if (!unc_list || num_unc_names <= 0) {
6914 d_printf("Failed to load unc names list from '%s'\n",
6915 multishare_conn_fname);
6916 return false;
6918 TALLOC_FREE(unc_list);
6919 } else {
6920 num_unc_names = 1;
6923 ev = tevent_context_init(talloc_tos());
6924 if (ev == NULL) {
6925 d_printf("tevent_context_init failed\n");
6926 return false;
6929 for (i=0; i<num_unc_names; i++) {
6930 struct cli_state *cli;
6931 char *base_fname;
6933 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
6934 dname, i);
6935 if (base_fname == NULL) {
6936 return false;
6939 if (!torture_open_connection(&cli, i)) {
6940 return false;
6943 status = cli_ntcreate(cli, dname, 0,
6944 MAXIMUM_ALLOWED_ACCESS,
6945 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
6946 FILE_SHARE_DELETE,
6947 FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
6948 &dnum);
6950 if (!NT_STATUS_IS_OK(status)) {
6951 d_printf("Could not create %s: %s\n", dname,
6952 nt_errstr(status));
6953 return false;
6956 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
6957 FILE_NOTIFY_CHANGE_FILE_NAME |
6958 FILE_NOTIFY_CHANGE_DIR_NAME |
6959 FILE_NOTIFY_CHANGE_ATTRIBUTES |
6960 FILE_NOTIFY_CHANGE_LAST_WRITE,
6961 false, print_notifies, NULL);
6962 if (req1 == NULL) {
6963 d_printf("Could not create notify request\n");
6964 return false;
6967 req2 = torture_createdels_send(talloc_tos(), ev, cli,
6968 base_fname, 10, torture_numops);
6969 if (req2 == NULL) {
6970 d_printf("Could not create createdels request\n");
6971 return false;
6973 TALLOC_FREE(base_fname);
6975 tevent_req_set_callback(req2, notify_bench_done,
6976 &num_finished);
6979 while (num_finished < num_unc_names) {
6980 int ret;
6981 ret = tevent_loop_once(ev);
6982 if (ret != 0) {
6983 d_printf("tevent_loop_once failed\n");
6984 return false;
6988 if (!tevent_req_poll(req2, ev)) {
6989 d_printf("tevent_req_poll failed\n");
6992 status = torture_createdels_recv(req2);
6993 d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
6995 return true;
6998 static bool run_mangle1(int dummy)
7000 struct cli_state *cli;
7001 const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
7002 uint16_t fnum;
7003 fstring alt_name;
7004 NTSTATUS status;
7005 time_t change_time, access_time, write_time;
7006 SMB_OFF_T size;
7007 uint16_t mode;
7009 printf("starting mangle1 test\n");
7010 if (!torture_open_connection(&cli, 0)) {
7011 return False;
7014 cli_sockopt(cli, sockops);
7016 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
7017 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
7018 0, 0, &fnum);
7019 if (!NT_STATUS_IS_OK(status)) {
7020 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
7021 return false;
7023 cli_close(cli, fnum);
7025 status = cli_qpathinfo_alt_name(cli, fname, alt_name);
7026 if (!NT_STATUS_IS_OK(status)) {
7027 d_printf("cli_qpathinfo_alt_name failed: %s\n",
7028 nt_errstr(status));
7029 return false;
7031 d_printf("alt_name: %s\n", alt_name);
7033 status = cli_open(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
7034 if (!NT_STATUS_IS_OK(status)) {
7035 d_printf("cli_open(%s) failed: %s\n", alt_name,
7036 nt_errstr(status));
7037 return false;
7039 cli_close(cli, fnum);
7041 status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
7042 &write_time, &size, &mode);
7043 if (!NT_STATUS_IS_OK(status)) {
7044 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
7045 nt_errstr(status));
7046 return false;
7049 return true;
7052 static size_t null_source(uint8_t *buf, size_t n, void *priv)
7054 size_t *to_pull = (size_t *)priv;
7055 size_t thistime = *to_pull;
7057 thistime = MIN(thistime, n);
7058 if (thistime == 0) {
7059 return 0;
7062 memset(buf, 0, thistime);
7063 *to_pull -= thistime;
7064 return thistime;
7067 static bool run_windows_write(int dummy)
7069 struct cli_state *cli1;
7070 uint16_t fnum;
7071 int i;
7072 bool ret = false;
7073 const char *fname = "\\writetest.txt";
7074 struct timeval start_time;
7075 double seconds;
7076 double kbytes;
7077 NTSTATUS status;
7079 printf("starting windows_write test\n");
7080 if (!torture_open_connection(&cli1, 0)) {
7081 return False;
7084 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
7085 if (!NT_STATUS_IS_OK(status)) {
7086 printf("open failed (%s)\n", nt_errstr(status));
7087 return False;
7090 cli_sockopt(cli1, sockops);
7092 start_time = timeval_current();
7094 for (i=0; i<torture_numops; i++) {
7095 uint8_t c = 0;
7096 off_t start = i * torture_blocksize;
7097 size_t to_pull = torture_blocksize - 1;
7099 status = cli_writeall(cli1, fnum, 0, &c,
7100 start + torture_blocksize - 1, 1, NULL);
7101 if (!NT_STATUS_IS_OK(status)) {
7102 printf("cli_write failed: %s\n", nt_errstr(status));
7103 goto fail;
7106 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
7107 null_source, &to_pull);
7108 if (!NT_STATUS_IS_OK(status)) {
7109 printf("cli_push returned: %s\n", nt_errstr(status));
7110 goto fail;
7114 seconds = timeval_elapsed(&start_time);
7115 kbytes = (double)torture_blocksize * torture_numops;
7116 kbytes /= 1024;
7118 printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
7119 (double)seconds, (int)(kbytes/seconds));
7121 ret = true;
7122 fail:
7123 cli_close(cli1, fnum);
7124 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7125 torture_close_connection(cli1);
7126 return ret;
7129 static bool run_cli_echo(int dummy)
7131 struct cli_state *cli;
7132 NTSTATUS status;
7134 printf("starting cli_echo test\n");
7135 if (!torture_open_connection(&cli, 0)) {
7136 return false;
7138 cli_sockopt(cli, sockops);
7140 status = cli_echo(cli, 5, data_blob_const("hello", 5));
7142 d_printf("cli_echo returned %s\n", nt_errstr(status));
7144 torture_close_connection(cli);
7145 return NT_STATUS_IS_OK(status);
7148 static bool run_uid_regression_test(int dummy)
7150 static struct cli_state *cli;
7151 int16_t old_vuid;
7152 int16_t old_cnum;
7153 bool correct = True;
7154 NTSTATUS status;
7156 printf("starting uid regression test\n");
7158 if (!torture_open_connection(&cli, 0)) {
7159 return False;
7162 cli_sockopt(cli, sockops);
7164 /* Ok - now save then logoff our current user. */
7165 old_vuid = cli_state_get_uid(cli);
7167 status = cli_ulogoff(cli);
7168 if (!NT_STATUS_IS_OK(status)) {
7169 d_printf("(%s) cli_ulogoff failed: %s\n",
7170 __location__, nt_errstr(status));
7171 correct = false;
7172 goto out;
7175 cli_state_set_uid(cli, old_vuid);
7177 /* Try an operation. */
7178 status = cli_mkdir(cli, "\\uid_reg_test");
7179 if (NT_STATUS_IS_OK(status)) {
7180 d_printf("(%s) cli_mkdir succeeded\n",
7181 __location__);
7182 correct = false;
7183 goto out;
7184 } else {
7185 /* Should be bad uid. */
7186 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
7187 NT_STATUS_USER_SESSION_DELETED)) {
7188 correct = false;
7189 goto out;
7193 old_cnum = cli_state_get_tid(cli);
7195 /* Now try a SMBtdis with the invald vuid set to zero. */
7196 cli_state_set_uid(cli, 0);
7198 /* This should succeed. */
7199 status = cli_tdis(cli);
7201 if (NT_STATUS_IS_OK(status)) {
7202 d_printf("First tdis with invalid vuid should succeed.\n");
7203 } else {
7204 d_printf("First tdis failed (%s)\n", nt_errstr(status));
7205 correct = false;
7206 goto out;
7209 cli_state_set_uid(cli, old_vuid);
7210 cli_state_set_tid(cli, old_cnum);
7212 /* This should fail. */
7213 status = cli_tdis(cli);
7214 if (NT_STATUS_IS_OK(status)) {
7215 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
7216 correct = false;
7217 goto out;
7218 } else {
7219 /* Should be bad tid. */
7220 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
7221 NT_STATUS_NETWORK_NAME_DELETED)) {
7222 correct = false;
7223 goto out;
7227 cli_rmdir(cli, "\\uid_reg_test");
7229 out:
7231 cli_shutdown(cli);
7232 return correct;
7236 static const char *illegal_chars = "*\\/?<>|\":";
7237 static char force_shortname_chars[] = " +,.[];=\177";
7239 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
7240 const char *mask, void *state)
7242 struct cli_state *pcli = (struct cli_state *)state;
7243 fstring fname;
7244 NTSTATUS status = NT_STATUS_OK;
7246 slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
7248 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
7249 return NT_STATUS_OK;
7251 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
7252 status = cli_rmdir(pcli, fname);
7253 if (!NT_STATUS_IS_OK(status)) {
7254 printf("del_fn: failed to rmdir %s\n,", fname );
7256 } else {
7257 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7258 if (!NT_STATUS_IS_OK(status)) {
7259 printf("del_fn: failed to unlink %s\n,", fname );
7262 return status;
7265 struct sn_state {
7266 int matched;
7267 int i;
7268 bool val;
7271 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
7272 const char *name, void *state)
7274 struct sn_state *s = (struct sn_state *)state;
7275 int i = s->i;
7277 #if 0
7278 printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
7279 i, finfo->name, finfo->short_name);
7280 #endif
7282 if (strchr(force_shortname_chars, i)) {
7283 if (!finfo->short_name) {
7284 /* Shortname not created when it should be. */
7285 d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
7286 __location__, finfo->name, i);
7287 s->val = true;
7289 } else if (finfo->short_name){
7290 /* Shortname created when it should not be. */
7291 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
7292 __location__, finfo->short_name, finfo->name);
7293 s->val = true;
7295 s->matched += 1;
7296 return NT_STATUS_OK;
7299 static bool run_shortname_test(int dummy)
7301 static struct cli_state *cli;
7302 bool correct = True;
7303 int i;
7304 struct sn_state s;
7305 char fname[20];
7306 NTSTATUS status;
7308 printf("starting shortname test\n");
7310 if (!torture_open_connection(&cli, 0)) {
7311 return False;
7314 cli_sockopt(cli, sockops);
7316 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7317 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7318 cli_rmdir(cli, "\\shortname");
7320 status = cli_mkdir(cli, "\\shortname");
7321 if (!NT_STATUS_IS_OK(status)) {
7322 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
7323 __location__, nt_errstr(status));
7324 correct = false;
7325 goto out;
7328 strlcpy(fname, "\\shortname\\", sizeof(fname));
7329 strlcat(fname, "test .txt", sizeof(fname));
7331 s.val = false;
7333 for (i = 32; i < 128; i++) {
7334 uint16_t fnum = (uint16_t)-1;
7336 s.i = i;
7338 if (strchr(illegal_chars, i)) {
7339 continue;
7341 fname[15] = i;
7343 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
7344 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum);
7345 if (!NT_STATUS_IS_OK(status)) {
7346 d_printf("(%s) cli_nt_create of %s failed: %s\n",
7347 __location__, fname, nt_errstr(status));
7348 correct = false;
7349 goto out;
7351 cli_close(cli, fnum);
7353 s.matched = 0;
7354 status = cli_list(cli, "\\shortname\\test*.*", 0,
7355 shortname_list_fn, &s);
7356 if (s.matched != 1) {
7357 d_printf("(%s) failed to list %s: %s\n",
7358 __location__, fname, nt_errstr(status));
7359 correct = false;
7360 goto out;
7363 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7364 if (!NT_STATUS_IS_OK(status)) {
7365 d_printf("(%s) failed to delete %s: %s\n",
7366 __location__, fname, nt_errstr(status));
7367 correct = false;
7368 goto out;
7371 if (s.val) {
7372 correct = false;
7373 goto out;
7377 out:
7379 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7380 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7381 cli_rmdir(cli, "\\shortname");
7382 torture_close_connection(cli);
7383 return correct;
7386 static void pagedsearch_cb(struct tevent_req *req)
7388 int rc;
7389 struct tldap_message *msg;
7390 char *dn;
7392 rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
7393 if (rc != TLDAP_SUCCESS) {
7394 d_printf("tldap_search_paged_recv failed: %s\n",
7395 tldap_err2string(rc));
7396 return;
7398 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
7399 TALLOC_FREE(msg);
7400 return;
7402 if (!tldap_entry_dn(msg, &dn)) {
7403 d_printf("tldap_entry_dn failed\n");
7404 return;
7406 d_printf("%s\n", dn);
7407 TALLOC_FREE(msg);
7410 static bool run_tldap(int dummy)
7412 struct tldap_context *ld;
7413 int fd, rc;
7414 NTSTATUS status;
7415 struct sockaddr_storage addr;
7416 struct tevent_context *ev;
7417 struct tevent_req *req;
7418 char *basedn;
7419 const char *filter;
7421 if (!resolve_name(host, &addr, 0, false)) {
7422 d_printf("could not find host %s\n", host);
7423 return false;
7425 status = open_socket_out(&addr, 389, 9999, &fd);
7426 if (!NT_STATUS_IS_OK(status)) {
7427 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
7428 return false;
7431 ld = tldap_context_create(talloc_tos(), fd);
7432 if (ld == NULL) {
7433 close(fd);
7434 d_printf("tldap_context_create failed\n");
7435 return false;
7438 rc = tldap_fetch_rootdse(ld);
7439 if (rc != TLDAP_SUCCESS) {
7440 d_printf("tldap_fetch_rootdse failed: %s\n",
7441 tldap_errstr(talloc_tos(), ld, rc));
7442 return false;
7445 basedn = tldap_talloc_single_attribute(
7446 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
7447 if (basedn == NULL) {
7448 d_printf("no defaultNamingContext\n");
7449 return false;
7451 d_printf("defaultNamingContext: %s\n", basedn);
7453 ev = tevent_context_init(talloc_tos());
7454 if (ev == NULL) {
7455 d_printf("tevent_context_init failed\n");
7456 return false;
7459 req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
7460 TLDAP_SCOPE_SUB, "(objectclass=*)",
7461 NULL, 0, 0,
7462 NULL, 0, NULL, 0, 0, 0, 0, 5);
7463 if (req == NULL) {
7464 d_printf("tldap_search_paged_send failed\n");
7465 return false;
7467 tevent_req_set_callback(req, pagedsearch_cb, NULL);
7469 tevent_req_poll(req, ev);
7471 TALLOC_FREE(req);
7473 /* test search filters against rootDSE */
7474 filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
7475 "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
7477 rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
7478 NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
7479 talloc_tos(), NULL, NULL);
7480 if (rc != TLDAP_SUCCESS) {
7481 d_printf("tldap_search with complex filter failed: %s\n",
7482 tldap_errstr(talloc_tos(), ld, rc));
7483 return false;
7486 TALLOC_FREE(ld);
7487 return true;
7490 /* Torture test to ensure no regression of :
7491 https://bugzilla.samba.org/show_bug.cgi?id=7084
7494 static bool run_dir_createtime(int dummy)
7496 struct cli_state *cli;
7497 const char *dname = "\\testdir";
7498 const char *fname = "\\testdir\\testfile";
7499 NTSTATUS status;
7500 struct timespec create_time;
7501 struct timespec create_time1;
7502 uint16_t fnum;
7503 bool ret = false;
7505 if (!torture_open_connection(&cli, 0)) {
7506 return false;
7509 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7510 cli_rmdir(cli, dname);
7512 status = cli_mkdir(cli, dname);
7513 if (!NT_STATUS_IS_OK(status)) {
7514 printf("mkdir failed: %s\n", nt_errstr(status));
7515 goto out;
7518 status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
7519 NULL, NULL, NULL);
7520 if (!NT_STATUS_IS_OK(status)) {
7521 printf("cli_qpathinfo2 returned %s\n",
7522 nt_errstr(status));
7523 goto out;
7526 /* Sleep 3 seconds, then create a file. */
7527 sleep(3);
7529 status = cli_open(cli, fname, O_RDWR | O_CREAT | O_EXCL,
7530 DENY_NONE, &fnum);
7531 if (!NT_STATUS_IS_OK(status)) {
7532 printf("cli_open failed: %s\n", nt_errstr(status));
7533 goto out;
7536 status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
7537 NULL, NULL, NULL);
7538 if (!NT_STATUS_IS_OK(status)) {
7539 printf("cli_qpathinfo2 (2) returned %s\n",
7540 nt_errstr(status));
7541 goto out;
7544 if (timespec_compare(&create_time1, &create_time)) {
7545 printf("run_dir_createtime: create time was updated (error)\n");
7546 } else {
7547 printf("run_dir_createtime: create time was not updated (correct)\n");
7548 ret = true;
7551 out:
7553 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7554 cli_rmdir(cli, dname);
7555 if (!torture_close_connection(cli)) {
7556 ret = false;
7558 return ret;
7562 static bool run_streamerror(int dummy)
7564 struct cli_state *cli;
7565 const char *dname = "\\testdir";
7566 const char *streamname =
7567 "testdir:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
7568 NTSTATUS status;
7569 time_t change_time, access_time, write_time;
7570 SMB_OFF_T size;
7571 uint16_t mode, fnum;
7572 bool ret = true;
7574 if (!torture_open_connection(&cli, 0)) {
7575 return false;
7578 cli_unlink(cli, "\\testdir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7579 cli_rmdir(cli, dname);
7581 status = cli_mkdir(cli, dname);
7582 if (!NT_STATUS_IS_OK(status)) {
7583 printf("mkdir failed: %s\n", nt_errstr(status));
7584 return false;
7587 cli_qpathinfo1(cli, streamname, &change_time, &access_time, &write_time,
7588 &size, &mode);
7589 status = cli_nt_error(cli);
7591 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7592 printf("pathinfo returned %s, expected "
7593 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
7594 nt_errstr(status));
7595 ret = false;
7598 status = cli_ntcreate(cli, streamname, 0x16,
7599 FILE_READ_DATA|FILE_READ_EA|
7600 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
7601 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7602 FILE_OPEN, 0, 0, &fnum);
7604 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7605 printf("ntcreate returned %s, expected "
7606 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
7607 nt_errstr(status));
7608 ret = false;
7612 cli_rmdir(cli, dname);
7613 return ret;
7616 static bool run_local_substitute(int dummy)
7618 bool ok = true;
7620 ok &= subst_test("%U", "bla", "", -1, -1, "bla");
7621 ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
7622 ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
7623 ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
7624 ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
7625 ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
7626 ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
7627 ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
7629 /* Different captialization rules in sub_basic... */
7631 ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
7632 "blaDOM") == 0);
7634 return ok;
7637 static bool run_local_base64(int dummy)
7639 int i;
7640 bool ret = true;
7642 for (i=1; i<2000; i++) {
7643 DATA_BLOB blob1, blob2;
7644 char *b64;
7646 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
7647 blob1.length = i;
7648 generate_random_buffer(blob1.data, blob1.length);
7650 b64 = base64_encode_data_blob(talloc_tos(), blob1);
7651 if (b64 == NULL) {
7652 d_fprintf(stderr, "base64_encode_data_blob failed "
7653 "for %d bytes\n", i);
7654 ret = false;
7656 blob2 = base64_decode_data_blob(b64);
7657 TALLOC_FREE(b64);
7659 if (data_blob_cmp(&blob1, &blob2)) {
7660 d_fprintf(stderr, "data_blob_cmp failed for %d "
7661 "bytes\n", i);
7662 ret = false;
7664 TALLOC_FREE(blob1.data);
7665 data_blob_free(&blob2);
7667 return ret;
7670 static bool run_local_gencache(int dummy)
7672 char *val;
7673 time_t tm;
7674 DATA_BLOB blob;
7676 if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
7677 d_printf("%s: gencache_set() failed\n", __location__);
7678 return False;
7681 if (!gencache_get("foo", NULL, NULL)) {
7682 d_printf("%s: gencache_get() failed\n", __location__);
7683 return False;
7686 if (!gencache_get("foo", &val, &tm)) {
7687 d_printf("%s: gencache_get() failed\n", __location__);
7688 return False;
7691 if (strcmp(val, "bar") != 0) {
7692 d_printf("%s: gencache_get() returned %s, expected %s\n",
7693 __location__, val, "bar");
7694 SAFE_FREE(val);
7695 return False;
7698 SAFE_FREE(val);
7700 if (!gencache_del("foo")) {
7701 d_printf("%s: gencache_del() failed\n", __location__);
7702 return False;
7704 if (gencache_del("foo")) {
7705 d_printf("%s: second gencache_del() succeeded\n",
7706 __location__);
7707 return False;
7710 if (gencache_get("foo", &val, &tm)) {
7711 d_printf("%s: gencache_get() on deleted entry "
7712 "succeeded\n", __location__);
7713 return False;
7716 blob = data_blob_string_const_null("bar");
7717 tm = time(NULL) + 60;
7719 if (!gencache_set_data_blob("foo", &blob, tm)) {
7720 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
7721 return False;
7724 if (!gencache_get_data_blob("foo", &blob, NULL, NULL)) {
7725 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
7726 return False;
7729 if (strcmp((const char *)blob.data, "bar") != 0) {
7730 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
7731 __location__, (const char *)blob.data, "bar");
7732 data_blob_free(&blob);
7733 return False;
7736 data_blob_free(&blob);
7738 if (!gencache_del("foo")) {
7739 d_printf("%s: gencache_del() failed\n", __location__);
7740 return False;
7742 if (gencache_del("foo")) {
7743 d_printf("%s: second gencache_del() succeeded\n",
7744 __location__);
7745 return False;
7748 if (gencache_get_data_blob("foo", &blob, NULL, NULL)) {
7749 d_printf("%s: gencache_get_data_blob() on deleted entry "
7750 "succeeded\n", __location__);
7751 return False;
7754 return True;
7757 static bool rbt_testval(struct db_context *db, const char *key,
7758 const char *value)
7760 struct db_record *rec;
7761 TDB_DATA data = string_tdb_data(value);
7762 bool ret = false;
7763 NTSTATUS status;
7765 rec = db->fetch_locked(db, db, string_tdb_data(key));
7766 if (rec == NULL) {
7767 d_fprintf(stderr, "fetch_locked failed\n");
7768 goto done;
7770 status = rec->store(rec, data, 0);
7771 if (!NT_STATUS_IS_OK(status)) {
7772 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
7773 goto done;
7775 TALLOC_FREE(rec);
7777 rec = db->fetch_locked(db, db, string_tdb_data(key));
7778 if (rec == NULL) {
7779 d_fprintf(stderr, "second fetch_locked failed\n");
7780 goto done;
7782 if ((rec->value.dsize != data.dsize)
7783 || (memcmp(rec->value.dptr, data.dptr, data.dsize) != 0)) {
7784 d_fprintf(stderr, "Got wrong data back\n");
7785 goto done;
7788 ret = true;
7789 done:
7790 TALLOC_FREE(rec);
7791 return ret;
7794 static bool run_local_rbtree(int dummy)
7796 struct db_context *db;
7797 bool ret = false;
7798 int i;
7800 db = db_open_rbt(NULL);
7802 if (db == NULL) {
7803 d_fprintf(stderr, "db_open_rbt failed\n");
7804 return false;
7807 for (i=0; i<1000; i++) {
7808 char *key, *value;
7810 if (asprintf(&key, "key%ld", random()) == -1) {
7811 goto done;
7813 if (asprintf(&value, "value%ld", random()) == -1) {
7814 SAFE_FREE(key);
7815 goto done;
7818 if (!rbt_testval(db, key, value)) {
7819 SAFE_FREE(key);
7820 SAFE_FREE(value);
7821 goto done;
7824 SAFE_FREE(value);
7825 if (asprintf(&value, "value%ld", random()) == -1) {
7826 SAFE_FREE(key);
7827 goto done;
7830 if (!rbt_testval(db, key, value)) {
7831 SAFE_FREE(key);
7832 SAFE_FREE(value);
7833 goto done;
7836 SAFE_FREE(key);
7837 SAFE_FREE(value);
7840 ret = true;
7842 done:
7843 TALLOC_FREE(db);
7844 return ret;
7849 local test for character set functions
7851 This is a very simple test for the functionality in convert_string_error()
7853 static bool run_local_convert_string(int dummy)
7855 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
7856 const char *test_strings[2] = { "March", "M\303\244rz" };
7857 char dst[7];
7858 int i;
7860 for (i=0; i<2; i++) {
7861 const char *str = test_strings[i];
7862 int len = strlen(str);
7863 size_t converted_size;
7864 bool ret;
7866 memset(dst, 'X', sizeof(dst));
7868 /* first try with real source length */
7869 ret = convert_string_error(CH_UNIX, CH_UTF8,
7870 str, len,
7871 dst, sizeof(dst),
7872 &converted_size);
7873 if (ret != true) {
7874 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
7875 goto failed;
7878 if (converted_size != len) {
7879 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
7880 str, len, (int)converted_size);
7881 goto failed;
7884 if (strncmp(str, dst, converted_size) != 0) {
7885 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
7886 goto failed;
7889 if (strlen(str) != converted_size) {
7890 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
7891 (int)strlen(str), (int)converted_size);
7892 goto failed;
7895 if (dst[converted_size] != 'X') {
7896 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
7897 goto failed;
7900 /* now with srclen==-1, this causes the nul to be
7901 * converted too */
7902 ret = convert_string_error(CH_UNIX, CH_UTF8,
7903 str, -1,
7904 dst, sizeof(dst),
7905 &converted_size);
7906 if (ret != true) {
7907 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
7908 goto failed;
7911 if (converted_size != len+1) {
7912 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
7913 str, len, (int)converted_size);
7914 goto failed;
7917 if (strncmp(str, dst, converted_size) != 0) {
7918 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
7919 goto failed;
7922 if (len+1 != converted_size) {
7923 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
7924 len+1, (int)converted_size);
7925 goto failed;
7928 if (dst[converted_size] != 'X') {
7929 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
7930 goto failed;
7936 TALLOC_FREE(tmp_ctx);
7937 return true;
7938 failed:
7939 TALLOC_FREE(tmp_ctx);
7940 return false;
7944 struct talloc_dict_test {
7945 int content;
7948 static int talloc_dict_traverse_fn(DATA_BLOB key, void *data, void *priv)
7950 int *count = (int *)priv;
7951 *count += 1;
7952 return 0;
7955 static bool run_local_talloc_dict(int dummy)
7957 struct talloc_dict *dict;
7958 struct talloc_dict_test *t;
7959 int key, count;
7961 dict = talloc_dict_init(talloc_tos());
7962 if (dict == NULL) {
7963 return false;
7966 t = talloc(talloc_tos(), struct talloc_dict_test);
7967 if (t == NULL) {
7968 return false;
7971 key = 1;
7972 t->content = 1;
7973 if (!talloc_dict_set(dict, data_blob_const(&key, sizeof(key)), t)) {
7974 return false;
7977 count = 0;
7978 if (talloc_dict_traverse(dict, talloc_dict_traverse_fn, &count) != 0) {
7979 return false;
7982 if (count != 1) {
7983 return false;
7986 TALLOC_FREE(dict);
7988 return true;
7991 static bool run_local_string_to_sid(int dummy) {
7992 struct dom_sid sid;
7994 if (string_to_sid(&sid, "S--1-5-32-545")) {
7995 printf("allowing S--1-5-32-545\n");
7996 return false;
7998 if (string_to_sid(&sid, "S-1-5-32-+545")) {
7999 printf("allowing S-1-5-32-+545\n");
8000 return false;
8002 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")) {
8003 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
8004 return false;
8006 if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
8007 printf("allowing S-1-5-32-545-abc\n");
8008 return false;
8010 if (!string_to_sid(&sid, "S-1-5-32-545")) {
8011 printf("could not parse S-1-5-32-545\n");
8012 return false;
8014 if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
8015 printf("mis-parsed S-1-5-32-545 as %s\n",
8016 sid_string_tos(&sid));
8017 return false;
8019 return true;
8022 static bool run_local_binary_to_sid(int dummy) {
8023 struct dom_sid *sid = talloc(NULL, struct dom_sid);
8024 static const char good_binary_sid[] = {
8025 0x1, /* revision number */
8026 15, /* num auths */
8027 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8028 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8029 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8030 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8031 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8032 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8033 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8034 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8035 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8036 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8037 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8038 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8039 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8040 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8041 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8042 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8045 static const char long_binary_sid[] = {
8046 0x1, /* revision number */
8047 15, /* num auths */
8048 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8049 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8050 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8051 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8052 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8053 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8054 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8055 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8056 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8057 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8058 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8059 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8060 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8061 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8062 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8063 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8064 0x1, 0x1, 0x1, 0x1, /* auth[15] */
8065 0x1, 0x1, 0x1, 0x1, /* auth[16] */
8066 0x1, 0x1, 0x1, 0x1, /* auth[17] */
8069 static const char long_binary_sid2[] = {
8070 0x1, /* revision number */
8071 32, /* num auths */
8072 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8073 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8074 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8075 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8076 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8077 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8078 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8079 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8080 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8081 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8082 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8083 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8084 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8085 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8086 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8087 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8088 0x1, 0x1, 0x1, 0x1, /* auth[15] */
8089 0x1, 0x1, 0x1, 0x1, /* auth[16] */
8090 0x1, 0x1, 0x1, 0x1, /* auth[17] */
8091 0x1, 0x1, 0x1, 0x1, /* auth[18] */
8092 0x1, 0x1, 0x1, 0x1, /* auth[19] */
8093 0x1, 0x1, 0x1, 0x1, /* auth[20] */
8094 0x1, 0x1, 0x1, 0x1, /* auth[21] */
8095 0x1, 0x1, 0x1, 0x1, /* auth[22] */
8096 0x1, 0x1, 0x1, 0x1, /* auth[23] */
8097 0x1, 0x1, 0x1, 0x1, /* auth[24] */
8098 0x1, 0x1, 0x1, 0x1, /* auth[25] */
8099 0x1, 0x1, 0x1, 0x1, /* auth[26] */
8100 0x1, 0x1, 0x1, 0x1, /* auth[27] */
8101 0x1, 0x1, 0x1, 0x1, /* auth[28] */
8102 0x1, 0x1, 0x1, 0x1, /* auth[29] */
8103 0x1, 0x1, 0x1, 0x1, /* auth[30] */
8104 0x1, 0x1, 0x1, 0x1, /* auth[31] */
8107 if (!sid_parse(good_binary_sid, sizeof(good_binary_sid), sid)) {
8108 return false;
8110 if (sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid)) {
8111 return false;
8113 if (sid_parse(long_binary_sid, sizeof(long_binary_sid), sid)) {
8114 return false;
8116 return true;
8119 /* Split a path name into filename and stream name components. Canonicalise
8120 * such that an implicit $DATA token is always explicit.
8122 * The "specification" of this function can be found in the
8123 * run_local_stream_name() function in torture.c, I've tried those
8124 * combinations against a W2k3 server.
8127 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
8128 char **pbase, char **pstream)
8130 char *base = NULL;
8131 char *stream = NULL;
8132 char *sname; /* stream name */
8133 const char *stype; /* stream type */
8135 DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
8137 sname = strchr_m(fname, ':');
8139 if (lp_posix_pathnames() || (sname == NULL)) {
8140 if (pbase != NULL) {
8141 base = talloc_strdup(mem_ctx, fname);
8142 NT_STATUS_HAVE_NO_MEMORY(base);
8144 goto done;
8147 if (pbase != NULL) {
8148 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
8149 NT_STATUS_HAVE_NO_MEMORY(base);
8152 sname += 1;
8154 stype = strchr_m(sname, ':');
8156 if (stype == NULL) {
8157 sname = talloc_strdup(mem_ctx, sname);
8158 stype = "$DATA";
8160 else {
8161 if (strcasecmp_m(stype, ":$DATA") != 0) {
8163 * If there is an explicit stream type, so far we only
8164 * allow $DATA. Is there anything else allowed? -- vl
8166 DEBUG(10, ("[%s] is an invalid stream type\n", stype));
8167 TALLOC_FREE(base);
8168 return NT_STATUS_OBJECT_NAME_INVALID;
8170 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
8171 stype += 1;
8174 if (sname == NULL) {
8175 TALLOC_FREE(base);
8176 return NT_STATUS_NO_MEMORY;
8179 if (sname[0] == '\0') {
8181 * no stream name, so no stream
8183 goto done;
8186 if (pstream != NULL) {
8187 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
8188 if (stream == NULL) {
8189 TALLOC_FREE(sname);
8190 TALLOC_FREE(base);
8191 return NT_STATUS_NO_MEMORY;
8194 * upper-case the type field
8196 strupper_m(strchr_m(stream, ':')+1);
8199 done:
8200 if (pbase != NULL) {
8201 *pbase = base;
8203 if (pstream != NULL) {
8204 *pstream = stream;
8206 return NT_STATUS_OK;
8209 static bool test_stream_name(const char *fname, const char *expected_base,
8210 const char *expected_stream,
8211 NTSTATUS expected_status)
8213 NTSTATUS status;
8214 char *base = NULL;
8215 char *stream = NULL;
8217 status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
8218 if (!NT_STATUS_EQUAL(status, expected_status)) {
8219 goto error;
8222 if (!NT_STATUS_IS_OK(status)) {
8223 return true;
8226 if (base == NULL) goto error;
8228 if (strcmp(expected_base, base) != 0) goto error;
8230 if ((expected_stream != NULL) && (stream == NULL)) goto error;
8231 if ((expected_stream == NULL) && (stream != NULL)) goto error;
8233 if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
8234 goto error;
8236 TALLOC_FREE(base);
8237 TALLOC_FREE(stream);
8238 return true;
8240 error:
8241 d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
8242 fname, expected_base ? expected_base : "<NULL>",
8243 expected_stream ? expected_stream : "<NULL>",
8244 nt_errstr(expected_status));
8245 d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
8246 base ? base : "<NULL>", stream ? stream : "<NULL>",
8247 nt_errstr(status));
8248 TALLOC_FREE(base);
8249 TALLOC_FREE(stream);
8250 return false;
8253 static bool run_local_stream_name(int dummy)
8255 bool ret = true;
8257 ret &= test_stream_name(
8258 "bla", "bla", NULL, NT_STATUS_OK);
8259 ret &= test_stream_name(
8260 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
8261 ret &= test_stream_name(
8262 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8263 ret &= test_stream_name(
8264 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
8265 ret &= test_stream_name(
8266 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8267 ret &= test_stream_name(
8268 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
8269 ret &= test_stream_name(
8270 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
8271 ret &= test_stream_name(
8272 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
8274 return ret;
8277 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
8279 if (a.length != b.length) {
8280 printf("a.length=%d != b.length=%d\n",
8281 (int)a.length, (int)b.length);
8282 return false;
8284 if (memcmp(a.data, b.data, a.length) != 0) {
8285 printf("a.data and b.data differ\n");
8286 return false;
8288 return true;
8291 static bool run_local_memcache(int dummy)
8293 struct memcache *cache;
8294 DATA_BLOB k1, k2;
8295 DATA_BLOB d1, d2, d3;
8296 DATA_BLOB v1, v2, v3;
8298 TALLOC_CTX *mem_ctx;
8299 char *str1, *str2;
8300 size_t size1, size2;
8301 bool ret = false;
8303 cache = memcache_init(NULL, 100);
8305 if (cache == NULL) {
8306 printf("memcache_init failed\n");
8307 return false;
8310 d1 = data_blob_const("d1", 2);
8311 d2 = data_blob_const("d2", 2);
8312 d3 = data_blob_const("d3", 2);
8314 k1 = data_blob_const("d1", 2);
8315 k2 = data_blob_const("d2", 2);
8317 memcache_add(cache, STAT_CACHE, k1, d1);
8318 memcache_add(cache, GETWD_CACHE, k2, d2);
8320 if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
8321 printf("could not find k1\n");
8322 return false;
8324 if (!data_blob_equal(d1, v1)) {
8325 return false;
8328 if (!memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8329 printf("could not find k2\n");
8330 return false;
8332 if (!data_blob_equal(d2, v2)) {
8333 return false;
8336 memcache_add(cache, STAT_CACHE, k1, d3);
8338 if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
8339 printf("could not find replaced k1\n");
8340 return false;
8342 if (!data_blob_equal(d3, v3)) {
8343 return false;
8346 memcache_add(cache, GETWD_CACHE, k1, d1);
8348 if (memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8349 printf("Did find k2, should have been purged\n");
8350 return false;
8353 TALLOC_FREE(cache);
8355 cache = memcache_init(NULL, 0);
8357 mem_ctx = talloc_init("foo");
8359 str1 = talloc_strdup(mem_ctx, "string1");
8360 str2 = talloc_strdup(mem_ctx, "string2");
8362 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8363 data_blob_string_const("torture"), &str1);
8364 size1 = talloc_total_size(cache);
8366 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8367 data_blob_string_const("torture"), &str2);
8368 size2 = talloc_total_size(cache);
8370 printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
8372 if (size2 > size1) {
8373 printf("memcache leaks memory!\n");
8374 goto fail;
8377 ret = true;
8378 fail:
8379 TALLOC_FREE(cache);
8380 return ret;
8383 static void wbclient_done(struct tevent_req *req)
8385 wbcErr wbc_err;
8386 struct winbindd_response *wb_resp;
8387 int *i = (int *)tevent_req_callback_data_void(req);
8389 wbc_err = wb_trans_recv(req, req, &wb_resp);
8390 TALLOC_FREE(req);
8391 *i += 1;
8392 d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
8395 static bool run_local_wbclient(int dummy)
8397 struct event_context *ev;
8398 struct wb_context **wb_ctx;
8399 struct winbindd_request wb_req;
8400 bool result = false;
8401 int i, j;
8403 BlockSignals(True, SIGPIPE);
8405 ev = tevent_context_init_byname(talloc_tos(), "epoll");
8406 if (ev == NULL) {
8407 goto fail;
8410 wb_ctx = talloc_array(ev, struct wb_context *, nprocs);
8411 if (wb_ctx == NULL) {
8412 goto fail;
8415 ZERO_STRUCT(wb_req);
8416 wb_req.cmd = WINBINDD_PING;
8418 d_printf("nprocs=%d, numops=%d\n", (int)nprocs, (int)torture_numops);
8420 for (i=0; i<nprocs; i++) {
8421 wb_ctx[i] = wb_context_init(ev, NULL);
8422 if (wb_ctx[i] == NULL) {
8423 goto fail;
8425 for (j=0; j<torture_numops; j++) {
8426 struct tevent_req *req;
8427 req = wb_trans_send(ev, ev, wb_ctx[i],
8428 (j % 2) == 0, &wb_req);
8429 if (req == NULL) {
8430 goto fail;
8432 tevent_req_set_callback(req, wbclient_done, &i);
8436 i = 0;
8438 while (i < nprocs * torture_numops) {
8439 tevent_loop_once(ev);
8442 result = true;
8443 fail:
8444 TALLOC_FREE(ev);
8445 return result;
8448 static void getaddrinfo_finished(struct tevent_req *req)
8450 char *name = (char *)tevent_req_callback_data_void(req);
8451 struct addrinfo *ainfo;
8452 int res;
8454 res = getaddrinfo_recv(req, &ainfo);
8455 if (res != 0) {
8456 d_printf("gai(%s) returned %s\n", name, gai_strerror(res));
8457 return;
8459 d_printf("gai(%s) succeeded\n", name);
8460 freeaddrinfo(ainfo);
8463 static bool run_getaddrinfo_send(int dummy)
8465 TALLOC_CTX *frame = talloc_stackframe();
8466 struct fncall_context *ctx;
8467 struct tevent_context *ev;
8468 bool result = false;
8469 const char *names[4] = { "www.samba.org", "notfound.samba.org",
8470 "www.slashdot.org", "heise.de" };
8471 struct tevent_req *reqs[4];
8472 int i;
8474 ev = event_context_init(frame);
8475 if (ev == NULL) {
8476 goto fail;
8479 ctx = fncall_context_init(frame, 4);
8481 for (i=0; i<ARRAY_SIZE(names); i++) {
8482 reqs[i] = getaddrinfo_send(frame, ev, ctx, names[i], NULL,
8483 NULL);
8484 if (reqs[i] == NULL) {
8485 goto fail;
8487 tevent_req_set_callback(reqs[i], getaddrinfo_finished,
8488 discard_const_p(void, names[i]));
8491 for (i=0; i<ARRAY_SIZE(reqs); i++) {
8492 tevent_loop_once(ev);
8495 result = true;
8496 fail:
8497 TALLOC_FREE(frame);
8498 return result;
8501 static bool dbtrans_inc(struct db_context *db)
8503 struct db_record *rec;
8504 uint32_t *val;
8505 bool ret = false;
8506 NTSTATUS status;
8508 rec = db->fetch_locked(db, db, string_term_tdb_data("transtest"));
8509 if (rec == NULL) {
8510 printf(__location__ "fetch_lock failed\n");
8511 return false;
8514 if (rec->value.dsize != sizeof(uint32_t)) {
8515 printf(__location__ "value.dsize = %d\n",
8516 (int)rec->value.dsize);
8517 goto fail;
8520 val = (uint32_t *)rec->value.dptr;
8521 *val += 1;
8523 status = rec->store(rec, make_tdb_data((uint8_t *)val,
8524 sizeof(uint32_t)),
8526 if (!NT_STATUS_IS_OK(status)) {
8527 printf(__location__ "store failed: %s\n",
8528 nt_errstr(status));
8529 goto fail;
8532 ret = true;
8533 fail:
8534 TALLOC_FREE(rec);
8535 return ret;
8538 static bool run_local_dbtrans(int dummy)
8540 struct db_context *db;
8541 struct db_record *rec;
8542 NTSTATUS status;
8543 uint32_t initial;
8544 int res;
8546 db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
8547 O_RDWR|O_CREAT, 0600);
8548 if (db == NULL) {
8549 printf("Could not open transtest.db\n");
8550 return false;
8553 res = db->transaction_start(db);
8554 if (res != 0) {
8555 printf(__location__ "transaction_start failed\n");
8556 return false;
8559 rec = db->fetch_locked(db, db, string_term_tdb_data("transtest"));
8560 if (rec == NULL) {
8561 printf(__location__ "fetch_lock failed\n");
8562 return false;
8565 if (rec->value.dptr == NULL) {
8566 initial = 0;
8567 status = rec->store(
8568 rec, make_tdb_data((uint8_t *)&initial,
8569 sizeof(initial)),
8571 if (!NT_STATUS_IS_OK(status)) {
8572 printf(__location__ "store returned %s\n",
8573 nt_errstr(status));
8574 return false;
8578 TALLOC_FREE(rec);
8580 res = db->transaction_commit(db);
8581 if (res != 0) {
8582 printf(__location__ "transaction_commit failed\n");
8583 return false;
8586 while (true) {
8587 uint32_t val, val2;
8588 int i;
8590 res = db->transaction_start(db);
8591 if (res != 0) {
8592 printf(__location__ "transaction_start failed\n");
8593 break;
8596 if (!dbwrap_fetch_uint32(db, "transtest", &val)) {
8597 printf(__location__ "dbwrap_fetch_uint32 failed\n");
8598 break;
8601 for (i=0; i<10; i++) {
8602 if (!dbtrans_inc(db)) {
8603 return false;
8607 if (!dbwrap_fetch_uint32(db, "transtest", &val2)) {
8608 printf(__location__ "dbwrap_fetch_uint32 failed\n");
8609 break;
8612 if (val2 != val + 10) {
8613 printf(__location__ "val=%d, val2=%d\n",
8614 (int)val, (int)val2);
8615 break;
8618 printf("val2=%d\r", val2);
8620 res = db->transaction_commit(db);
8621 if (res != 0) {
8622 printf(__location__ "transaction_commit failed\n");
8623 break;
8627 TALLOC_FREE(db);
8628 return true;
8632 * Just a dummy test to be run under a debugger. There's no real way
8633 * to inspect the tevent_select specific function from outside of
8634 * tevent_select.c.
8637 static bool run_local_tevent_select(int dummy)
8639 struct tevent_context *ev;
8640 struct tevent_fd *fd1, *fd2;
8641 bool result = false;
8643 ev = tevent_context_init_byname(NULL, "select");
8644 if (ev == NULL) {
8645 d_fprintf(stderr, "tevent_context_init_byname failed\n");
8646 goto fail;
8649 fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
8650 if (fd1 == NULL) {
8651 d_fprintf(stderr, "tevent_add_fd failed\n");
8652 goto fail;
8654 fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
8655 if (fd2 == NULL) {
8656 d_fprintf(stderr, "tevent_add_fd failed\n");
8657 goto fail;
8659 TALLOC_FREE(fd2);
8661 fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
8662 if (fd2 == NULL) {
8663 d_fprintf(stderr, "tevent_add_fd failed\n");
8664 goto fail;
8667 result = true;
8668 fail:
8669 TALLOC_FREE(ev);
8670 return result;
8673 static double create_procs(bool (*fn)(int), bool *result)
8675 int i, status;
8676 volatile pid_t *child_status;
8677 volatile bool *child_status_out;
8678 int synccount;
8679 int tries = 8;
8680 struct timeval start;
8682 synccount = 0;
8684 child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*nprocs);
8685 if (!child_status) {
8686 printf("Failed to setup shared memory\n");
8687 return -1;
8690 child_status_out = (volatile bool *)shm_setup(sizeof(bool)*nprocs);
8691 if (!child_status_out) {
8692 printf("Failed to setup result status shared memory\n");
8693 return -1;
8696 for (i = 0; i < nprocs; i++) {
8697 child_status[i] = 0;
8698 child_status_out[i] = True;
8701 start = timeval_current();
8703 for (i=0;i<nprocs;i++) {
8704 procnum = i;
8705 if (fork() == 0) {
8706 pid_t mypid = getpid();
8707 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
8709 slprintf(myname,sizeof(myname),"CLIENT%d", i);
8711 while (1) {
8712 if (torture_open_connection(&current_cli, i)) break;
8713 if (tries-- == 0) {
8714 printf("pid %d failed to start\n", (int)getpid());
8715 _exit(1);
8717 smb_msleep(10);
8720 child_status[i] = getpid();
8722 while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
8724 child_status_out[i] = fn(i);
8725 _exit(0);
8729 do {
8730 synccount = 0;
8731 for (i=0;i<nprocs;i++) {
8732 if (child_status[i]) synccount++;
8734 if (synccount == nprocs) break;
8735 smb_msleep(10);
8736 } while (timeval_elapsed(&start) < 30);
8738 if (synccount != nprocs) {
8739 printf("FAILED TO START %d CLIENTS (started %d)\n", nprocs, synccount);
8740 *result = False;
8741 return timeval_elapsed(&start);
8744 /* start the client load */
8745 start = timeval_current();
8747 for (i=0;i<nprocs;i++) {
8748 child_status[i] = 0;
8751 printf("%d clients started\n", nprocs);
8753 for (i=0;i<nprocs;i++) {
8754 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
8757 printf("\n");
8759 for (i=0;i<nprocs;i++) {
8760 if (!child_status_out[i]) {
8761 *result = False;
8764 return timeval_elapsed(&start);
8767 #define FLAG_MULTIPROC 1
8769 static struct {
8770 const char *name;
8771 bool (*fn)(int);
8772 unsigned flags;
8773 } torture_ops[] = {
8774 {"FDPASS", run_fdpasstest, 0},
8775 {"LOCK1", run_locktest1, 0},
8776 {"LOCK2", run_locktest2, 0},
8777 {"LOCK3", run_locktest3, 0},
8778 {"LOCK4", run_locktest4, 0},
8779 {"LOCK5", run_locktest5, 0},
8780 {"LOCK6", run_locktest6, 0},
8781 {"LOCK7", run_locktest7, 0},
8782 {"LOCK8", run_locktest8, 0},
8783 {"LOCK9", run_locktest9, 0},
8784 {"UNLINK", run_unlinktest, 0},
8785 {"BROWSE", run_browsetest, 0},
8786 {"ATTR", run_attrtest, 0},
8787 {"TRANS2", run_trans2test, 0},
8788 {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
8789 {"TORTURE",run_torture, FLAG_MULTIPROC},
8790 {"RANDOMIPC", run_randomipc, 0},
8791 {"NEGNOWAIT", run_negprot_nowait, 0},
8792 {"NBENCH", run_nbench, 0},
8793 {"NBENCH2", run_nbench2, 0},
8794 {"OPLOCK1", run_oplock1, 0},
8795 {"OPLOCK2", run_oplock2, 0},
8796 {"OPLOCK4", run_oplock4, 0},
8797 {"DIR", run_dirtest, 0},
8798 {"DIR1", run_dirtest1, 0},
8799 {"DIR-CREATETIME", run_dir_createtime, 0},
8800 {"DENY1", torture_denytest1, 0},
8801 {"DENY2", torture_denytest2, 0},
8802 {"TCON", run_tcon_test, 0},
8803 {"TCONDEV", run_tcon_devtype_test, 0},
8804 {"RW1", run_readwritetest, 0},
8805 {"RW2", run_readwritemulti, FLAG_MULTIPROC},
8806 {"RW3", run_readwritelarge, 0},
8807 {"RW-SIGNING", run_readwritelarge_signtest, 0},
8808 {"OPEN", run_opentest, 0},
8809 {"POSIX", run_simple_posix_open_test, 0},
8810 {"POSIX-APPEND", run_posix_append, 0},
8811 {"CASE-INSENSITIVE-CREATE", run_case_insensitive_create, 0},
8812 {"ASYNC-ECHO", run_async_echo, 0},
8813 { "UID-REGRESSION-TEST", run_uid_regression_test, 0},
8814 { "SHORTNAME-TEST", run_shortname_test, 0},
8815 { "ADDRCHANGE", run_addrchange, 0},
8816 #if 1
8817 {"OPENATTR", run_openattrtest, 0},
8818 #endif
8819 {"XCOPY", run_xcopy, 0},
8820 {"RENAME", run_rename, 0},
8821 {"DELETE", run_deletetest, 0},
8822 {"DELETE-LN", run_deletetest_ln, 0},
8823 {"PROPERTIES", run_properties, 0},
8824 {"MANGLE", torture_mangle, 0},
8825 {"MANGLE1", run_mangle1, 0},
8826 {"W2K", run_w2ktest, 0},
8827 {"TRANS2SCAN", torture_trans2_scan, 0},
8828 {"NTTRANSSCAN", torture_nttrans_scan, 0},
8829 {"UTABLE", torture_utable, 0},
8830 {"CASETABLE", torture_casetable, 0},
8831 {"ERRMAPEXTRACT", run_error_map_extract, 0},
8832 {"PIPE_NUMBER", run_pipe_number, 0},
8833 {"TCON2", run_tcon2_test, 0},
8834 {"IOCTL", torture_ioctl_test, 0},
8835 {"CHKPATH", torture_chkpath_test, 0},
8836 {"FDSESS", run_fdsesstest, 0},
8837 { "EATEST", run_eatest, 0},
8838 { "SESSSETUP_BENCH", run_sesssetup_bench, 0},
8839 { "CHAIN1", run_chain1, 0},
8840 { "CHAIN2", run_chain2, 0},
8841 { "WINDOWS-WRITE", run_windows_write, 0},
8842 { "NTTRANS-CREATE", run_nttrans_create, 0},
8843 { "CLI_ECHO", run_cli_echo, 0},
8844 { "GETADDRINFO", run_getaddrinfo_send, 0},
8845 { "TLDAP", run_tldap },
8846 { "STREAMERROR", run_streamerror },
8847 { "NOTIFY-BENCH", run_notify_bench },
8848 { "BAD-NBT-SESSION", run_bad_nbt_session },
8849 { "SMB-ANY-CONNECT", run_smb_any_connect },
8850 { "NOTIFY-ONLINE", run_notify_online },
8851 { "SMB2-BASIC", run_smb2_basic },
8852 { "LOCAL-SUBSTITUTE", run_local_substitute, 0},
8853 { "LOCAL-GENCACHE", run_local_gencache, 0},
8854 { "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0},
8855 { "LOCAL-BASE64", run_local_base64, 0},
8856 { "LOCAL-RBTREE", run_local_rbtree, 0},
8857 { "LOCAL-MEMCACHE", run_local_memcache, 0},
8858 { "LOCAL-STREAM-NAME", run_local_stream_name, 0},
8859 { "LOCAL-WBCLIENT", run_local_wbclient, 0},
8860 { "LOCAL-string_to_sid", run_local_string_to_sid, 0},
8861 { "LOCAL-binary_to_sid", run_local_binary_to_sid, 0},
8862 { "LOCAL-DBTRANS", run_local_dbtrans, 0},
8863 { "LOCAL-TEVENT-SELECT", run_local_tevent_select, 0},
8864 { "LOCAL-CONVERT-STRING", run_local_convert_string, 0},
8865 {NULL, NULL, 0}};
8869 /****************************************************************************
8870 run a specified test or "ALL"
8871 ****************************************************************************/
8872 static bool run_test(const char *name)
8874 bool ret = True;
8875 bool result = True;
8876 bool found = False;
8877 int i;
8878 double t;
8879 if (strequal(name,"ALL")) {
8880 for (i=0;torture_ops[i].name;i++) {
8881 run_test(torture_ops[i].name);
8883 found = True;
8886 for (i=0;torture_ops[i].name;i++) {
8887 fstr_sprintf(randomfname, "\\XX%x",
8888 (unsigned)random());
8890 if (strequal(name, torture_ops[i].name)) {
8891 found = True;
8892 printf("Running %s\n", name);
8893 if (torture_ops[i].flags & FLAG_MULTIPROC) {
8894 t = create_procs(torture_ops[i].fn, &result);
8895 if (!result) {
8896 ret = False;
8897 printf("TEST %s FAILED!\n", name);
8899 } else {
8900 struct timeval start;
8901 start = timeval_current();
8902 if (!torture_ops[i].fn(0)) {
8903 ret = False;
8904 printf("TEST %s FAILED!\n", name);
8906 t = timeval_elapsed(&start);
8908 printf("%s took %g secs\n\n", name, t);
8912 if (!found) {
8913 printf("Did not find a test named %s\n", name);
8914 ret = False;
8917 return ret;
8921 static void usage(void)
8923 int i;
8925 printf("WARNING samba4 test suite is much more complete nowadays.\n");
8926 printf("Please use samba4 torture.\n\n");
8928 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
8930 printf("\t-d debuglevel\n");
8931 printf("\t-U user%%pass\n");
8932 printf("\t-k use kerberos\n");
8933 printf("\t-N numprocs\n");
8934 printf("\t-n my_netbios_name\n");
8935 printf("\t-W workgroup\n");
8936 printf("\t-o num_operations\n");
8937 printf("\t-O socket_options\n");
8938 printf("\t-m maximum protocol\n");
8939 printf("\t-L use oplocks\n");
8940 printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
8941 printf("\t-A showall\n");
8942 printf("\t-p port\n");
8943 printf("\t-s seed\n");
8944 printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
8945 printf("\t-f filename filename to test\n");
8946 printf("\n\n");
8948 printf("tests are:");
8949 for (i=0;torture_ops[i].name;i++) {
8950 printf(" %s", torture_ops[i].name);
8952 printf("\n");
8954 printf("default test is ALL\n");
8956 exit(1);
8959 /****************************************************************************
8960 main program
8961 ****************************************************************************/
8962 int main(int argc,char *argv[])
8964 int opt, i;
8965 char *p;
8966 int gotuser = 0;
8967 int gotpass = 0;
8968 bool correct = True;
8969 TALLOC_CTX *frame = talloc_stackframe();
8970 int seed = time(NULL);
8972 #ifdef HAVE_SETBUFFER
8973 setbuffer(stdout, NULL, 0);
8974 #endif
8976 setup_logging("smbtorture", DEBUG_STDOUT);
8978 load_case_tables();
8980 if (is_default_dyn_CONFIGFILE()) {
8981 if(getenv("SMB_CONF_PATH")) {
8982 set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
8985 lp_load_global(get_dyn_CONFIGFILE());
8986 load_interfaces();
8988 if (argc < 2) {
8989 usage();
8992 for(p = argv[1]; *p; p++)
8993 if(*p == '\\')
8994 *p = '/';
8996 if (strncmp(argv[1], "//", 2)) {
8997 usage();
9000 fstrcpy(host, &argv[1][2]);
9001 p = strchr_m(&host[2],'/');
9002 if (!p) {
9003 usage();
9005 *p = 0;
9006 fstrcpy(share, p+1);
9008 fstrcpy(myname, get_myname(talloc_tos()));
9009 if (!*myname) {
9010 fprintf(stderr, "Failed to get my hostname.\n");
9011 return 1;
9014 if (*username == 0 && getenv("LOGNAME")) {
9015 fstrcpy(username,getenv("LOGNAME"));
9018 argc--;
9019 argv++;
9021 fstrcpy(workgroup, lp_workgroup());
9023 while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
9024 != EOF) {
9025 switch (opt) {
9026 case 'p':
9027 port_to_use = atoi(optarg);
9028 break;
9029 case 's':
9030 seed = atoi(optarg);
9031 break;
9032 case 'W':
9033 fstrcpy(workgroup,optarg);
9034 break;
9035 case 'm':
9036 max_protocol = interpret_protocol(optarg, max_protocol);
9037 break;
9038 case 'N':
9039 nprocs = atoi(optarg);
9040 break;
9041 case 'o':
9042 torture_numops = atoi(optarg);
9043 break;
9044 case 'd':
9045 lp_set_cmdline("log level", optarg);
9046 break;
9047 case 'O':
9048 sockops = optarg;
9049 break;
9050 case 'L':
9051 use_oplocks = True;
9052 break;
9053 case 'l':
9054 local_path = optarg;
9055 break;
9056 case 'A':
9057 torture_showall = True;
9058 break;
9059 case 'n':
9060 fstrcpy(myname, optarg);
9061 break;
9062 case 'c':
9063 client_txt = optarg;
9064 break;
9065 case 'e':
9066 do_encrypt = true;
9067 break;
9068 case 'k':
9069 #ifdef HAVE_KRB5
9070 use_kerberos = True;
9071 #else
9072 d_printf("No kerberos support compiled in\n");
9073 exit(1);
9074 #endif
9075 break;
9076 case 'U':
9077 gotuser = 1;
9078 fstrcpy(username,optarg);
9079 p = strchr_m(username,'%');
9080 if (p) {
9081 *p = 0;
9082 fstrcpy(password, p+1);
9083 gotpass = 1;
9085 break;
9086 case 'b':
9087 fstrcpy(multishare_conn_fname, optarg);
9088 use_multishare_conn = True;
9089 break;
9090 case 'B':
9091 torture_blocksize = atoi(optarg);
9092 break;
9093 case 'f':
9094 test_filename = SMB_STRDUP(optarg);
9095 break;
9096 default:
9097 printf("Unknown option %c (%d)\n", (char)opt, opt);
9098 usage();
9102 d_printf("using seed %d\n", seed);
9104 srandom(seed);
9106 if(use_kerberos && !gotuser) gotpass = True;
9108 while (!gotpass) {
9109 p = getpass("Password:");
9110 if (p) {
9111 fstrcpy(password, p);
9112 gotpass = 1;
9116 printf("host=%s share=%s user=%s myname=%s\n",
9117 host, share, username, myname);
9119 if (argc == optind) {
9120 correct = run_test("ALL");
9121 } else {
9122 for (i=optind;i<argc;i++) {
9123 if (!run_test(argv[i])) {
9124 correct = False;
9129 TALLOC_FREE(frame);
9131 if (correct) {
9132 return(0);
9133 } else {
9134 return(1);