s3-torture: run_locktest5(): replace cli_lock() with cli_lock32()
[Samba/gebeck_regimport.git] / source3 / torture / torture.c
blob39d7ad3005a80368f883d4276ba2567bb3d8e3be
1 /*
2 Unix SMB/CIFS implementation.
3 SMB torture tester
4 Copyright (C) Andrew Tridgell 1997-1998
5 Copyright (C) Jeremy Allison 2009
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
22 #include "system/shmem.h"
23 #include "wbc_async.h"
24 #include "torture/proto.h"
25 #include "libcli/security/security.h"
26 #include "tldap.h"
27 #include "tldap_util.h"
28 #include "../librpc/gen_ndr/svcctl.h"
29 #include "memcache.h"
30 #include "nsswitch/winbind_client.h"
31 #include "dbwrap.h"
32 #include "talloc_dict.h"
33 #include "async_smb.h"
34 #include "libsmb/libsmb.h"
35 #include "libsmb/clirap.h"
36 #include "trans2.h"
37 #include "libsmb/nmblib.h"
38 #include "../lib/util/tevent_ntstatus.h"
39 #include "util_tdb.h"
40 #include "libsmb/read_smb.h"
42 extern char *optarg;
43 extern int optind;
45 fstring host, workgroup, share, password, username, myname;
46 static int max_protocol = PROTOCOL_NT1;
47 static const char *sockops="TCP_NODELAY";
48 static int nprocs=1;
49 static int port_to_use=0;
50 int torture_numops=100;
51 int torture_blocksize=1024*1024;
52 static int procnum; /* records process count number when forking */
53 static struct cli_state *current_cli;
54 static fstring randomfname;
55 static bool use_oplocks;
56 static bool use_level_II_oplocks;
57 static const char *client_txt = "client_oplocks.txt";
58 static bool use_kerberos;
59 static fstring multishare_conn_fname;
60 static bool use_multishare_conn = False;
61 static bool do_encrypt;
62 static const char *local_path = NULL;
63 static int signing_state = Undefined;
64 char *test_filename;
66 bool torture_showall = False;
68 static double create_procs(bool (*fn)(int), bool *result);
71 /* return a pointer to a anonymous shared memory segment of size "size"
72 which will persist across fork() but will disappear when all processes
73 exit
75 The memory is not zeroed
77 This function uses system5 shared memory. It takes advantage of a property
78 that the memory is not destroyed if it is attached when the id is removed
80 void *shm_setup(int size)
82 int shmid;
83 void *ret;
85 #ifdef __QNXNTO__
86 shmid = shm_open("private", O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
87 if (shmid == -1) {
88 printf("can't get shared memory\n");
89 exit(1);
91 shm_unlink("private");
92 if (ftruncate(shmid, size) == -1) {
93 printf("can't set shared memory size\n");
94 exit(1);
96 ret = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, shmid, 0);
97 if (ret == MAP_FAILED) {
98 printf("can't map shared memory\n");
99 exit(1);
101 #else
102 shmid = shmget(IPC_PRIVATE, size, S_IRUSR | S_IWUSR);
103 if (shmid == -1) {
104 printf("can't get shared memory\n");
105 exit(1);
107 ret = (void *)shmat(shmid, 0, 0);
108 if (!ret || ret == (void *)-1) {
109 printf("can't attach to shared memory\n");
110 return NULL;
112 /* the following releases the ipc, but note that this process
113 and all its children will still have access to the memory, its
114 just that the shmid is no longer valid for other shm calls. This
115 means we don't leave behind lots of shm segments after we exit
117 See Stevens "advanced programming in unix env" for details
119 shmctl(shmid, IPC_RMID, 0);
120 #endif
122 return ret;
125 /********************************************************************
126 Ensure a connection is encrypted.
127 ********************************************************************/
129 static bool force_cli_encryption(struct cli_state *c,
130 const char *sharename)
132 uint16 major, minor;
133 uint32 caplow, caphigh;
134 NTSTATUS status;
136 if (!SERVER_HAS_UNIX_CIFS(c)) {
137 d_printf("Encryption required and "
138 "server that doesn't support "
139 "UNIX extensions - failing connect\n");
140 return false;
143 status = cli_unix_extensions_version(c, &major, &minor, &caplow,
144 &caphigh);
145 if (!NT_STATUS_IS_OK(status)) {
146 d_printf("Encryption required and "
147 "can't get UNIX CIFS extensions "
148 "version from server: %s\n", nt_errstr(status));
149 return false;
152 if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
153 d_printf("Encryption required and "
154 "share %s doesn't support "
155 "encryption.\n", sharename);
156 return false;
159 if (c->use_kerberos) {
160 status = cli_gss_smb_encryption_start(c);
161 } else {
162 status = cli_raw_ntlm_smb_encryption_start(c,
163 username,
164 password,
165 workgroup);
168 if (!NT_STATUS_IS_OK(status)) {
169 d_printf("Encryption required and "
170 "setup failed with error %s.\n",
171 nt_errstr(status));
172 return false;
175 return true;
179 static struct cli_state *open_nbt_connection(void)
181 struct cli_state *c;
182 NTSTATUS status;
184 status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
185 signing_state, &c);
186 if (!NT_STATUS_IS_OK(status)) {
187 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
188 return NULL;
191 c->use_kerberos = use_kerberos;
193 c->timeout = 120000; /* set a really long timeout (2 minutes) */
194 if (use_oplocks) c->use_oplocks = True;
195 if (use_level_II_oplocks) c->use_level_II_oplocks = True;
197 return c;
200 /****************************************************************************
201 Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
202 ****************************************************************************/
204 static bool cli_bad_session_request(int fd,
205 struct nmb_name *calling, struct nmb_name *called)
207 TALLOC_CTX *frame;
208 uint8_t len_buf[4];
209 struct iovec iov[3];
210 ssize_t len;
211 uint8_t *inbuf;
212 int err;
213 bool ret = false;
214 uint8_t message_type;
215 uint8_t error;
217 frame = talloc_stackframe();
219 iov[0].iov_base = len_buf;
220 iov[0].iov_len = sizeof(len_buf);
222 /* put in the destination name */
224 iov[1].iov_base = name_mangle(talloc_tos(), called->name,
225 called->name_type);
226 if (iov[1].iov_base == NULL) {
227 goto fail;
229 iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
230 talloc_get_size(iov[1].iov_base));
232 /* and my name */
234 iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
235 calling->name_type);
236 if (iov[2].iov_base == NULL) {
237 goto fail;
239 iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
240 talloc_get_size(iov[2].iov_base));
242 /* Deliberately corrupt the name len (first byte) */
243 *((uint8_t *)iov[2].iov_base) = 100;
245 /* send a session request (RFC 1002) */
246 /* setup the packet length
247 * Remove four bytes from the length count, since the length
248 * field in the NBT Session Service header counts the number
249 * of bytes which follow. The cli_send_smb() function knows
250 * about this and accounts for those four bytes.
251 * CRH.
254 _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
255 SCVAL(len_buf,0,0x81);
257 len = write_data_iov(fd, iov, 3);
258 if (len == -1) {
259 goto fail;
261 len = read_smb(fd, talloc_tos(), &inbuf, &err);
262 if (len == -1) {
263 errno = err;
264 goto fail;
267 message_type = CVAL(inbuf, 0);
268 if (message_type != 0x83) {
269 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
270 message_type);
271 goto fail;
274 if (smb_len(inbuf) != 1) {
275 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
276 (int)smb_len(inbuf));
277 goto fail;
280 error = CVAL(inbuf, 4);
281 if (error != 0x82) {
282 d_fprintf(stderr, "Expected error 0x82, got %d\n",
283 (int)error);
284 goto fail;
287 ret = true;
288 fail:
289 TALLOC_FREE(frame);
290 return ret;
293 /* Insert a NULL at the first separator of the given path and return a pointer
294 * to the remainder of the string.
296 static char *
297 terminate_path_at_separator(char * path)
299 char * p;
301 if (!path) {
302 return NULL;
305 if ((p = strchr_m(path, '/'))) {
306 *p = '\0';
307 return p + 1;
310 if ((p = strchr_m(path, '\\'))) {
311 *p = '\0';
312 return p + 1;
315 /* No separator. */
316 return NULL;
320 parse a //server/share type UNC name
322 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
323 char **hostname, char **sharename)
325 char *p;
327 *hostname = *sharename = NULL;
329 if (strncmp(unc_name, "\\\\", 2) &&
330 strncmp(unc_name, "//", 2)) {
331 return False;
334 *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
335 p = terminate_path_at_separator(*hostname);
337 if (p && *p) {
338 *sharename = talloc_strdup(mem_ctx, p);
339 terminate_path_at_separator(*sharename);
342 if (*hostname && *sharename) {
343 return True;
346 TALLOC_FREE(*hostname);
347 TALLOC_FREE(*sharename);
348 return False;
351 static bool torture_open_connection_share(struct cli_state **c,
352 const char *hostname,
353 const char *sharename)
355 int flags = 0;
356 NTSTATUS status;
358 if (use_kerberos)
359 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
360 if (use_oplocks)
361 flags |= CLI_FULL_CONNECTION_OPLOCKS;
362 if (use_level_II_oplocks)
363 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
365 status = cli_full_connection(c, myname,
366 hostname, NULL, port_to_use,
367 sharename, "?????",
368 username, workgroup,
369 password, flags, signing_state);
370 if (!NT_STATUS_IS_OK(status)) {
371 printf("failed to open share connection: //%s/%s port:%d - %s\n",
372 hostname, sharename, port_to_use, nt_errstr(status));
373 return False;
376 (*c)->timeout = 120000; /* set a really long timeout (2 minutes) */
378 if (do_encrypt) {
379 return force_cli_encryption(*c,
380 sharename);
382 return True;
385 bool torture_open_connection(struct cli_state **c, int conn_index)
387 char **unc_list = NULL;
388 int num_unc_names = 0;
389 bool result;
391 if (use_multishare_conn==True) {
392 char *h, *s;
393 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
394 if (!unc_list || num_unc_names <= 0) {
395 printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
396 exit(1);
399 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
400 NULL, &h, &s)) {
401 printf("Failed to parse UNC name %s\n",
402 unc_list[conn_index % num_unc_names]);
403 TALLOC_FREE(unc_list);
404 exit(1);
407 result = torture_open_connection_share(c, h, s);
409 /* h, s were copied earlier */
410 TALLOC_FREE(unc_list);
411 return result;
414 return torture_open_connection_share(c, host, share);
417 bool torture_init_connection(struct cli_state **pcli)
419 struct cli_state *cli;
421 cli = open_nbt_connection();
422 if (cli == NULL) {
423 return false;
426 *pcli = cli;
427 return true;
430 bool torture_cli_session_setup2(struct cli_state *cli, uint16 *new_vuid)
432 uint16 old_vuid = cli->vuid;
433 fstring old_user_name;
434 size_t passlen = strlen(password);
435 NTSTATUS status;
436 bool ret;
438 fstrcpy(old_user_name, cli->user_name);
439 cli->vuid = 0;
440 ret = NT_STATUS_IS_OK(cli_session_setup(cli, username,
441 password, passlen,
442 password, passlen,
443 workgroup));
444 *new_vuid = cli->vuid;
445 cli->vuid = old_vuid;
446 status = cli_set_username(cli, old_user_name);
447 if (!NT_STATUS_IS_OK(status)) {
448 return false;
450 return ret;
454 bool torture_close_connection(struct cli_state *c)
456 bool ret = True;
457 NTSTATUS status;
459 status = cli_tdis(c);
460 if (!NT_STATUS_IS_OK(status)) {
461 printf("tdis failed (%s)\n", nt_errstr(status));
462 ret = False;
465 cli_shutdown(c);
467 return ret;
471 /* check if the server produced the expected dos or nt error code */
472 static bool check_both_error(int line, NTSTATUS status,
473 uint8 eclass, uint32 ecode, NTSTATUS nterr)
475 if (NT_STATUS_IS_DOS(status)) {
476 uint8 cclass;
477 uint32 num;
479 /* Check DOS error */
480 cclass = NT_STATUS_DOS_CLASS(status);
481 num = NT_STATUS_DOS_CODE(status);
483 if (eclass != cclass || ecode != num) {
484 printf("unexpected error code class=%d code=%d\n",
485 (int)cclass, (int)num);
486 printf(" expected %d/%d %s (line=%d)\n",
487 (int)eclass, (int)ecode, nt_errstr(nterr), line);
488 return false;
490 } else {
491 /* Check NT error */
492 if (!NT_STATUS_EQUAL(nterr, status)) {
493 printf("unexpected error code %s\n",
494 nt_errstr(status));
495 printf(" expected %s (line=%d)\n",
496 nt_errstr(nterr), line);
497 return false;
501 return true;
505 /* check if the server produced the expected error code */
506 static bool check_error(int line, struct cli_state *c,
507 uint8 eclass, uint32 ecode, NTSTATUS nterr)
509 if (cli_is_dos_error(c)) {
510 uint8 cclass;
511 uint32 num;
513 /* Check DOS error */
515 cli_dos_error(c, &cclass, &num);
517 if (eclass != cclass || ecode != num) {
518 printf("unexpected error code class=%d code=%d\n",
519 (int)cclass, (int)num);
520 printf(" expected %d/%d %s (line=%d)\n",
521 (int)eclass, (int)ecode, nt_errstr(nterr), line);
522 return False;
525 } else {
526 NTSTATUS status;
528 /* Check NT error */
530 status = cli_nt_error(c);
532 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
533 printf("unexpected error code %s\n", nt_errstr(status));
534 printf(" expected %s (line=%d)\n", nt_errstr(nterr), line);
535 return False;
539 return True;
543 static bool wait_lock(struct cli_state *c, int fnum, uint32 offset, uint32 len)
545 NTSTATUS status;
547 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
549 while (!NT_STATUS_IS_OK(status)) {
550 if (!check_both_error(__LINE__, status, ERRDOS,
551 ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
552 return false;
555 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
558 return true;
562 static bool rw_torture(struct cli_state *c)
564 const char *lockfname = "\\torture.lck";
565 fstring fname;
566 uint16_t fnum;
567 uint16_t fnum2;
568 pid_t pid2, pid = getpid();
569 int i, j;
570 char buf[1024];
571 bool correct = True;
572 NTSTATUS status;
574 memset(buf, '\0', sizeof(buf));
576 status = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
577 DENY_NONE, &fnum2);
578 if (!NT_STATUS_IS_OK(status)) {
579 status = cli_open(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
581 if (!NT_STATUS_IS_OK(status)) {
582 printf("open of %s failed (%s)\n",
583 lockfname, nt_errstr(status));
584 return False;
587 for (i=0;i<torture_numops;i++) {
588 unsigned n = (unsigned)sys_random()%10;
590 if (i % 10 == 0) {
591 printf("%d\r", i); fflush(stdout);
593 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
595 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
596 return False;
599 status = cli_open(c, fname, O_RDWR | O_CREAT | O_TRUNC,
600 DENY_ALL, &fnum);
601 if (!NT_STATUS_IS_OK(status)) {
602 printf("open failed (%s)\n", nt_errstr(status));
603 correct = False;
604 break;
607 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
608 sizeof(pid), NULL);
609 if (!NT_STATUS_IS_OK(status)) {
610 printf("write failed (%s)\n", nt_errstr(status));
611 correct = False;
614 for (j=0;j<50;j++) {
615 status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
616 sizeof(pid)+(j*sizeof(buf)),
617 sizeof(buf), NULL);
618 if (!NT_STATUS_IS_OK(status)) {
619 printf("write failed (%s)\n",
620 nt_errstr(status));
621 correct = False;
625 pid2 = 0;
627 if (cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid)) != sizeof(pid)) {
628 printf("read failed (%s)\n", cli_errstr(c));
629 correct = False;
632 if (pid2 != pid) {
633 printf("data corruption!\n");
634 correct = False;
637 status = cli_close(c, fnum);
638 if (!NT_STATUS_IS_OK(status)) {
639 printf("close failed (%s)\n", nt_errstr(status));
640 correct = False;
643 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
644 if (!NT_STATUS_IS_OK(status)) {
645 printf("unlink failed (%s)\n", nt_errstr(status));
646 correct = False;
649 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
650 if (!NT_STATUS_IS_OK(status)) {
651 printf("unlock failed (%s)\n", nt_errstr(status));
652 correct = False;
656 cli_close(c, fnum2);
657 cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
659 printf("%d\n", i);
661 return correct;
664 static bool run_torture(int dummy)
666 struct cli_state *cli;
667 bool ret;
669 cli = current_cli;
671 cli_sockopt(cli, sockops);
673 ret = rw_torture(cli);
675 if (!torture_close_connection(cli)) {
676 ret = False;
679 return ret;
682 static bool rw_torture3(struct cli_state *c, char *lockfname)
684 uint16_t fnum = (uint16_t)-1;
685 unsigned int i = 0;
686 char buf[131072];
687 char buf_rd[131072];
688 unsigned count;
689 unsigned countprev = 0;
690 ssize_t sent = 0;
691 bool correct = True;
692 NTSTATUS status = NT_STATUS_OK;
694 srandom(1);
695 for (i = 0; i < sizeof(buf); i += sizeof(uint32))
697 SIVAL(buf, i, sys_random());
700 if (procnum == 0)
702 status = cli_unlink(
703 c, lockfname,
704 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
705 if (!NT_STATUS_IS_OK(status)) {
706 printf("unlink failed (%s) (normal, this file should "
707 "not exist)\n", nt_errstr(status));
710 status = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
711 DENY_NONE, &fnum);
712 if (!NT_STATUS_IS_OK(status)) {
713 printf("first open read/write of %s failed (%s)\n",
714 lockfname, nt_errstr(status));
715 return False;
718 else
720 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
722 status = cli_open(c, lockfname, O_RDONLY,
723 DENY_NONE, &fnum);
724 if (!NT_STATUS_IS_OK(status)) {
725 break;
727 smb_msleep(10);
729 if (!NT_STATUS_IS_OK(status)) {
730 printf("second open read-only of %s failed (%s)\n",
731 lockfname, nt_errstr(status));
732 return False;
736 i = 0;
737 for (count = 0; count < sizeof(buf); count += sent)
739 if (count >= countprev) {
740 printf("%d %8d\r", i, count);
741 fflush(stdout);
742 i++;
743 countprev += (sizeof(buf) / 20);
746 if (procnum == 0)
748 sent = ((unsigned)sys_random()%(20))+ 1;
749 if (sent > sizeof(buf) - count)
751 sent = sizeof(buf) - count;
754 status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
755 count, (size_t)sent, NULL);
756 if (!NT_STATUS_IS_OK(status)) {
757 printf("write failed (%s)\n",
758 nt_errstr(status));
759 correct = False;
762 else
764 sent = cli_read(c, fnum, buf_rd+count, count,
765 sizeof(buf)-count);
766 if (sent < 0)
768 printf("read failed offset:%d size:%ld (%s)\n",
769 count, (unsigned long)sizeof(buf)-count,
770 cli_errstr(c));
771 correct = False;
772 sent = 0;
774 if (sent > 0)
776 if (memcmp(buf_rd+count, buf+count, sent) != 0)
778 printf("read/write compare failed\n");
779 printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
780 correct = False;
781 break;
788 status = cli_close(c, fnum);
789 if (!NT_STATUS_IS_OK(status)) {
790 printf("close failed (%s)\n", nt_errstr(status));
791 correct = False;
794 return correct;
797 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
799 const char *lockfname = "\\torture2.lck";
800 uint16_t fnum1;
801 uint16_t fnum2;
802 int i;
803 char buf[131072];
804 char buf_rd[131072];
805 bool correct = True;
806 ssize_t bytes_read;
807 NTSTATUS status;
809 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
810 if (!NT_STATUS_IS_OK(status)) {
811 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
814 status = cli_open(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
815 DENY_NONE, &fnum1);
816 if (!NT_STATUS_IS_OK(status)) {
817 printf("first open read/write of %s failed (%s)\n",
818 lockfname, nt_errstr(status));
819 return False;
822 status = cli_open(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
823 if (!NT_STATUS_IS_OK(status)) {
824 printf("second open read-only of %s failed (%s)\n",
825 lockfname, nt_errstr(status));
826 cli_close(c1, fnum1);
827 return False;
830 for (i = 0; i < torture_numops; i++)
832 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
833 if (i % 10 == 0) {
834 printf("%d\r", i); fflush(stdout);
837 generate_random_buffer((unsigned char *)buf, buf_size);
839 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
840 buf_size, NULL);
841 if (!NT_STATUS_IS_OK(status)) {
842 printf("write failed (%s)\n", nt_errstr(status));
843 correct = False;
844 break;
847 if ((bytes_read = cli_read(c2, fnum2, buf_rd, 0, buf_size)) != buf_size) {
848 printf("read failed (%s)\n", cli_errstr(c2));
849 printf("read %d, expected %ld\n", (int)bytes_read,
850 (unsigned long)buf_size);
851 correct = False;
852 break;
855 if (memcmp(buf_rd, buf, buf_size) != 0)
857 printf("read/write compare failed\n");
858 correct = False;
859 break;
863 status = cli_close(c2, fnum2);
864 if (!NT_STATUS_IS_OK(status)) {
865 printf("close failed (%s)\n", nt_errstr(status));
866 correct = False;
869 status = cli_close(c1, fnum1);
870 if (!NT_STATUS_IS_OK(status)) {
871 printf("close failed (%s)\n", nt_errstr(status));
872 correct = False;
875 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
876 if (!NT_STATUS_IS_OK(status)) {
877 printf("unlink failed (%s)\n", nt_errstr(status));
878 correct = False;
881 return correct;
884 static bool run_readwritetest(int dummy)
886 struct cli_state *cli1, *cli2;
887 bool test1, test2 = False;
889 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
890 return False;
892 cli_sockopt(cli1, sockops);
893 cli_sockopt(cli2, sockops);
895 printf("starting readwritetest\n");
897 test1 = rw_torture2(cli1, cli2);
898 printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
900 if (test1) {
901 test2 = rw_torture2(cli1, cli1);
902 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
905 if (!torture_close_connection(cli1)) {
906 test1 = False;
909 if (!torture_close_connection(cli2)) {
910 test2 = False;
913 return (test1 && test2);
916 static bool run_readwritemulti(int dummy)
918 struct cli_state *cli;
919 bool test;
921 cli = current_cli;
923 cli_sockopt(cli, sockops);
925 printf("run_readwritemulti: fname %s\n", randomfname);
926 test = rw_torture3(cli, randomfname);
928 if (!torture_close_connection(cli)) {
929 test = False;
932 return test;
935 static bool run_readwritelarge_internal(int max_xmit_k)
937 static struct cli_state *cli1;
938 uint16_t fnum1;
939 const char *lockfname = "\\large.dat";
940 SMB_OFF_T fsize;
941 char buf[126*1024];
942 bool correct = True;
943 NTSTATUS status;
945 if (!torture_open_connection(&cli1, 0)) {
946 return False;
948 cli_sockopt(cli1, sockops);
949 memset(buf,'\0',sizeof(buf));
951 cli1->max_xmit = max_xmit_k*1024;
953 if (signing_state == Required) {
954 /* Horrible cheat to force
955 multiple signed outstanding
956 packets against a Samba server.
958 cli1->is_samba = false;
961 printf("starting readwritelarge_internal\n");
963 cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
965 status = cli_open(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
966 DENY_NONE, &fnum1);
967 if (!NT_STATUS_IS_OK(status)) {
968 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
969 return False;
972 cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
974 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
975 NULL, NULL, NULL);
976 if (!NT_STATUS_IS_OK(status)) {
977 printf("qfileinfo failed (%s)\n", nt_errstr(status));
978 correct = False;
981 if (fsize == sizeof(buf))
982 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
983 (unsigned long)fsize);
984 else {
985 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
986 (unsigned long)fsize);
987 correct = False;
990 status = cli_close(cli1, fnum1);
991 if (!NT_STATUS_IS_OK(status)) {
992 printf("close failed (%s)\n", nt_errstr(status));
993 correct = False;
996 status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
997 if (!NT_STATUS_IS_OK(status)) {
998 printf("unlink failed (%s)\n", nt_errstr(status));
999 correct = False;
1002 status = cli_open(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1003 DENY_NONE, &fnum1);
1004 if (!NT_STATUS_IS_OK(status)) {
1005 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1006 return False;
1009 cli1->max_xmit = 4*1024;
1011 cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1013 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1014 NULL, NULL, NULL);
1015 if (!NT_STATUS_IS_OK(status)) {
1016 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1017 correct = False;
1020 if (fsize == sizeof(buf))
1021 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1022 (unsigned long)fsize);
1023 else {
1024 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1025 (unsigned long)fsize);
1026 correct = False;
1029 #if 0
1030 /* ToDo - set allocation. JRA */
1031 if(!cli_set_allocation_size(cli1, fnum1, 0)) {
1032 printf("set allocation size to zero failed (%s)\n", cli_errstr(&cli1));
1033 return False;
1035 if (!cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL, NULL,
1036 NULL, NULL)) {
1037 printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
1038 correct = False;
1040 if (fsize != 0)
1041 printf("readwritelarge test 3 (truncate test) succeeded (size = %x)\n", fsize);
1042 #endif
1044 status = cli_close(cli1, fnum1);
1045 if (!NT_STATUS_IS_OK(status)) {
1046 printf("close failed (%s)\n", nt_errstr(status));
1047 correct = False;
1050 if (!torture_close_connection(cli1)) {
1051 correct = False;
1053 return correct;
1056 static bool run_readwritelarge(int dummy)
1058 return run_readwritelarge_internal(128);
1061 static bool run_readwritelarge_signtest(int dummy)
1063 bool ret;
1064 signing_state = Required;
1065 ret = run_readwritelarge_internal(2);
1066 signing_state = Undefined;
1067 return ret;
1070 int line_count = 0;
1071 int nbio_id;
1073 #define ival(s) strtol(s, NULL, 0)
1075 /* run a test that simulates an approximate netbench client load */
1076 static bool run_netbench(int client)
1078 struct cli_state *cli;
1079 int i;
1080 char line[1024];
1081 char cname[20];
1082 FILE *f;
1083 const char *params[20];
1084 bool correct = True;
1086 cli = current_cli;
1088 nbio_id = client;
1090 cli_sockopt(cli, sockops);
1092 nb_setup(cli);
1094 slprintf(cname,sizeof(cname)-1, "client%d", client);
1096 f = fopen(client_txt, "r");
1098 if (!f) {
1099 perror(client_txt);
1100 return False;
1103 while (fgets(line, sizeof(line)-1, f)) {
1104 char *saveptr;
1105 line_count++;
1107 line[strlen(line)-1] = 0;
1109 /* printf("[%d] %s\n", line_count, line); */
1111 all_string_sub(line,"client1", cname, sizeof(line));
1113 /* parse the command parameters */
1114 params[0] = strtok_r(line, " ", &saveptr);
1115 i = 0;
1116 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1118 params[i] = "";
1120 if (i < 2) continue;
1122 if (!strncmp(params[0],"SMB", 3)) {
1123 printf("ERROR: You are using a dbench 1 load file\n");
1124 exit(1);
1127 if (!strcmp(params[0],"NTCreateX")) {
1128 nb_createx(params[1], ival(params[2]), ival(params[3]),
1129 ival(params[4]));
1130 } else if (!strcmp(params[0],"Close")) {
1131 nb_close(ival(params[1]));
1132 } else if (!strcmp(params[0],"Rename")) {
1133 nb_rename(params[1], params[2]);
1134 } else if (!strcmp(params[0],"Unlink")) {
1135 nb_unlink(params[1]);
1136 } else if (!strcmp(params[0],"Deltree")) {
1137 nb_deltree(params[1]);
1138 } else if (!strcmp(params[0],"Rmdir")) {
1139 nb_rmdir(params[1]);
1140 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1141 nb_qpathinfo(params[1]);
1142 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1143 nb_qfileinfo(ival(params[1]));
1144 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1145 nb_qfsinfo(ival(params[1]));
1146 } else if (!strcmp(params[0],"FIND_FIRST")) {
1147 nb_findfirst(params[1]);
1148 } else if (!strcmp(params[0],"WriteX")) {
1149 nb_writex(ival(params[1]),
1150 ival(params[2]), ival(params[3]), ival(params[4]));
1151 } else if (!strcmp(params[0],"ReadX")) {
1152 nb_readx(ival(params[1]),
1153 ival(params[2]), ival(params[3]), ival(params[4]));
1154 } else if (!strcmp(params[0],"Flush")) {
1155 nb_flush(ival(params[1]));
1156 } else {
1157 printf("Unknown operation %s\n", params[0]);
1158 exit(1);
1161 fclose(f);
1163 nb_cleanup();
1165 if (!torture_close_connection(cli)) {
1166 correct = False;
1169 return correct;
1173 /* run a test that simulates an approximate netbench client load */
1174 static bool run_nbench(int dummy)
1176 double t;
1177 bool correct = True;
1179 nbio_shmem(nprocs);
1181 nbio_id = -1;
1183 signal(SIGALRM, nb_alarm);
1184 alarm(1);
1185 t = create_procs(run_netbench, &correct);
1186 alarm(0);
1188 printf("\nThroughput %g MB/sec\n",
1189 1.0e-6 * nbio_total() / t);
1190 return correct;
1195 This test checks for two things:
1197 1) correct support for retaining locks over a close (ie. the server
1198 must not use posix semantics)
1199 2) support for lock timeouts
1201 static bool run_locktest1(int dummy)
1203 struct cli_state *cli1, *cli2;
1204 const char *fname = "\\lockt1.lck";
1205 uint16_t fnum1, fnum2, fnum3;
1206 time_t t1, t2;
1207 unsigned lock_timeout;
1208 NTSTATUS status;
1210 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1211 return False;
1213 cli_sockopt(cli1, sockops);
1214 cli_sockopt(cli2, sockops);
1216 printf("starting locktest1\n");
1218 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1220 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1221 &fnum1);
1222 if (!NT_STATUS_IS_OK(status)) {
1223 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1224 return False;
1227 status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1228 if (!NT_STATUS_IS_OK(status)) {
1229 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1230 return False;
1233 status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1234 if (!NT_STATUS_IS_OK(status)) {
1235 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1236 return False;
1239 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1240 if (!NT_STATUS_IS_OK(status)) {
1241 printf("lock1 failed (%s)\n", nt_errstr(status));
1242 return false;
1245 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1246 if (NT_STATUS_IS_OK(status)) {
1247 printf("lock2 succeeded! This is a locking bug\n");
1248 return false;
1249 } else {
1250 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1251 NT_STATUS_LOCK_NOT_GRANTED)) {
1252 return false;
1256 lock_timeout = (1 + (random() % 20));
1257 printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1258 t1 = time(NULL);
1259 status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1260 if (NT_STATUS_IS_OK(status)) {
1261 printf("lock3 succeeded! This is a locking bug\n");
1262 return false;
1263 } else {
1264 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1265 NT_STATUS_FILE_LOCK_CONFLICT)) {
1266 return false;
1269 t2 = time(NULL);
1271 if (ABS(t2 - t1) < lock_timeout-1) {
1272 printf("error: This server appears not to support timed lock requests\n");
1275 printf("server slept for %u seconds for a %u second timeout\n",
1276 (unsigned int)(t2-t1), lock_timeout);
1278 status = cli_close(cli1, fnum2);
1279 if (!NT_STATUS_IS_OK(status)) {
1280 printf("close1 failed (%s)\n", nt_errstr(status));
1281 return False;
1284 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1285 if (NT_STATUS_IS_OK(status)) {
1286 printf("lock4 succeeded! This is a locking bug\n");
1287 return false;
1288 } else {
1289 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1290 NT_STATUS_FILE_LOCK_CONFLICT)) {
1291 return false;
1295 status = cli_close(cli1, fnum1);
1296 if (!NT_STATUS_IS_OK(status)) {
1297 printf("close2 failed (%s)\n", nt_errstr(status));
1298 return False;
1301 status = cli_close(cli2, fnum3);
1302 if (!NT_STATUS_IS_OK(status)) {
1303 printf("close3 failed (%s)\n", nt_errstr(status));
1304 return False;
1307 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1308 if (!NT_STATUS_IS_OK(status)) {
1309 printf("unlink failed (%s)\n", nt_errstr(status));
1310 return False;
1314 if (!torture_close_connection(cli1)) {
1315 return False;
1318 if (!torture_close_connection(cli2)) {
1319 return False;
1322 printf("Passed locktest1\n");
1323 return True;
1327 this checks to see if a secondary tconx can use open files from an
1328 earlier tconx
1330 static bool run_tcon_test(int dummy)
1332 static struct cli_state *cli;
1333 const char *fname = "\\tcontest.tmp";
1334 uint16 fnum1;
1335 uint16 cnum1, cnum2, cnum3;
1336 uint16 vuid1, vuid2;
1337 char buf[4];
1338 bool ret = True;
1339 NTSTATUS status;
1341 memset(buf, '\0', sizeof(buf));
1343 if (!torture_open_connection(&cli, 0)) {
1344 return False;
1346 cli_sockopt(cli, sockops);
1348 printf("starting tcontest\n");
1350 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1352 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1353 if (!NT_STATUS_IS_OK(status)) {
1354 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1355 return False;
1358 cnum1 = cli->cnum;
1359 vuid1 = cli->vuid;
1361 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1362 if (!NT_STATUS_IS_OK(status)) {
1363 printf("initial write failed (%s)", nt_errstr(status));
1364 return False;
1367 status = cli_tcon_andx(cli, share, "?????",
1368 password, strlen(password)+1);
1369 if (!NT_STATUS_IS_OK(status)) {
1370 printf("%s refused 2nd tree connect (%s)\n", host,
1371 nt_errstr(status));
1372 cli_shutdown(cli);
1373 return False;
1376 cnum2 = cli->cnum;
1377 cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1378 vuid2 = cli->vuid + 1;
1380 /* try a write with the wrong tid */
1381 cli->cnum = cnum2;
1383 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1384 if (NT_STATUS_IS_OK(status)) {
1385 printf("* server allows write with wrong TID\n");
1386 ret = False;
1387 } else {
1388 printf("server fails write with wrong TID : %s\n",
1389 nt_errstr(status));
1393 /* try a write with an invalid tid */
1394 cli->cnum = cnum3;
1396 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1397 if (NT_STATUS_IS_OK(status)) {
1398 printf("* server allows write with invalid TID\n");
1399 ret = False;
1400 } else {
1401 printf("server fails write with invalid TID : %s\n",
1402 nt_errstr(status));
1405 /* try a write with an invalid vuid */
1406 cli->vuid = vuid2;
1407 cli->cnum = cnum1;
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 invalid VUID\n");
1412 ret = False;
1413 } else {
1414 printf("server fails write with invalid VUID : %s\n",
1415 nt_errstr(status));
1418 cli->cnum = cnum1;
1419 cli->vuid = vuid1;
1421 status = cli_close(cli, fnum1);
1422 if (!NT_STATUS_IS_OK(status)) {
1423 printf("close failed (%s)\n", nt_errstr(status));
1424 return False;
1427 cli->cnum = cnum2;
1429 status = cli_tdis(cli);
1430 if (!NT_STATUS_IS_OK(status)) {
1431 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1432 return False;
1435 cli->cnum = cnum1;
1437 if (!torture_close_connection(cli)) {
1438 return False;
1441 return ret;
1446 checks for old style tcon support
1448 static bool run_tcon2_test(int dummy)
1450 static struct cli_state *cli;
1451 uint16 cnum, max_xmit;
1452 char *service;
1453 NTSTATUS status;
1455 if (!torture_open_connection(&cli, 0)) {
1456 return False;
1458 cli_sockopt(cli, sockops);
1460 printf("starting tcon2 test\n");
1462 if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1463 return false;
1466 status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1468 SAFE_FREE(service);
1470 if (!NT_STATUS_IS_OK(status)) {
1471 printf("tcon2 failed : %s\n", nt_errstr(status));
1472 } else {
1473 printf("tcon OK : max_xmit=%d cnum=%d\n",
1474 (int)max_xmit, (int)cnum);
1477 if (!torture_close_connection(cli)) {
1478 return False;
1481 printf("Passed tcon2 test\n");
1482 return True;
1485 static bool tcon_devtest(struct cli_state *cli,
1486 const char *myshare, const char *devtype,
1487 const char *return_devtype,
1488 NTSTATUS expected_error)
1490 NTSTATUS status;
1491 bool ret;
1493 status = cli_tcon_andx(cli, myshare, devtype,
1494 password, strlen(password)+1);
1496 if (NT_STATUS_IS_OK(expected_error)) {
1497 if (NT_STATUS_IS_OK(status)) {
1498 if (strcmp(cli->dev, return_devtype) == 0) {
1499 ret = True;
1500 } else {
1501 printf("tconX to share %s with type %s "
1502 "succeeded but returned the wrong "
1503 "device type (got [%s] but should have got [%s])\n",
1504 myshare, devtype, cli->dev, return_devtype);
1505 ret = False;
1507 } else {
1508 printf("tconX to share %s with type %s "
1509 "should have succeeded but failed\n",
1510 myshare, devtype);
1511 ret = False;
1513 cli_tdis(cli);
1514 } else {
1515 if (NT_STATUS_IS_OK(status)) {
1516 printf("tconx to share %s with type %s "
1517 "should have failed but succeeded\n",
1518 myshare, devtype);
1519 ret = False;
1520 } else {
1521 if (NT_STATUS_EQUAL(cli_nt_error(cli),
1522 expected_error)) {
1523 ret = True;
1524 } else {
1525 printf("Returned unexpected error\n");
1526 ret = False;
1530 return ret;
1534 checks for correct tconX support
1536 static bool run_tcon_devtype_test(int dummy)
1538 static struct cli_state *cli1 = NULL;
1539 int flags = 0;
1540 NTSTATUS status;
1541 bool ret = True;
1543 status = cli_full_connection(&cli1, myname,
1544 host, NULL, port_to_use,
1545 NULL, NULL,
1546 username, workgroup,
1547 password, flags, signing_state);
1549 if (!NT_STATUS_IS_OK(status)) {
1550 printf("could not open connection\n");
1551 return False;
1554 if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1555 ret = False;
1557 if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1558 ret = False;
1560 if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1561 ret = False;
1563 if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1564 ret = False;
1566 if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1567 ret = False;
1569 if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1570 ret = False;
1572 if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1573 ret = False;
1575 if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1576 ret = False;
1578 if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1579 ret = False;
1581 if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1582 ret = False;
1584 cli_shutdown(cli1);
1586 if (ret)
1587 printf("Passed tcondevtest\n");
1589 return ret;
1594 This test checks that
1596 1) the server supports multiple locking contexts on the one SMB
1597 connection, distinguished by PID.
1599 2) the server correctly fails overlapping locks made by the same PID (this
1600 goes against POSIX behaviour, which is why it is tricky to implement)
1602 3) the server denies unlock requests by an incorrect client PID
1604 static bool run_locktest2(int dummy)
1606 static struct cli_state *cli;
1607 const char *fname = "\\lockt2.lck";
1608 uint16_t fnum1, fnum2, fnum3;
1609 bool correct = True;
1610 NTSTATUS status;
1612 if (!torture_open_connection(&cli, 0)) {
1613 return False;
1616 cli_sockopt(cli, sockops);
1618 printf("starting locktest2\n");
1620 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1622 cli_setpid(cli, 1);
1624 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1625 if (!NT_STATUS_IS_OK(status)) {
1626 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1627 return False;
1630 status = cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1631 if (!NT_STATUS_IS_OK(status)) {
1632 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1633 return False;
1636 cli_setpid(cli, 2);
1638 status = cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1639 if (!NT_STATUS_IS_OK(status)) {
1640 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1641 return False;
1644 cli_setpid(cli, 1);
1646 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1647 if (!NT_STATUS_IS_OK(status)) {
1648 printf("lock1 failed (%s)\n", nt_errstr(status));
1649 return false;
1652 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1653 if (NT_STATUS_IS_OK(status)) {
1654 printf("WRITE lock1 succeeded! This is a locking bug\n");
1655 correct = false;
1656 } else {
1657 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1658 NT_STATUS_LOCK_NOT_GRANTED)) {
1659 return false;
1663 status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1664 if (NT_STATUS_IS_OK(status)) {
1665 printf("WRITE lock2 succeeded! This is a locking bug\n");
1666 correct = false;
1667 } else {
1668 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1669 NT_STATUS_LOCK_NOT_GRANTED)) {
1670 return false;
1674 status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1675 if (NT_STATUS_IS_OK(status)) {
1676 printf("READ lock2 succeeded! This is a locking bug\n");
1677 correct = false;
1678 } else {
1679 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1680 NT_STATUS_FILE_LOCK_CONFLICT)) {
1681 return false;
1685 status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1686 if (!NT_STATUS_IS_OK(status)) {
1687 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1689 cli_setpid(cli, 2);
1690 if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1691 printf("unlock at 100 succeeded! This is a locking bug\n");
1692 correct = False;
1695 status = cli_unlock(cli, fnum1, 0, 4);
1696 if (NT_STATUS_IS_OK(status)) {
1697 printf("unlock1 succeeded! This is a locking bug\n");
1698 correct = false;
1699 } else {
1700 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1701 NT_STATUS_RANGE_NOT_LOCKED)) {
1702 return false;
1706 status = cli_unlock(cli, fnum1, 0, 8);
1707 if (NT_STATUS_IS_OK(status)) {
1708 printf("unlock2 succeeded! This is a locking bug\n");
1709 correct = false;
1710 } else {
1711 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1712 NT_STATUS_RANGE_NOT_LOCKED)) {
1713 return false;
1717 status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1718 if (NT_STATUS_IS_OK(status)) {
1719 printf("lock3 succeeded! This is a locking bug\n");
1720 correct = false;
1721 } else {
1722 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1723 NT_STATUS_LOCK_NOT_GRANTED)) {
1724 return false;
1728 cli_setpid(cli, 1);
1730 status = cli_close(cli, fnum1);
1731 if (!NT_STATUS_IS_OK(status)) {
1732 printf("close1 failed (%s)\n", nt_errstr(status));
1733 return False;
1736 status = cli_close(cli, fnum2);
1737 if (!NT_STATUS_IS_OK(status)) {
1738 printf("close2 failed (%s)\n", nt_errstr(status));
1739 return False;
1742 status = cli_close(cli, fnum3);
1743 if (!NT_STATUS_IS_OK(status)) {
1744 printf("close3 failed (%s)\n", nt_errstr(status));
1745 return False;
1748 if (!torture_close_connection(cli)) {
1749 correct = False;
1752 printf("locktest2 finished\n");
1754 return correct;
1759 This test checks that
1761 1) the server supports the full offset range in lock requests
1763 static bool run_locktest3(int dummy)
1765 static struct cli_state *cli1, *cli2;
1766 const char *fname = "\\lockt3.lck";
1767 uint16_t fnum1, fnum2;
1768 int i;
1769 uint32 offset;
1770 bool correct = True;
1771 NTSTATUS status;
1773 #define NEXT_OFFSET offset += (~(uint32)0) / torture_numops
1775 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1776 return False;
1778 cli_sockopt(cli1, sockops);
1779 cli_sockopt(cli2, sockops);
1781 printf("starting locktest3\n");
1783 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1785 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1786 &fnum1);
1787 if (!NT_STATUS_IS_OK(status)) {
1788 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1789 return False;
1792 status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1793 if (!NT_STATUS_IS_OK(status)) {
1794 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1795 return False;
1798 for (offset=i=0;i<torture_numops;i++) {
1799 NEXT_OFFSET;
1801 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1802 if (!NT_STATUS_IS_OK(status)) {
1803 printf("lock1 %d failed (%s)\n",
1805 nt_errstr(status));
1806 return False;
1809 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1810 if (!NT_STATUS_IS_OK(status)) {
1811 printf("lock2 %d failed (%s)\n",
1813 nt_errstr(status));
1814 return False;
1818 for (offset=i=0;i<torture_numops;i++) {
1819 NEXT_OFFSET;
1821 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1822 if (NT_STATUS_IS_OK(status)) {
1823 printf("error: lock1 %d succeeded!\n", i);
1824 return False;
1827 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1828 if (NT_STATUS_IS_OK(status)) {
1829 printf("error: lock2 %d succeeded!\n", i);
1830 return False;
1833 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1834 if (NT_STATUS_IS_OK(status)) {
1835 printf("error: lock3 %d succeeded!\n", i);
1836 return False;
1839 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1840 if (NT_STATUS_IS_OK(status)) {
1841 printf("error: lock4 %d succeeded!\n", i);
1842 return False;
1846 for (offset=i=0;i<torture_numops;i++) {
1847 NEXT_OFFSET;
1849 status = cli_unlock(cli1, fnum1, offset-1, 1);
1850 if (!NT_STATUS_IS_OK(status)) {
1851 printf("unlock1 %d failed (%s)\n",
1853 nt_errstr(status));
1854 return False;
1857 status = cli_unlock(cli2, fnum2, offset-2, 1);
1858 if (!NT_STATUS_IS_OK(status)) {
1859 printf("unlock2 %d failed (%s)\n",
1861 nt_errstr(status));
1862 return False;
1866 status = cli_close(cli1, fnum1);
1867 if (!NT_STATUS_IS_OK(status)) {
1868 printf("close1 failed (%s)\n", nt_errstr(status));
1869 return False;
1872 status = cli_close(cli2, fnum2);
1873 if (!NT_STATUS_IS_OK(status)) {
1874 printf("close2 failed (%s)\n", nt_errstr(status));
1875 return False;
1878 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1879 if (!NT_STATUS_IS_OK(status)) {
1880 printf("unlink failed (%s)\n", nt_errstr(status));
1881 return False;
1884 if (!torture_close_connection(cli1)) {
1885 correct = False;
1888 if (!torture_close_connection(cli2)) {
1889 correct = False;
1892 printf("finished locktest3\n");
1894 return correct;
1897 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1898 printf("** "); correct = False; \
1902 looks at overlapping locks
1904 static bool run_locktest4(int dummy)
1906 static struct cli_state *cli1, *cli2;
1907 const char *fname = "\\lockt4.lck";
1908 uint16_t fnum1, fnum2, f;
1909 bool ret;
1910 char buf[1000];
1911 bool correct = True;
1912 NTSTATUS status;
1914 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1915 return False;
1918 cli_sockopt(cli1, sockops);
1919 cli_sockopt(cli2, sockops);
1921 printf("starting locktest4\n");
1923 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1925 cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1926 cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1928 memset(buf, 0, sizeof(buf));
1930 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
1931 NULL);
1932 if (!NT_STATUS_IS_OK(status)) {
1933 printf("Failed to create file: %s\n", nt_errstr(status));
1934 correct = False;
1935 goto fail;
1938 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1939 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
1940 EXPECTED(ret, False);
1941 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1943 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
1944 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
1945 EXPECTED(ret, True);
1946 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1948 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
1949 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
1950 EXPECTED(ret, False);
1951 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1953 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
1954 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
1955 EXPECTED(ret, True);
1956 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1958 ret = (cli_setpid(cli1, 1),
1959 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
1960 (cli_setpid(cli1, 2),
1961 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
1962 EXPECTED(ret, False);
1963 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1965 ret = (cli_setpid(cli1, 1),
1966 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
1967 (cli_setpid(cli1, 2),
1968 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
1969 EXPECTED(ret, True);
1970 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1972 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
1973 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
1974 EXPECTED(ret, True);
1975 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1977 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
1978 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
1979 EXPECTED(ret, False);
1980 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1982 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
1983 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
1984 EXPECTED(ret, False);
1985 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
1987 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
1988 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
1989 EXPECTED(ret, True);
1990 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1992 ret = (cli_setpid(cli1, 1),
1993 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
1994 (cli_setpid(cli1, 2),
1995 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
1996 EXPECTED(ret, False);
1997 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1999 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2000 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2001 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2002 EXPECTED(ret, False);
2003 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2006 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2007 (cli_read(cli2, fnum2, buf, 120, 4) == 4);
2008 EXPECTED(ret, False);
2009 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2011 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2012 ret = NT_STATUS_IS_OK(status);
2013 if (ret) {
2014 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2015 NULL);
2016 ret = NT_STATUS_IS_OK(status);
2018 EXPECTED(ret, False);
2019 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2022 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2023 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2024 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2025 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2026 EXPECTED(ret, True);
2027 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2030 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2031 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2032 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2033 (cli_read(cli2, fnum2, buf, 150, 4) == 4) &&
2034 !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2035 150, 4, NULL))) &&
2036 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2037 EXPECTED(ret, True);
2038 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2040 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2041 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2042 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2043 160, 4, NULL)) &&
2044 (cli_read(cli2, fnum2, buf, 160, 4) == 4);
2045 EXPECTED(ret, True);
2046 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2048 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2049 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2050 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2051 170, 4, NULL)) &&
2052 (cli_read(cli2, fnum2, buf, 170, 4) == 4);
2053 EXPECTED(ret, True);
2054 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2056 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2057 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2058 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2059 !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2060 190, 4, NULL)) &&
2061 (cli_read(cli2, fnum2, buf, 190, 4) == 4);
2062 EXPECTED(ret, True);
2063 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2065 cli_close(cli1, fnum1);
2066 cli_close(cli2, fnum2);
2067 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2068 cli_open(cli1, fname, O_RDWR, DENY_NONE, &f);
2069 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2070 NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2071 NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2072 NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2073 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2074 cli_close(cli1, f);
2075 cli_close(cli1, fnum1);
2076 EXPECTED(ret, True);
2077 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2079 fail:
2080 cli_close(cli1, fnum1);
2081 cli_close(cli2, fnum2);
2082 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2083 torture_close_connection(cli1);
2084 torture_close_connection(cli2);
2086 printf("finished locktest4\n");
2087 return correct;
2091 looks at lock upgrade/downgrade.
2093 static bool run_locktest5(int dummy)
2095 static struct cli_state *cli1, *cli2;
2096 const char *fname = "\\lockt5.lck";
2097 uint16_t fnum1, fnum2, fnum3;
2098 bool ret;
2099 char buf[1000];
2100 bool correct = True;
2101 NTSTATUS status;
2103 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2104 return False;
2107 cli_sockopt(cli1, sockops);
2108 cli_sockopt(cli2, sockops);
2110 printf("starting locktest5\n");
2112 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2114 cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2115 cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2116 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2118 memset(buf, 0, sizeof(buf));
2120 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2121 NULL);
2122 if (!NT_STATUS_IS_OK(status)) {
2123 printf("Failed to create file: %s\n", nt_errstr(status));
2124 correct = False;
2125 goto fail;
2128 /* Check for NT bug... */
2129 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2130 NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2131 cli_close(cli1, fnum1);
2132 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2133 status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2134 ret = NT_STATUS_IS_OK(status);
2135 EXPECTED(ret, True);
2136 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2137 cli_close(cli1, fnum1);
2138 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2139 cli_unlock(cli1, fnum3, 0, 1);
2141 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2142 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2143 EXPECTED(ret, True);
2144 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2146 status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2147 ret = NT_STATUS_IS_OK(status);
2148 EXPECTED(ret, False);
2150 printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2152 /* Unlock the process 2 lock. */
2153 cli_unlock(cli2, fnum2, 0, 4);
2155 status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2156 ret = NT_STATUS_IS_OK(status);
2157 EXPECTED(ret, False);
2159 printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
2161 /* Unlock the process 1 fnum3 lock. */
2162 cli_unlock(cli1, fnum3, 0, 4);
2164 /* Stack 2 more locks here. */
2165 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2166 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2168 EXPECTED(ret, True);
2169 printf("the same process %s stack read locks\n", ret?"can":"cannot");
2171 /* Unlock the first process lock, then check this was the WRITE lock that was
2172 removed. */
2174 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2175 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2177 EXPECTED(ret, True);
2178 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2180 /* Unlock the process 2 lock. */
2181 cli_unlock(cli2, fnum2, 0, 4);
2183 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2185 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2186 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2187 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2189 EXPECTED(ret, True);
2190 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2192 /* Ensure the next unlock fails. */
2193 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2194 EXPECTED(ret, False);
2195 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2197 /* Ensure connection 2 can get a write lock. */
2198 status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2199 ret = NT_STATUS_IS_OK(status);
2200 EXPECTED(ret, True);
2202 printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2205 fail:
2206 cli_close(cli1, fnum1);
2207 cli_close(cli2, fnum2);
2208 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2209 if (!torture_close_connection(cli1)) {
2210 correct = False;
2212 if (!torture_close_connection(cli2)) {
2213 correct = False;
2216 printf("finished locktest5\n");
2218 return correct;
2222 tries the unusual lockingX locktype bits
2224 static bool run_locktest6(int dummy)
2226 static struct cli_state *cli;
2227 const char *fname[1] = { "\\lock6.txt" };
2228 int i;
2229 uint16_t fnum;
2230 NTSTATUS status;
2232 if (!torture_open_connection(&cli, 0)) {
2233 return False;
2236 cli_sockopt(cli, sockops);
2238 printf("starting locktest6\n");
2240 for (i=0;i<1;i++) {
2241 printf("Testing %s\n", fname[i]);
2243 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2245 cli_open(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2246 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2247 cli_close(cli, fnum);
2248 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2250 cli_open(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2251 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2252 cli_close(cli, fnum);
2253 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2255 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2258 torture_close_connection(cli);
2260 printf("finished locktest6\n");
2261 return True;
2264 static bool run_locktest7(int dummy)
2266 struct cli_state *cli1;
2267 const char *fname = "\\lockt7.lck";
2268 uint16_t fnum1;
2269 char buf[200];
2270 bool correct = False;
2271 NTSTATUS status;
2273 if (!torture_open_connection(&cli1, 0)) {
2274 return False;
2277 cli_sockopt(cli1, sockops);
2279 printf("starting locktest7\n");
2281 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2283 cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2285 memset(buf, 0, sizeof(buf));
2287 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2288 NULL);
2289 if (!NT_STATUS_IS_OK(status)) {
2290 printf("Failed to create file: %s\n", nt_errstr(status));
2291 goto fail;
2294 cli_setpid(cli1, 1);
2296 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2297 if (!NT_STATUS_IS_OK(status)) {
2298 printf("Unable to apply read lock on range 130:4, error was %s\n", nt_errstr(status));
2299 goto fail;
2300 } else {
2301 printf("pid1 successfully locked range 130:4 for READ\n");
2304 if (cli_read(cli1, fnum1, buf, 130, 4) != 4) {
2305 printf("pid1 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2306 goto fail;
2307 } else {
2308 printf("pid1 successfully read the range 130:4\n");
2311 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2312 if (!NT_STATUS_IS_OK(status)) {
2313 printf("pid1 unable to write to the range 130:4, error was "
2314 "%s\n", nt_errstr(status));
2315 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2316 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2317 goto fail;
2319 } else {
2320 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2321 goto fail;
2324 cli_setpid(cli1, 2);
2326 if (cli_read(cli1, fnum1, buf, 130, 4) != 4) {
2327 printf("pid2 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2328 } else {
2329 printf("pid2 successfully read the range 130:4\n");
2332 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2333 if (!NT_STATUS_IS_OK(status)) {
2334 printf("pid2 unable to write to the range 130:4, error was "
2335 "%s\n", nt_errstr(status));
2336 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2337 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2338 goto fail;
2340 } else {
2341 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2342 goto fail;
2345 cli_setpid(cli1, 1);
2346 cli_unlock(cli1, fnum1, 130, 4);
2348 status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2349 if (!NT_STATUS_IS_OK(status)) {
2350 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2351 goto fail;
2352 } else {
2353 printf("pid1 successfully locked range 130:4 for WRITE\n");
2356 if (cli_read(cli1, fnum1, buf, 130, 4) != 4) {
2357 printf("pid1 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2358 goto fail;
2359 } else {
2360 printf("pid1 successfully read the range 130:4\n");
2363 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2364 if (!NT_STATUS_IS_OK(status)) {
2365 printf("pid1 unable to write to the range 130:4, error was "
2366 "%s\n", nt_errstr(status));
2367 goto fail;
2368 } else {
2369 printf("pid1 successfully wrote to the range 130:4\n");
2372 cli_setpid(cli1, 2);
2374 if (cli_read(cli1, fnum1, buf, 130, 4) != 4) {
2375 printf("pid2 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2376 if (NT_STATUS_V(cli_nt_error(cli1)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
2377 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2378 goto fail;
2380 } else {
2381 printf("pid2 successfully read the range 130:4 (should be denied)\n");
2382 goto fail;
2385 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2386 if (!NT_STATUS_IS_OK(status)) {
2387 printf("pid2 unable to write to the range 130:4, error was "
2388 "%s\n", nt_errstr(status));
2389 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2390 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2391 goto fail;
2393 } else {
2394 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2395 goto fail;
2398 cli_unlock(cli1, fnum1, 130, 0);
2399 correct = True;
2401 fail:
2402 cli_close(cli1, fnum1);
2403 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2404 torture_close_connection(cli1);
2406 printf("finished locktest7\n");
2407 return correct;
2411 * This demonstrates a problem with our use of GPFS share modes: A file
2412 * descriptor sitting in the pending close queue holding a GPFS share mode
2413 * blocks opening a file another time. Happens with Word 2007 temp files.
2414 * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2415 * open is denied with NT_STATUS_SHARING_VIOLATION.
2418 static bool run_locktest8(int dummy)
2420 struct cli_state *cli1;
2421 const char *fname = "\\lockt8.lck";
2422 uint16_t fnum1, fnum2;
2423 char buf[200];
2424 bool correct = False;
2425 NTSTATUS status;
2427 if (!torture_open_connection(&cli1, 0)) {
2428 return False;
2431 cli_sockopt(cli1, sockops);
2433 printf("starting locktest8\n");
2435 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2437 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2438 &fnum1);
2439 if (!NT_STATUS_IS_OK(status)) {
2440 d_fprintf(stderr, "cli_open returned %s\n", nt_errstr(status));
2441 return false;
2444 memset(buf, 0, sizeof(buf));
2446 status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2447 if (!NT_STATUS_IS_OK(status)) {
2448 d_fprintf(stderr, "cli_open second time returned %s\n",
2449 nt_errstr(status));
2450 goto fail;
2453 status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2454 if (!NT_STATUS_IS_OK(status)) {
2455 printf("Unable to apply read lock on range 1:1, error was "
2456 "%s\n", nt_errstr(status));
2457 goto fail;
2460 status = cli_close(cli1, fnum1);
2461 if (!NT_STATUS_IS_OK(status)) {
2462 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2463 goto fail;
2466 status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2467 if (!NT_STATUS_IS_OK(status)) {
2468 d_fprintf(stderr, "cli_open third time returned %s\n",
2469 nt_errstr(status));
2470 goto fail;
2473 correct = true;
2475 fail:
2476 cli_close(cli1, fnum1);
2477 cli_close(cli1, fnum2);
2478 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2479 torture_close_connection(cli1);
2481 printf("finished locktest8\n");
2482 return correct;
2486 * This test is designed to be run in conjunction with
2487 * external NFS or POSIX locks taken in the filesystem.
2488 * It checks that the smbd server will block until the
2489 * lock is released and then acquire it. JRA.
2492 static bool got_alarm;
2493 static int alarm_fd;
2495 static void alarm_handler(int dummy)
2497 got_alarm = True;
2500 static void alarm_handler_parent(int dummy)
2502 close(alarm_fd);
2505 static void do_local_lock(int read_fd, int write_fd)
2507 int fd;
2508 char c = '\0';
2509 struct flock lock;
2510 const char *local_pathname = NULL;
2511 int ret;
2513 local_pathname = talloc_asprintf(talloc_tos(),
2514 "%s/lockt9.lck", local_path);
2515 if (!local_pathname) {
2516 printf("child: alloc fail\n");
2517 exit(1);
2520 unlink(local_pathname);
2521 fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2522 if (fd == -1) {
2523 printf("child: open of %s failed %s.\n",
2524 local_pathname, strerror(errno));
2525 exit(1);
2528 /* Now take a fcntl lock. */
2529 lock.l_type = F_WRLCK;
2530 lock.l_whence = SEEK_SET;
2531 lock.l_start = 0;
2532 lock.l_len = 4;
2533 lock.l_pid = getpid();
2535 ret = fcntl(fd,F_SETLK,&lock);
2536 if (ret == -1) {
2537 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2538 local_pathname, strerror(errno));
2539 exit(1);
2540 } else {
2541 printf("child: got lock 0:4 on file %s.\n",
2542 local_pathname );
2543 fflush(stdout);
2546 CatchSignal(SIGALRM, alarm_handler);
2547 alarm(5);
2548 /* Signal the parent. */
2549 if (write(write_fd, &c, 1) != 1) {
2550 printf("child: start signal fail %s.\n",
2551 strerror(errno));
2552 exit(1);
2554 alarm(0);
2556 alarm(10);
2557 /* Wait for the parent to be ready. */
2558 if (read(read_fd, &c, 1) != 1) {
2559 printf("child: reply signal fail %s.\n",
2560 strerror(errno));
2561 exit(1);
2563 alarm(0);
2565 sleep(5);
2566 close(fd);
2567 printf("child: released lock 0:4 on file %s.\n",
2568 local_pathname );
2569 fflush(stdout);
2570 exit(0);
2573 static bool run_locktest9(int dummy)
2575 struct cli_state *cli1;
2576 const char *fname = "\\lockt9.lck";
2577 uint16_t fnum;
2578 bool correct = False;
2579 int pipe_in[2], pipe_out[2];
2580 pid_t child_pid;
2581 char c = '\0';
2582 int ret;
2583 struct timeval start;
2584 double seconds;
2585 NTSTATUS status;
2587 printf("starting locktest9\n");
2589 if (local_path == NULL) {
2590 d_fprintf(stderr, "locktest9 must be given a local path via -l <localpath>\n");
2591 return false;
2594 if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2595 return false;
2598 child_pid = fork();
2599 if (child_pid == -1) {
2600 return false;
2603 if (child_pid == 0) {
2604 /* Child. */
2605 do_local_lock(pipe_out[0], pipe_in[1]);
2606 exit(0);
2609 close(pipe_out[0]);
2610 close(pipe_in[1]);
2611 pipe_out[0] = -1;
2612 pipe_in[1] = -1;
2614 /* Parent. */
2615 ret = read(pipe_in[0], &c, 1);
2616 if (ret != 1) {
2617 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2618 strerror(errno));
2619 return false;
2622 if (!torture_open_connection(&cli1, 0)) {
2623 return false;
2626 cli_sockopt(cli1, sockops);
2628 status = cli_open(cli1, fname, O_RDWR, DENY_NONE,
2629 &fnum);
2630 if (!NT_STATUS_IS_OK(status)) {
2631 d_fprintf(stderr, "cli_open returned %s\n", nt_errstr(status));
2632 return false;
2635 /* Ensure the child has the lock. */
2636 status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2637 if (NT_STATUS_IS_OK(status)) {
2638 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2639 goto fail;
2640 } else {
2641 d_printf("Child has the lock.\n");
2644 /* Tell the child to wait 5 seconds then exit. */
2645 ret = write(pipe_out[1], &c, 1);
2646 if (ret != 1) {
2647 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2648 strerror(errno));
2649 goto fail;
2652 /* Wait 20 seconds for the lock. */
2653 alarm_fd = cli1->fd;
2654 CatchSignal(SIGALRM, alarm_handler_parent);
2655 alarm(20);
2657 start = timeval_current();
2659 status = cli_lock32(cli1, fnum, 0, 4, -1, WRITE_LOCK);
2660 if (!NT_STATUS_IS_OK(status)) {
2661 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2662 "%s\n", nt_errstr(status));
2663 goto fail_nofd;
2665 alarm(0);
2667 seconds = timeval_elapsed(&start);
2669 printf("Parent got the lock after %.2f seconds.\n",
2670 seconds);
2672 status = cli_close(cli1, fnum);
2673 if (!NT_STATUS_IS_OK(status)) {
2674 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2675 goto fail;
2678 correct = true;
2680 fail:
2681 cli_close(cli1, fnum);
2682 torture_close_connection(cli1);
2684 fail_nofd:
2686 printf("finished locktest9\n");
2687 return correct;
2691 test whether fnums and tids open on one VC are available on another (a major
2692 security hole)
2694 static bool run_fdpasstest(int dummy)
2696 struct cli_state *cli1, *cli2;
2697 const char *fname = "\\fdpass.tst";
2698 uint16_t fnum1;
2699 char buf[1024];
2700 NTSTATUS status;
2702 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2703 return False;
2705 cli_sockopt(cli1, sockops);
2706 cli_sockopt(cli2, sockops);
2708 printf("starting fdpasstest\n");
2710 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2712 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
2713 &fnum1);
2714 if (!NT_STATUS_IS_OK(status)) {
2715 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2716 return False;
2719 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
2720 13, NULL);
2721 if (!NT_STATUS_IS_OK(status)) {
2722 printf("write failed (%s)\n", nt_errstr(status));
2723 return False;
2726 cli2->vuid = cli1->vuid;
2727 cli2->cnum = cli1->cnum;
2728 cli2->pid = cli1->pid;
2730 if (cli_read(cli2, fnum1, buf, 0, 13) == 13) {
2731 printf("read succeeded! nasty security hole [%s]\n",
2732 buf);
2733 return False;
2736 cli_close(cli1, fnum1);
2737 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2739 torture_close_connection(cli1);
2740 torture_close_connection(cli2);
2742 printf("finished fdpasstest\n");
2743 return True;
2746 static bool run_fdsesstest(int dummy)
2748 struct cli_state *cli;
2749 uint16 new_vuid;
2750 uint16 saved_vuid;
2751 uint16 new_cnum;
2752 uint16 saved_cnum;
2753 const char *fname = "\\fdsess.tst";
2754 const char *fname1 = "\\fdsess1.tst";
2755 uint16_t fnum1;
2756 uint16_t fnum2;
2757 char buf[1024];
2758 bool ret = True;
2759 NTSTATUS status;
2761 if (!torture_open_connection(&cli, 0))
2762 return False;
2763 cli_sockopt(cli, sockops);
2765 if (!torture_cli_session_setup2(cli, &new_vuid))
2766 return False;
2768 saved_cnum = cli->cnum;
2769 if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, share, "?????", "", 1)))
2770 return False;
2771 new_cnum = cli->cnum;
2772 cli->cnum = saved_cnum;
2774 printf("starting fdsesstest\n");
2776 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2777 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2779 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2780 if (!NT_STATUS_IS_OK(status)) {
2781 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2782 return False;
2785 status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
2786 NULL);
2787 if (!NT_STATUS_IS_OK(status)) {
2788 printf("write failed (%s)\n", nt_errstr(status));
2789 return False;
2792 saved_vuid = cli->vuid;
2793 cli->vuid = new_vuid;
2795 if (cli_read(cli, fnum1, buf, 0, 13) == 13) {
2796 printf("read succeeded with different vuid! nasty security hole [%s]\n",
2797 buf);
2798 ret = False;
2800 /* Try to open a file with different vuid, samba cnum. */
2801 if (NT_STATUS_IS_OK(cli_open(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
2802 printf("create with different vuid, same cnum succeeded.\n");
2803 cli_close(cli, fnum2);
2804 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2805 } else {
2806 printf("create with different vuid, same cnum failed.\n");
2807 printf("This will cause problems with service clients.\n");
2808 ret = False;
2811 cli->vuid = saved_vuid;
2813 /* Try with same vuid, different cnum. */
2814 cli->cnum = new_cnum;
2816 if (cli_read(cli, fnum1, buf, 0, 13) == 13) {
2817 printf("read succeeded with different cnum![%s]\n",
2818 buf);
2819 ret = False;
2822 cli->cnum = saved_cnum;
2823 cli_close(cli, fnum1);
2824 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2826 torture_close_connection(cli);
2828 printf("finished fdsesstest\n");
2829 return ret;
2833 This test checks that
2835 1) the server does not allow an unlink on a file that is open
2837 static bool run_unlinktest(int dummy)
2839 struct cli_state *cli;
2840 const char *fname = "\\unlink.tst";
2841 uint16_t fnum;
2842 bool correct = True;
2843 NTSTATUS status;
2845 if (!torture_open_connection(&cli, 0)) {
2846 return False;
2849 cli_sockopt(cli, sockops);
2851 printf("starting unlink test\n");
2853 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2855 cli_setpid(cli, 1);
2857 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2858 if (!NT_STATUS_IS_OK(status)) {
2859 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2860 return False;
2863 status = cli_unlink(cli, fname,
2864 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2865 if (NT_STATUS_IS_OK(status)) {
2866 printf("error: server allowed unlink on an open file\n");
2867 correct = False;
2868 } else {
2869 correct = check_error(__LINE__, cli, ERRDOS, ERRbadshare,
2870 NT_STATUS_SHARING_VIOLATION);
2873 cli_close(cli, fnum);
2874 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2876 if (!torture_close_connection(cli)) {
2877 correct = False;
2880 printf("unlink test finished\n");
2882 return correct;
2887 test how many open files this server supports on the one socket
2889 static bool run_maxfidtest(int dummy)
2891 struct cli_state *cli;
2892 fstring fname;
2893 uint16_t fnums[0x11000];
2894 int i;
2895 int retries=4;
2896 bool correct = True;
2897 NTSTATUS status;
2899 cli = current_cli;
2901 if (retries <= 0) {
2902 printf("failed to connect\n");
2903 return False;
2906 cli_sockopt(cli, sockops);
2908 for (i=0; i<0x11000; i++) {
2909 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2910 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
2911 &fnums[i]);
2912 if (!NT_STATUS_IS_OK(status)) {
2913 printf("open of %s failed (%s)\n",
2914 fname, nt_errstr(status));
2915 printf("maximum fnum is %d\n", i);
2916 break;
2918 printf("%6d\r", i);
2920 printf("%6d\n", i);
2921 i--;
2923 printf("cleaning up\n");
2924 for (;i>=0;i--) {
2925 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2926 cli_close(cli, fnums[i]);
2928 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2929 if (!NT_STATUS_IS_OK(status)) {
2930 printf("unlink of %s failed (%s)\n",
2931 fname, nt_errstr(status));
2932 correct = False;
2934 printf("%6d\r", i);
2936 printf("%6d\n", 0);
2938 printf("maxfid test finished\n");
2939 if (!torture_close_connection(cli)) {
2940 correct = False;
2942 return correct;
2945 /* generate a random buffer */
2946 static void rand_buf(char *buf, int len)
2948 while (len--) {
2949 *buf = (char)sys_random();
2950 buf++;
2954 /* send smb negprot commands, not reading the response */
2955 static bool run_negprot_nowait(int dummy)
2957 struct tevent_context *ev;
2958 int i;
2959 struct cli_state *cli;
2960 bool correct = True;
2962 printf("starting negprot nowait test\n");
2964 ev = tevent_context_init(talloc_tos());
2965 if (ev == NULL) {
2966 return false;
2969 if (!(cli = open_nbt_connection())) {
2970 TALLOC_FREE(ev);
2971 return False;
2974 for (i=0;i<50000;i++) {
2975 struct tevent_req *req;
2977 req = cli_negprot_send(ev, ev, cli);
2978 if (req == NULL) {
2979 TALLOC_FREE(ev);
2980 return false;
2982 if (!tevent_req_poll(req, ev)) {
2983 d_fprintf(stderr, "tevent_req_poll failed: %s\n",
2984 strerror(errno));
2985 TALLOC_FREE(ev);
2986 return false;
2988 TALLOC_FREE(req);
2991 if (torture_close_connection(cli)) {
2992 correct = False;
2995 printf("finished negprot nowait test\n");
2997 return correct;
3000 /* send smb negprot commands, not reading the response */
3001 static bool run_bad_nbt_session(int dummy)
3003 struct nmb_name called, calling;
3004 struct sockaddr_storage ss;
3005 NTSTATUS status;
3006 int fd;
3007 bool ret;
3009 printf("starting bad nbt session test\n");
3011 make_nmb_name(&calling, myname, 0x0);
3012 make_nmb_name(&called , host, 0x20);
3014 if (!resolve_name(host, &ss, 0x20, true)) {
3015 d_fprintf(stderr, "Could not resolve name %s\n", host);
3016 return false;
3019 status = open_socket_out(&ss, 139, 10000, &fd);
3020 if (!NT_STATUS_IS_OK(status)) {
3021 d_fprintf(stderr, "open_socket_out failed: %s\n",
3022 nt_errstr(status));
3023 return false;
3026 ret = cli_bad_session_request(fd, &calling, &called);
3027 close(fd);
3028 if (!ret) {
3029 d_fprintf(stderr, "open_socket_out failed: %s\n",
3030 nt_errstr(status));
3031 return false;
3034 printf("finished bad nbt session test\n");
3035 return true;
3038 /* send random IPC commands */
3039 static bool run_randomipc(int dummy)
3041 char *rparam = NULL;
3042 char *rdata = NULL;
3043 unsigned int rdrcnt,rprcnt;
3044 char param[1024];
3045 int api, param_len, i;
3046 struct cli_state *cli;
3047 bool correct = True;
3048 int count = 50000;
3050 printf("starting random ipc test\n");
3052 if (!torture_open_connection(&cli, 0)) {
3053 return False;
3056 for (i=0;i<count;i++) {
3057 api = sys_random() % 500;
3058 param_len = (sys_random() % 64);
3060 rand_buf(param, param_len);
3062 SSVAL(param,0,api);
3064 cli_api(cli,
3065 param, param_len, 8,
3066 NULL, 0, BUFFER_SIZE,
3067 &rparam, &rprcnt,
3068 &rdata, &rdrcnt);
3069 if (i % 100 == 0) {
3070 printf("%d/%d\r", i,count);
3073 printf("%d/%d\n", i, count);
3075 if (!torture_close_connection(cli)) {
3076 correct = False;
3079 printf("finished random ipc test\n");
3081 return correct;
3086 static void browse_callback(const char *sname, uint32 stype,
3087 const char *comment, void *state)
3089 printf("\t%20.20s %08x %s\n", sname, stype, comment);
3095 This test checks the browse list code
3098 static bool run_browsetest(int dummy)
3100 static struct cli_state *cli;
3101 bool correct = True;
3103 printf("starting browse test\n");
3105 if (!torture_open_connection(&cli, 0)) {
3106 return False;
3109 printf("domain list:\n");
3110 cli_NetServerEnum(cli, cli->server_domain,
3111 SV_TYPE_DOMAIN_ENUM,
3112 browse_callback, NULL);
3114 printf("machine list:\n");
3115 cli_NetServerEnum(cli, cli->server_domain,
3116 SV_TYPE_ALL,
3117 browse_callback, NULL);
3119 if (!torture_close_connection(cli)) {
3120 correct = False;
3123 printf("browse test finished\n");
3125 return correct;
3131 This checks how the getatr calls works
3133 static bool run_attrtest(int dummy)
3135 struct cli_state *cli;
3136 uint16_t fnum;
3137 time_t t, t2;
3138 const char *fname = "\\attrib123456789.tst";
3139 bool correct = True;
3140 NTSTATUS status;
3142 printf("starting attrib test\n");
3144 if (!torture_open_connection(&cli, 0)) {
3145 return False;
3148 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3149 cli_open(cli, fname,
3150 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3151 cli_close(cli, fnum);
3153 status = cli_getatr(cli, fname, NULL, NULL, &t);
3154 if (!NT_STATUS_IS_OK(status)) {
3155 printf("getatr failed (%s)\n", nt_errstr(status));
3156 correct = False;
3159 if (abs(t - time(NULL)) > 60*60*24*10) {
3160 printf("ERROR: SMBgetatr bug. time is %s",
3161 ctime(&t));
3162 t = time(NULL);
3163 correct = True;
3166 t2 = t-60*60*24; /* 1 day ago */
3168 status = cli_setatr(cli, fname, 0, t2);
3169 if (!NT_STATUS_IS_OK(status)) {
3170 printf("setatr failed (%s)\n", nt_errstr(status));
3171 correct = True;
3174 status = cli_getatr(cli, fname, NULL, NULL, &t);
3175 if (!NT_STATUS_IS_OK(status)) {
3176 printf("getatr failed (%s)\n", nt_errstr(status));
3177 correct = True;
3180 if (t != t2) {
3181 printf("ERROR: getatr/setatr bug. times are\n%s",
3182 ctime(&t));
3183 printf("%s", ctime(&t2));
3184 correct = True;
3187 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3189 if (!torture_close_connection(cli)) {
3190 correct = False;
3193 printf("attrib test finished\n");
3195 return correct;
3200 This checks a couple of trans2 calls
3202 static bool run_trans2test(int dummy)
3204 struct cli_state *cli;
3205 uint16_t fnum;
3206 SMB_OFF_T size;
3207 time_t c_time, a_time, m_time;
3208 struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
3209 const char *fname = "\\trans2.tst";
3210 const char *dname = "\\trans2";
3211 const char *fname2 = "\\trans2\\trans2.tst";
3212 char *pname;
3213 bool correct = True;
3214 NTSTATUS status;
3215 uint32_t fs_attr;
3217 printf("starting trans2 test\n");
3219 if (!torture_open_connection(&cli, 0)) {
3220 return False;
3223 status = cli_get_fs_attr_info(cli, &fs_attr);
3224 if (!NT_STATUS_IS_OK(status)) {
3225 printf("ERROR: cli_get_fs_attr_info returned %s\n",
3226 nt_errstr(status));
3227 correct = false;
3230 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3231 cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3232 status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
3233 &a_time_ts, &w_time_ts, &m_time_ts, NULL);
3234 if (!NT_STATUS_IS_OK(status)) {
3235 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
3236 correct = False;
3239 status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
3240 if (!NT_STATUS_IS_OK(status)) {
3241 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
3242 correct = False;
3245 if (strcmp(pname, fname)) {
3246 printf("qfilename gave different name? [%s] [%s]\n",
3247 fname, pname);
3248 correct = False;
3251 cli_close(cli, fnum);
3253 sleep(2);
3255 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3256 status = cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
3257 &fnum);
3258 if (!NT_STATUS_IS_OK(status)) {
3259 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3260 return False;
3262 cli_close(cli, fnum);
3264 status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
3265 NULL);
3266 if (!NT_STATUS_IS_OK(status)) {
3267 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
3268 correct = False;
3269 } else {
3270 if (c_time != m_time) {
3271 printf("create time=%s", ctime(&c_time));
3272 printf("modify time=%s", ctime(&m_time));
3273 printf("This system appears to have sticky create times\n");
3275 if (a_time % (60*60) == 0) {
3276 printf("access time=%s", ctime(&a_time));
3277 printf("This system appears to set a midnight access time\n");
3278 correct = False;
3281 if (abs(m_time - time(NULL)) > 60*60*24*7) {
3282 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
3283 correct = False;
3288 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3289 cli_open(cli, fname,
3290 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3291 cli_close(cli, fnum);
3292 status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
3293 &m_time_ts, &size, NULL, NULL);
3294 if (!NT_STATUS_IS_OK(status)) {
3295 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3296 correct = False;
3297 } else {
3298 if (w_time_ts.tv_sec < 60*60*24*2) {
3299 printf("write time=%s", ctime(&w_time_ts.tv_sec));
3300 printf("This system appears to set a initial 0 write time\n");
3301 correct = False;
3305 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3308 /* check if the server updates the directory modification time
3309 when creating a new file */
3310 status = cli_mkdir(cli, dname);
3311 if (!NT_STATUS_IS_OK(status)) {
3312 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
3313 correct = False;
3315 sleep(3);
3316 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3317 &w_time_ts, &m_time_ts, &size, NULL, NULL);
3318 if (!NT_STATUS_IS_OK(status)) {
3319 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3320 correct = False;
3323 cli_open(cli, fname2,
3324 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3325 cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
3326 cli_close(cli, fnum);
3327 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3328 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
3329 if (!NT_STATUS_IS_OK(status)) {
3330 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3331 correct = False;
3332 } else {
3333 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
3334 == 0) {
3335 printf("This system does not update directory modification times\n");
3336 correct = False;
3339 cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3340 cli_rmdir(cli, dname);
3342 if (!torture_close_connection(cli)) {
3343 correct = False;
3346 printf("trans2 test finished\n");
3348 return correct;
3352 This checks new W2K calls.
3355 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
3357 uint8_t *buf = NULL;
3358 uint32 len;
3359 NTSTATUS status;
3361 status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
3362 pcli->max_xmit, NULL, &buf, &len);
3363 if (!NT_STATUS_IS_OK(status)) {
3364 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
3365 nt_errstr(status));
3366 } else {
3367 printf("qfileinfo: level %d, len = %u\n", level, len);
3368 dump_data(0, (uint8 *)buf, len);
3369 printf("\n");
3371 TALLOC_FREE(buf);
3372 return status;
3375 static bool run_w2ktest(int dummy)
3377 struct cli_state *cli;
3378 uint16_t fnum;
3379 const char *fname = "\\w2ktest\\w2k.tst";
3380 int level;
3381 bool correct = True;
3383 printf("starting w2k test\n");
3385 if (!torture_open_connection(&cli, 0)) {
3386 return False;
3389 cli_open(cli, fname,
3390 O_RDWR | O_CREAT , DENY_NONE, &fnum);
3392 for (level = 1004; level < 1040; level++) {
3393 new_trans(cli, fnum, level);
3396 cli_close(cli, fnum);
3398 if (!torture_close_connection(cli)) {
3399 correct = False;
3402 printf("w2k test finished\n");
3404 return correct;
3409 this is a harness for some oplock tests
3411 static bool run_oplock1(int dummy)
3413 struct cli_state *cli1;
3414 const char *fname = "\\lockt1.lck";
3415 uint16_t fnum1;
3416 bool correct = True;
3417 NTSTATUS status;
3419 printf("starting oplock test 1\n");
3421 if (!torture_open_connection(&cli1, 0)) {
3422 return False;
3425 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3427 cli_sockopt(cli1, sockops);
3429 cli1->use_oplocks = True;
3431 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3432 &fnum1);
3433 if (!NT_STATUS_IS_OK(status)) {
3434 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3435 return False;
3438 cli1->use_oplocks = False;
3440 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3441 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3443 status = cli_close(cli1, fnum1);
3444 if (!NT_STATUS_IS_OK(status)) {
3445 printf("close2 failed (%s)\n", nt_errstr(status));
3446 return False;
3449 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3450 if (!NT_STATUS_IS_OK(status)) {
3451 printf("unlink failed (%s)\n", nt_errstr(status));
3452 return False;
3455 if (!torture_close_connection(cli1)) {
3456 correct = False;
3459 printf("finished oplock test 1\n");
3461 return correct;
3464 static bool run_oplock2(int dummy)
3466 struct cli_state *cli1, *cli2;
3467 const char *fname = "\\lockt2.lck";
3468 uint16_t fnum1, fnum2;
3469 int saved_use_oplocks = use_oplocks;
3470 char buf[4];
3471 bool correct = True;
3472 volatile bool *shared_correct;
3473 NTSTATUS status;
3475 shared_correct = (volatile bool *)shm_setup(sizeof(bool));
3476 *shared_correct = True;
3478 use_level_II_oplocks = True;
3479 use_oplocks = True;
3481 printf("starting oplock test 2\n");
3483 if (!torture_open_connection(&cli1, 0)) {
3484 use_level_II_oplocks = False;
3485 use_oplocks = saved_use_oplocks;
3486 return False;
3489 cli1->use_oplocks = True;
3490 cli1->use_level_II_oplocks = True;
3492 if (!torture_open_connection(&cli2, 1)) {
3493 use_level_II_oplocks = False;
3494 use_oplocks = saved_use_oplocks;
3495 return False;
3498 cli2->use_oplocks = True;
3499 cli2->use_level_II_oplocks = True;
3501 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3503 cli_sockopt(cli1, sockops);
3504 cli_sockopt(cli2, sockops);
3506 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3507 &fnum1);
3508 if (!NT_STATUS_IS_OK(status)) {
3509 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3510 return False;
3513 /* Don't need the globals any more. */
3514 use_level_II_oplocks = False;
3515 use_oplocks = saved_use_oplocks;
3517 if (fork() == 0) {
3518 /* Child code */
3519 status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
3520 if (!NT_STATUS_IS_OK(status)) {
3521 printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
3522 *shared_correct = False;
3523 exit(0);
3526 sleep(2);
3528 status = cli_close(cli2, fnum2);
3529 if (!NT_STATUS_IS_OK(status)) {
3530 printf("close2 failed (%s)\n", nt_errstr(status));
3531 *shared_correct = False;
3534 exit(0);
3537 sleep(2);
3539 /* Ensure cli1 processes the break. Empty file should always return 0
3540 * bytes. */
3542 if (cli_read(cli1, fnum1, buf, 0, 4) != 0) {
3543 printf("read on fnum1 failed (%s)\n", cli_errstr(cli1));
3544 correct = False;
3547 /* Should now be at level II. */
3548 /* Test if sending a write locks causes a break to none. */
3549 status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
3550 if (!NT_STATUS_IS_OK(status)) {
3551 printf("lock failed (%s)\n", nt_errstr(status));
3552 correct = False;
3555 cli_unlock(cli1, fnum1, 0, 4);
3557 sleep(2);
3559 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
3560 if (!NT_STATUS_IS_OK(status)) {
3561 printf("lock failed (%s)\n", nt_errstr(status));
3562 correct = False;
3565 cli_unlock(cli1, fnum1, 0, 4);
3567 sleep(2);
3569 cli_read(cli1, fnum1, buf, 0, 4);
3571 status = cli_close(cli1, fnum1);
3572 if (!NT_STATUS_IS_OK(status)) {
3573 printf("close1 failed (%s)\n", nt_errstr(status));
3574 correct = False;
3577 sleep(4);
3579 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3580 if (!NT_STATUS_IS_OK(status)) {
3581 printf("unlink failed (%s)\n", nt_errstr(status));
3582 correct = False;
3585 if (!torture_close_connection(cli1)) {
3586 correct = False;
3589 if (!*shared_correct) {
3590 correct = False;
3593 printf("finished oplock test 2\n");
3595 return correct;
3598 struct oplock4_state {
3599 struct tevent_context *ev;
3600 struct cli_state *cli;
3601 bool *got_break;
3602 uint16_t *fnum2;
3605 static void oplock4_got_break(struct tevent_req *req);
3606 static void oplock4_got_open(struct tevent_req *req);
3608 static bool run_oplock4(int dummy)
3610 struct tevent_context *ev;
3611 struct cli_state *cli1, *cli2;
3612 struct tevent_req *oplock_req, *open_req;
3613 const char *fname = "\\lockt4.lck";
3614 const char *fname_ln = "\\lockt4_ln.lck";
3615 uint16_t fnum1, fnum2;
3616 int saved_use_oplocks = use_oplocks;
3617 NTSTATUS status;
3618 bool correct = true;
3620 bool got_break;
3622 struct oplock4_state *state;
3624 printf("starting oplock test 4\n");
3626 if (!torture_open_connection(&cli1, 0)) {
3627 use_level_II_oplocks = false;
3628 use_oplocks = saved_use_oplocks;
3629 return false;
3632 if (!torture_open_connection(&cli2, 1)) {
3633 use_level_II_oplocks = false;
3634 use_oplocks = saved_use_oplocks;
3635 return false;
3638 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3639 cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3641 cli_sockopt(cli1, sockops);
3642 cli_sockopt(cli2, sockops);
3644 /* Create the file. */
3645 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3646 &fnum1);
3647 if (!NT_STATUS_IS_OK(status)) {
3648 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3649 return false;
3652 status = cli_close(cli1, fnum1);
3653 if (!NT_STATUS_IS_OK(status)) {
3654 printf("close1 failed (%s)\n", nt_errstr(status));
3655 return false;
3658 /* Now create a hardlink. */
3659 status = cli_nt_hardlink(cli1, fname, fname_ln);
3660 if (!NT_STATUS_IS_OK(status)) {
3661 printf("nt hardlink failed (%s)\n", nt_errstr(status));
3662 return false;
3665 /* Prove that opening hardlinks cause deny modes to conflict. */
3666 status = cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
3667 if (!NT_STATUS_IS_OK(status)) {
3668 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3669 return false;
3672 status = cli_open(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
3673 if (NT_STATUS_IS_OK(status)) {
3674 printf("open of %s succeeded - should fail with sharing violation.\n",
3675 fname_ln);
3676 return false;
3679 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3680 printf("open of %s should fail with sharing violation. Got %s\n",
3681 fname_ln, nt_errstr(status));
3682 return false;
3685 status = cli_close(cli1, fnum1);
3686 if (!NT_STATUS_IS_OK(status)) {
3687 printf("close1 failed (%s)\n", nt_errstr(status));
3688 return false;
3691 cli1->use_oplocks = true;
3692 cli1->use_level_II_oplocks = true;
3694 cli2->use_oplocks = true;
3695 cli2->use_level_II_oplocks = true;
3697 status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3698 if (!NT_STATUS_IS_OK(status)) {
3699 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3700 return false;
3703 ev = tevent_context_init(talloc_tos());
3704 if (ev == NULL) {
3705 printf("tevent_req_create failed\n");
3706 return false;
3709 state = talloc(ev, struct oplock4_state);
3710 if (state == NULL) {
3711 printf("talloc failed\n");
3712 return false;
3714 state->ev = ev;
3715 state->cli = cli1;
3716 state->got_break = &got_break;
3717 state->fnum2 = &fnum2;
3719 oplock_req = cli_smb_oplock_break_waiter_send(
3720 talloc_tos(), ev, cli1);
3721 if (oplock_req == NULL) {
3722 printf("cli_smb_oplock_break_waiter_send failed\n");
3723 return false;
3725 tevent_req_set_callback(oplock_req, oplock4_got_break, state);
3727 open_req = cli_open_send(
3728 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
3729 if (oplock_req == NULL) {
3730 printf("cli_open_send failed\n");
3731 return false;
3733 tevent_req_set_callback(open_req, oplock4_got_open, state);
3735 got_break = false;
3736 fnum2 = 0xffff;
3738 while (!got_break || fnum2 == 0xffff) {
3739 int ret;
3740 ret = tevent_loop_once(ev);
3741 if (ret == -1) {
3742 printf("tevent_loop_once failed: %s\n",
3743 strerror(errno));
3744 return false;
3748 status = cli_close(cli2, fnum2);
3749 if (!NT_STATUS_IS_OK(status)) {
3750 printf("close2 failed (%s)\n", nt_errstr(status));
3751 correct = false;
3754 status = cli_close(cli1, fnum1);
3755 if (!NT_STATUS_IS_OK(status)) {
3756 printf("close1 failed (%s)\n", nt_errstr(status));
3757 correct = false;
3760 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3761 if (!NT_STATUS_IS_OK(status)) {
3762 printf("unlink failed (%s)\n", nt_errstr(status));
3763 correct = false;
3766 status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3767 if (!NT_STATUS_IS_OK(status)) {
3768 printf("unlink failed (%s)\n", nt_errstr(status));
3769 correct = false;
3772 if (!torture_close_connection(cli1)) {
3773 correct = false;
3776 if (!got_break) {
3777 correct = false;
3780 printf("finished oplock test 4\n");
3782 return correct;
3785 static void oplock4_got_break(struct tevent_req *req)
3787 struct oplock4_state *state = tevent_req_callback_data(
3788 req, struct oplock4_state);
3789 uint16_t fnum;
3790 uint8_t level;
3791 NTSTATUS status;
3793 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
3794 TALLOC_FREE(req);
3795 if (!NT_STATUS_IS_OK(status)) {
3796 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
3797 nt_errstr(status));
3798 return;
3800 *state->got_break = true;
3802 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
3803 NO_OPLOCK);
3804 if (req == NULL) {
3805 printf("cli_oplock_ack_send failed\n");
3806 return;
3810 static void oplock4_got_open(struct tevent_req *req)
3812 struct oplock4_state *state = tevent_req_callback_data(
3813 req, struct oplock4_state);
3814 NTSTATUS status;
3816 status = cli_open_recv(req, state->fnum2);
3817 if (!NT_STATUS_IS_OK(status)) {
3818 printf("cli_open_recv returned %s\n", nt_errstr(status));
3819 *state->fnum2 = 0xffff;
3824 Test delete on close semantics.
3826 static bool run_deletetest(int dummy)
3828 struct cli_state *cli1 = NULL;
3829 struct cli_state *cli2 = NULL;
3830 const char *fname = "\\delete.file";
3831 uint16_t fnum1 = (uint16_t)-1;
3832 uint16_t fnum2 = (uint16_t)-1;
3833 bool correct = True;
3834 NTSTATUS status;
3836 printf("starting delete test\n");
3838 if (!torture_open_connection(&cli1, 0)) {
3839 return False;
3842 cli_sockopt(cli1, sockops);
3844 /* Test 1 - this should delete the file on close. */
3846 cli_setatr(cli1, fname, 0, 0);
3847 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3849 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
3850 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
3851 FILE_DELETE_ON_CLOSE, 0, &fnum1);
3852 if (!NT_STATUS_IS_OK(status)) {
3853 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
3854 correct = False;
3855 goto fail;
3858 status = cli_close(cli1, fnum1);
3859 if (!NT_STATUS_IS_OK(status)) {
3860 printf("[1] close failed (%s)\n", nt_errstr(status));
3861 correct = False;
3862 goto fail;
3865 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1))) {
3866 printf("[1] open of %s succeeded (should fail)\n", fname);
3867 correct = False;
3868 goto fail;
3871 printf("first delete on close test succeeded.\n");
3873 /* Test 2 - this should delete the file on close. */
3875 cli_setatr(cli1, fname, 0, 0);
3876 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3878 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3879 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
3880 FILE_OVERWRITE_IF, 0, 0, &fnum1);
3881 if (!NT_STATUS_IS_OK(status)) {
3882 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
3883 correct = False;
3884 goto fail;
3887 status = cli_nt_delete_on_close(cli1, fnum1, true);
3888 if (!NT_STATUS_IS_OK(status)) {
3889 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
3890 correct = False;
3891 goto fail;
3894 status = cli_close(cli1, fnum1);
3895 if (!NT_STATUS_IS_OK(status)) {
3896 printf("[2] close failed (%s)\n", nt_errstr(status));
3897 correct = False;
3898 goto fail;
3901 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3902 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
3903 status = cli_close(cli1, fnum1);
3904 if (!NT_STATUS_IS_OK(status)) {
3905 printf("[2] close failed (%s)\n", nt_errstr(status));
3906 correct = False;
3907 goto fail;
3909 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3910 } else
3911 printf("second delete on close test succeeded.\n");
3913 /* Test 3 - ... */
3914 cli_setatr(cli1, fname, 0, 0);
3915 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3917 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3918 FILE_ATTRIBUTE_NORMAL,
3919 FILE_SHARE_READ|FILE_SHARE_WRITE,
3920 FILE_OVERWRITE_IF, 0, 0, &fnum1);
3921 if (!NT_STATUS_IS_OK(status)) {
3922 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
3923 correct = False;
3924 goto fail;
3927 /* This should fail with a sharing violation - open for delete is only compatible
3928 with SHARE_DELETE. */
3930 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
3931 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, 0, &fnum2))) {
3932 printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
3933 correct = False;
3934 goto fail;
3937 /* This should succeed. */
3938 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3939 FILE_ATTRIBUTE_NORMAL,
3940 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3941 FILE_OPEN, 0, 0, &fnum2);
3942 if (!NT_STATUS_IS_OK(status)) {
3943 printf("[3] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
3944 correct = False;
3945 goto fail;
3948 status = cli_nt_delete_on_close(cli1, fnum1, true);
3949 if (!NT_STATUS_IS_OK(status)) {
3950 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
3951 correct = False;
3952 goto fail;
3955 status = cli_close(cli1, fnum1);
3956 if (!NT_STATUS_IS_OK(status)) {
3957 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
3958 correct = False;
3959 goto fail;
3962 status = cli_close(cli1, fnum2);
3963 if (!NT_STATUS_IS_OK(status)) {
3964 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
3965 correct = False;
3966 goto fail;
3969 /* This should fail - file should no longer be there. */
3971 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3972 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
3973 status = cli_close(cli1, fnum1);
3974 if (!NT_STATUS_IS_OK(status)) {
3975 printf("[3] close failed (%s)\n", nt_errstr(status));
3977 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3978 correct = False;
3979 goto fail;
3980 } else
3981 printf("third delete on close test succeeded.\n");
3983 /* Test 4 ... */
3984 cli_setatr(cli1, fname, 0, 0);
3985 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3987 status = cli_ntcreate(cli1, fname, 0,
3988 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_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("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
3994 correct = False;
3995 goto fail;
3998 /* This should succeed. */
3999 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4000 FILE_ATTRIBUTE_NORMAL,
4001 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4002 FILE_OPEN, 0, 0, &fnum2);
4003 if (!NT_STATUS_IS_OK(status)) {
4004 printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
4005 correct = False;
4006 goto fail;
4009 status = cli_close(cli1, fnum2);
4010 if (!NT_STATUS_IS_OK(status)) {
4011 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
4012 correct = False;
4013 goto fail;
4016 status = cli_nt_delete_on_close(cli1, fnum1, true);
4017 if (!NT_STATUS_IS_OK(status)) {
4018 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
4019 correct = False;
4020 goto fail;
4023 /* This should fail - no more opens once delete on close set. */
4024 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4025 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4026 FILE_OPEN, 0, 0, &fnum2))) {
4027 printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
4028 correct = False;
4029 goto fail;
4030 } else
4031 printf("fourth delete on close test succeeded.\n");
4033 status = cli_close(cli1, fnum1);
4034 if (!NT_STATUS_IS_OK(status)) {
4035 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
4036 correct = False;
4037 goto fail;
4040 /* Test 5 ... */
4041 cli_setatr(cli1, fname, 0, 0);
4042 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4044 status = cli_open(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
4045 if (!NT_STATUS_IS_OK(status)) {
4046 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4047 correct = False;
4048 goto fail;
4051 /* This should fail - only allowed on NT opens with DELETE access. */
4053 if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4054 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
4055 correct = False;
4056 goto fail;
4059 status = cli_close(cli1, fnum1);
4060 if (!NT_STATUS_IS_OK(status)) {
4061 printf("[5] close - 2 failed (%s)\n", nt_errstr(status));
4062 correct = False;
4063 goto fail;
4066 printf("fifth delete on close test succeeded.\n");
4068 /* Test 6 ... */
4069 cli_setatr(cli1, fname, 0, 0);
4070 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4072 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4073 FILE_ATTRIBUTE_NORMAL,
4074 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4075 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4076 if (!NT_STATUS_IS_OK(status)) {
4077 printf("[6] open of %s failed (%s)\n", fname,
4078 nt_errstr(status));
4079 correct = False;
4080 goto fail;
4083 /* This should fail - only allowed on NT opens with DELETE access. */
4085 if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4086 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
4087 correct = False;
4088 goto fail;
4091 status = cli_close(cli1, fnum1);
4092 if (!NT_STATUS_IS_OK(status)) {
4093 printf("[6] close - 2 failed (%s)\n", nt_errstr(status));
4094 correct = False;
4095 goto fail;
4098 printf("sixth delete on close test succeeded.\n");
4100 /* Test 7 ... */
4101 cli_setatr(cli1, fname, 0, 0);
4102 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4104 status = cli_ntcreate(cli1, fname, 0,
4105 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4106 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
4107 0, 0, &fnum1);
4108 if (!NT_STATUS_IS_OK(status)) {
4109 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4110 correct = False;
4111 goto fail;
4114 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4115 printf("[7] setting delete_on_close on file failed !\n");
4116 correct = False;
4117 goto fail;
4120 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, false))) {
4121 printf("[7] unsetting delete_on_close on file failed !\n");
4122 correct = False;
4123 goto fail;
4126 status = cli_close(cli1, fnum1);
4127 if (!NT_STATUS_IS_OK(status)) {
4128 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4129 correct = False;
4130 goto fail;
4133 /* This next open should succeed - we reset the flag. */
4134 status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4135 if (!NT_STATUS_IS_OK(status)) {
4136 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4137 correct = False;
4138 goto fail;
4141 status = cli_close(cli1, fnum1);
4142 if (!NT_STATUS_IS_OK(status)) {
4143 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4144 correct = False;
4145 goto fail;
4148 printf("seventh delete on close test succeeded.\n");
4150 /* Test 7 ... */
4151 cli_setatr(cli1, fname, 0, 0);
4152 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4154 if (!torture_open_connection(&cli2, 1)) {
4155 printf("[8] failed to open second connection.\n");
4156 correct = False;
4157 goto fail;
4160 cli_sockopt(cli1, sockops);
4162 status = cli_ntcreate(cli1, fname, 0,
4163 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4164 FILE_ATTRIBUTE_NORMAL,
4165 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4166 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4167 if (!NT_STATUS_IS_OK(status)) {
4168 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4169 correct = False;
4170 goto fail;
4173 status = cli_ntcreate(cli2, fname, 0,
4174 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4175 FILE_ATTRIBUTE_NORMAL,
4176 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4177 FILE_OPEN, 0, 0, &fnum2);
4178 if (!NT_STATUS_IS_OK(status)) {
4179 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4180 correct = False;
4181 goto fail;
4184 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4185 printf("[8] setting delete_on_close on file failed !\n");
4186 correct = False;
4187 goto fail;
4190 status = cli_close(cli1, fnum1);
4191 if (!NT_STATUS_IS_OK(status)) {
4192 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
4193 correct = False;
4194 goto fail;
4197 status = cli_close(cli2, fnum2);
4198 if (!NT_STATUS_IS_OK(status)) {
4199 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
4200 correct = False;
4201 goto fail;
4204 /* This should fail.. */
4205 status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4206 if (NT_STATUS_IS_OK(status)) {
4207 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
4208 goto fail;
4209 correct = False;
4210 } else
4211 printf("eighth delete on close test succeeded.\n");
4213 /* This should fail - we need to set DELETE_ACCESS. */
4214 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0,FILE_READ_DATA|FILE_WRITE_DATA,
4215 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE, 0, &fnum1))) {
4216 printf("[9] open of %s succeeded should have failed!\n", fname);
4217 correct = False;
4218 goto fail;
4221 printf("ninth delete on close test succeeded.\n");
4223 status = cli_ntcreate(cli1, fname, 0,
4224 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4225 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4226 FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
4227 0, &fnum1);
4228 if (!NT_STATUS_IS_OK(status)) {
4229 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
4230 correct = False;
4231 goto fail;
4234 /* This should delete the file. */
4235 status = cli_close(cli1, fnum1);
4236 if (!NT_STATUS_IS_OK(status)) {
4237 printf("[10] close failed (%s)\n", nt_errstr(status));
4238 correct = False;
4239 goto fail;
4242 /* This should fail.. */
4243 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
4244 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
4245 goto fail;
4246 correct = False;
4247 } else
4248 printf("tenth delete on close test succeeded.\n");
4250 cli_setatr(cli1, fname, 0, 0);
4251 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4253 /* What error do we get when attempting to open a read-only file with
4254 delete access ? */
4256 /* Create a readonly file. */
4257 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4258 FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
4259 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4260 if (!NT_STATUS_IS_OK(status)) {
4261 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
4262 correct = False;
4263 goto fail;
4266 status = cli_close(cli1, fnum1);
4267 if (!NT_STATUS_IS_OK(status)) {
4268 printf("[11] close failed (%s)\n", nt_errstr(status));
4269 correct = False;
4270 goto fail;
4273 /* Now try open for delete access. */
4274 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES|DELETE_ACCESS,
4275 0, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4276 FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4277 printf("[11] open of %s succeeded should have been denied with ACCESS_DENIED!\n", fname);
4278 cli_close(cli1, fnum1);
4279 goto fail;
4280 correct = False;
4281 } else {
4282 NTSTATUS nterr = cli_nt_error(cli1);
4283 if (!NT_STATUS_EQUAL(nterr,NT_STATUS_ACCESS_DENIED)) {
4284 printf("[11] open of %s should have been denied with ACCESS_DENIED! Got error %s\n", fname, nt_errstr(nterr));
4285 goto fail;
4286 correct = False;
4287 } else {
4288 printf("eleventh delete on close test succeeded.\n");
4292 printf("finished delete test\n");
4294 fail:
4295 /* FIXME: This will crash if we aborted before cli2 got
4296 * intialized, because these functions don't handle
4297 * uninitialized connections. */
4299 if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
4300 if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
4301 cli_setatr(cli1, fname, 0, 0);
4302 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4304 if (cli1 && !torture_close_connection(cli1)) {
4305 correct = False;
4307 if (cli2 && !torture_close_connection(cli2)) {
4308 correct = False;
4310 return correct;
4313 static bool run_deletetest_ln(int dummy)
4315 struct cli_state *cli;
4316 const char *fname = "\\delete1";
4317 const char *fname_ln = "\\delete1_ln";
4318 uint16_t fnum;
4319 uint16_t fnum1;
4320 NTSTATUS status;
4321 bool correct = true;
4322 time_t t;
4324 printf("starting deletetest-ln\n");
4326 if (!torture_open_connection(&cli, 0)) {
4327 return false;
4330 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4331 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4333 cli_sockopt(cli, sockops);
4335 /* Create the file. */
4336 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
4337 if (!NT_STATUS_IS_OK(status)) {
4338 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4339 return false;
4342 status = cli_close(cli, fnum);
4343 if (!NT_STATUS_IS_OK(status)) {
4344 printf("close1 failed (%s)\n", nt_errstr(status));
4345 return false;
4348 /* Now create a hardlink. */
4349 status = cli_nt_hardlink(cli, fname, fname_ln);
4350 if (!NT_STATUS_IS_OK(status)) {
4351 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4352 return false;
4355 /* Open the original file. */
4356 status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
4357 FILE_ATTRIBUTE_NORMAL,
4358 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4359 FILE_OPEN_IF, 0, 0, &fnum);
4360 if (!NT_STATUS_IS_OK(status)) {
4361 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
4362 return false;
4365 /* Unlink the hard link path. */
4366 status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
4367 FILE_ATTRIBUTE_NORMAL,
4368 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4369 FILE_OPEN_IF, 0, 0, &fnum1);
4370 if (!NT_STATUS_IS_OK(status)) {
4371 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
4372 return false;
4374 status = cli_nt_delete_on_close(cli, fnum1, true);
4375 if (!NT_STATUS_IS_OK(status)) {
4376 d_printf("(%s) failed to set delete_on_close %s: %s\n",
4377 __location__, fname_ln, nt_errstr(status));
4378 return false;
4381 status = cli_close(cli, fnum1);
4382 if (!NT_STATUS_IS_OK(status)) {
4383 printf("close %s failed (%s)\n",
4384 fname_ln, nt_errstr(status));
4385 return false;
4388 status = cli_close(cli, fnum);
4389 if (!NT_STATUS_IS_OK(status)) {
4390 printf("close %s failed (%s)\n",
4391 fname, nt_errstr(status));
4392 return false;
4395 /* Ensure the original file is still there. */
4396 status = cli_getatr(cli, fname, NULL, NULL, &t);
4397 if (!NT_STATUS_IS_OK(status)) {
4398 printf("%s getatr on file %s failed (%s)\n",
4399 __location__,
4400 fname,
4401 nt_errstr(status));
4402 correct = False;
4405 /* Ensure the link path is gone. */
4406 status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
4407 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4408 printf("%s, getatr for file %s returned wrong error code %s "
4409 "- should have been deleted\n",
4410 __location__,
4411 fname_ln, nt_errstr(status));
4412 correct = False;
4415 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4416 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4418 if (!torture_close_connection(cli)) {
4419 correct = false;
4422 printf("finished deletetest-ln\n");
4424 return correct;
4428 print out server properties
4430 static bool run_properties(int dummy)
4432 struct cli_state *cli;
4433 bool correct = True;
4435 printf("starting properties test\n");
4437 ZERO_STRUCT(cli);
4439 if (!torture_open_connection(&cli, 0)) {
4440 return False;
4443 cli_sockopt(cli, sockops);
4445 d_printf("Capabilities 0x%08x\n", cli->capabilities);
4447 if (!torture_close_connection(cli)) {
4448 correct = False;
4451 return correct;
4456 /* FIRST_DESIRED_ACCESS 0xf019f */
4457 #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
4458 FILE_READ_EA| /* 0xf */ \
4459 FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
4460 FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
4461 DELETE_ACCESS|READ_CONTROL_ACCESS|\
4462 WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
4463 /* SECOND_DESIRED_ACCESS 0xe0080 */
4464 #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
4465 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4466 WRITE_OWNER_ACCESS /* 0xe0000 */
4468 #if 0
4469 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
4470 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4471 FILE_READ_DATA|\
4472 WRITE_OWNER_ACCESS /* */
4473 #endif
4476 Test ntcreate calls made by xcopy
4478 static bool run_xcopy(int dummy)
4480 static struct cli_state *cli1;
4481 const char *fname = "\\test.txt";
4482 bool correct = True;
4483 uint16_t fnum1, fnum2;
4484 NTSTATUS status;
4486 printf("starting xcopy test\n");
4488 if (!torture_open_connection(&cli1, 0)) {
4489 return False;
4492 status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
4493 FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
4494 FILE_OVERWRITE_IF, 0x4044, 0, &fnum1);
4495 if (!NT_STATUS_IS_OK(status)) {
4496 printf("First open failed - %s\n", nt_errstr(status));
4497 return False;
4500 status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
4501 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4502 FILE_OPEN, 0x200000, 0, &fnum2);
4503 if (!NT_STATUS_IS_OK(status)) {
4504 printf("second open failed - %s\n", nt_errstr(status));
4505 return False;
4508 if (!torture_close_connection(cli1)) {
4509 correct = False;
4512 return correct;
4516 Test rename on files open with share delete and no share delete.
4518 static bool run_rename(int dummy)
4520 static struct cli_state *cli1;
4521 const char *fname = "\\test.txt";
4522 const char *fname1 = "\\test1.txt";
4523 bool correct = True;
4524 uint16_t fnum1;
4525 uint16_t attr;
4526 NTSTATUS status;
4528 printf("starting rename test\n");
4530 if (!torture_open_connection(&cli1, 0)) {
4531 return False;
4534 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4535 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4537 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4538 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
4539 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4540 if (!NT_STATUS_IS_OK(status)) {
4541 printf("First open failed - %s\n", nt_errstr(status));
4542 return False;
4545 status = cli_rename(cli1, fname, fname1);
4546 if (!NT_STATUS_IS_OK(status)) {
4547 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
4548 } else {
4549 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
4550 correct = False;
4553 status = cli_close(cli1, fnum1);
4554 if (!NT_STATUS_IS_OK(status)) {
4555 printf("close - 1 failed (%s)\n", nt_errstr(status));
4556 return False;
4559 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4560 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4561 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4562 #if 0
4563 FILE_SHARE_DELETE|FILE_SHARE_NONE,
4564 #else
4565 FILE_SHARE_DELETE|FILE_SHARE_READ,
4566 #endif
4567 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4568 if (!NT_STATUS_IS_OK(status)) {
4569 printf("Second open failed - %s\n", nt_errstr(status));
4570 return False;
4573 status = cli_rename(cli1, fname, fname1);
4574 if (!NT_STATUS_IS_OK(status)) {
4575 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
4576 correct = False;
4577 } else {
4578 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
4581 status = cli_close(cli1, fnum1);
4582 if (!NT_STATUS_IS_OK(status)) {
4583 printf("close - 2 failed (%s)\n", nt_errstr(status));
4584 return False;
4587 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4588 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4590 status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
4591 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4592 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4593 if (!NT_STATUS_IS_OK(status)) {
4594 printf("Third open failed - %s\n", nt_errstr(status));
4595 return False;
4599 #if 0
4601 uint16_t fnum2;
4603 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
4604 FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4605 printf("Fourth open failed - %s\n", cli_errstr(cli1));
4606 return False;
4608 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum2, true))) {
4609 printf("[8] setting delete_on_close on file failed !\n");
4610 return False;
4613 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
4614 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
4615 return False;
4618 #endif
4620 status = cli_rename(cli1, fname, fname1);
4621 if (!NT_STATUS_IS_OK(status)) {
4622 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
4623 correct = False;
4624 } else {
4625 printf("Third rename succeeded (SHARE_NONE)\n");
4628 status = cli_close(cli1, fnum1);
4629 if (!NT_STATUS_IS_OK(status)) {
4630 printf("close - 3 failed (%s)\n", nt_errstr(status));
4631 return False;
4634 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4635 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4637 /*----*/
4639 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4640 FILE_ATTRIBUTE_NORMAL,
4641 FILE_SHARE_READ | FILE_SHARE_WRITE,
4642 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4643 if (!NT_STATUS_IS_OK(status)) {
4644 printf("Fourth open failed - %s\n", nt_errstr(status));
4645 return False;
4648 status = cli_rename(cli1, fname, fname1);
4649 if (!NT_STATUS_IS_OK(status)) {
4650 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
4651 } else {
4652 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
4653 correct = False;
4656 status = cli_close(cli1, fnum1);
4657 if (!NT_STATUS_IS_OK(status)) {
4658 printf("close - 4 failed (%s)\n", nt_errstr(status));
4659 return False;
4662 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4663 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4665 /*--*/
4667 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4668 FILE_ATTRIBUTE_NORMAL,
4669 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4670 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4671 if (!NT_STATUS_IS_OK(status)) {
4672 printf("Fifth open failed - %s\n", nt_errstr(status));
4673 return False;
4676 status = cli_rename(cli1, fname, fname1);
4677 if (!NT_STATUS_IS_OK(status)) {
4678 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
4679 correct = False;
4680 } else {
4681 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
4685 * Now check if the first name still exists ...
4688 /* if (!NT_STATUS_OP(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4689 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4690 printf("Opening original file after rename of open file fails: %s\n",
4691 cli_errstr(cli1));
4693 else {
4694 printf("Opening original file after rename of open file works ...\n");
4695 (void)cli_close(cli1, fnum2);
4696 } */
4698 /*--*/
4699 status = cli_close(cli1, fnum1);
4700 if (!NT_STATUS_IS_OK(status)) {
4701 printf("close - 5 failed (%s)\n", nt_errstr(status));
4702 return False;
4705 /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
4706 status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
4707 if (!NT_STATUS_IS_OK(status)) {
4708 printf("getatr on file %s failed - %s ! \n",
4709 fname1, nt_errstr(status));
4710 correct = False;
4711 } else {
4712 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
4713 printf("Renamed file %s has wrong attr 0x%x "
4714 "(should be 0x%x)\n",
4715 fname1,
4716 attr,
4717 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
4718 correct = False;
4719 } else {
4720 printf("Renamed file %s has archive bit set\n", fname1);
4724 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4725 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4727 if (!torture_close_connection(cli1)) {
4728 correct = False;
4731 return correct;
4734 static bool run_pipe_number(int dummy)
4736 struct cli_state *cli1;
4737 const char *pipe_name = "\\SPOOLSS";
4738 uint16_t fnum;
4739 int num_pipes = 0;
4740 NTSTATUS status;
4742 printf("starting pipenumber test\n");
4743 if (!torture_open_connection(&cli1, 0)) {
4744 return False;
4747 cli_sockopt(cli1, sockops);
4748 while(1) {
4749 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
4750 FILE_ATTRIBUTE_NORMAL,
4751 FILE_SHARE_READ|FILE_SHARE_WRITE,
4752 FILE_OPEN_IF, 0, 0, &fnum);
4753 if (!NT_STATUS_IS_OK(status)) {
4754 printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
4755 break;
4757 num_pipes++;
4758 printf("\r%6d", num_pipes);
4761 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
4762 torture_close_connection(cli1);
4763 return True;
4767 Test open mode returns on read-only files.
4769 static bool run_opentest(int dummy)
4771 static struct cli_state *cli1;
4772 static struct cli_state *cli2;
4773 const char *fname = "\\readonly.file";
4774 uint16_t fnum1, fnum2;
4775 char buf[20];
4776 SMB_OFF_T fsize;
4777 bool correct = True;
4778 char *tmp_path;
4779 NTSTATUS status;
4781 printf("starting open test\n");
4783 if (!torture_open_connection(&cli1, 0)) {
4784 return False;
4787 cli_setatr(cli1, fname, 0, 0);
4788 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4790 cli_sockopt(cli1, sockops);
4792 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4793 if (!NT_STATUS_IS_OK(status)) {
4794 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4795 return False;
4798 status = cli_close(cli1, fnum1);
4799 if (!NT_STATUS_IS_OK(status)) {
4800 printf("close2 failed (%s)\n", nt_errstr(status));
4801 return False;
4804 status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
4805 if (!NT_STATUS_IS_OK(status)) {
4806 printf("cli_setatr failed (%s)\n", nt_errstr(status));
4807 return False;
4810 status = cli_open(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4811 if (!NT_STATUS_IS_OK(status)) {
4812 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4813 return False;
4816 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
4817 cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4819 if (check_error(__LINE__, cli1, ERRDOS, ERRnoaccess,
4820 NT_STATUS_ACCESS_DENIED)) {
4821 printf("correct error code ERRDOS/ERRnoaccess returned\n");
4824 printf("finished open test 1\n");
4826 cli_close(cli1, fnum1);
4828 /* Now try not readonly and ensure ERRbadshare is returned. */
4830 cli_setatr(cli1, fname, 0, 0);
4832 status = cli_open(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4833 if (!NT_STATUS_IS_OK(status)) {
4834 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4835 return False;
4838 /* This will fail - but the error should be ERRshare. */
4839 cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4841 if (check_error(__LINE__, cli1, ERRDOS, ERRbadshare,
4842 NT_STATUS_SHARING_VIOLATION)) {
4843 printf("correct error code ERRDOS/ERRbadshare returned\n");
4846 status = cli_close(cli1, fnum1);
4847 if (!NT_STATUS_IS_OK(status)) {
4848 printf("close2 failed (%s)\n", nt_errstr(status));
4849 return False;
4852 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4854 printf("finished open test 2\n");
4856 /* Test truncate open disposition on file opened for read. */
4857 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4858 if (!NT_STATUS_IS_OK(status)) {
4859 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
4860 return False;
4863 /* write 20 bytes. */
4865 memset(buf, '\0', 20);
4867 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
4868 if (!NT_STATUS_IS_OK(status)) {
4869 printf("write failed (%s)\n", nt_errstr(status));
4870 correct = False;
4873 status = cli_close(cli1, fnum1);
4874 if (!NT_STATUS_IS_OK(status)) {
4875 printf("(3) close1 failed (%s)\n", nt_errstr(status));
4876 return False;
4879 /* Ensure size == 20. */
4880 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
4881 if (!NT_STATUS_IS_OK(status)) {
4882 printf("(3) getatr failed (%s)\n", nt_errstr(status));
4883 return False;
4886 if (fsize != 20) {
4887 printf("(3) file size != 20\n");
4888 return False;
4891 /* Now test if we can truncate a file opened for readonly. */
4892 status = cli_open(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
4893 if (!NT_STATUS_IS_OK(status)) {
4894 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
4895 return False;
4898 status = cli_close(cli1, fnum1);
4899 if (!NT_STATUS_IS_OK(status)) {
4900 printf("close2 failed (%s)\n", nt_errstr(status));
4901 return False;
4904 /* Ensure size == 0. */
4905 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
4906 if (!NT_STATUS_IS_OK(status)) {
4907 printf("(3) getatr failed (%s)\n", nt_errstr(status));
4908 return False;
4911 if (fsize != 0) {
4912 printf("(3) file size != 0\n");
4913 return False;
4915 printf("finished open test 3\n");
4917 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4919 printf("Do ctemp tests\n");
4920 status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
4921 if (!NT_STATUS_IS_OK(status)) {
4922 printf("ctemp failed (%s)\n", nt_errstr(status));
4923 return False;
4926 printf("ctemp gave path %s\n", tmp_path);
4927 status = cli_close(cli1, fnum1);
4928 if (!NT_STATUS_IS_OK(status)) {
4929 printf("close of temp failed (%s)\n", nt_errstr(status));
4932 status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4933 if (!NT_STATUS_IS_OK(status)) {
4934 printf("unlink of temp failed (%s)\n", nt_errstr(status));
4937 /* Test the non-io opens... */
4939 if (!torture_open_connection(&cli2, 1)) {
4940 return False;
4943 cli_setatr(cli2, fname, 0, 0);
4944 cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4946 cli_sockopt(cli2, sockops);
4948 printf("TEST #1 testing 2 non-io opens (no delete)\n");
4949 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
4950 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4951 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4952 if (!NT_STATUS_IS_OK(status)) {
4953 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4954 return False;
4957 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
4958 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4959 FILE_OPEN_IF, 0, 0, &fnum2);
4960 if (!NT_STATUS_IS_OK(status)) {
4961 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4962 return False;
4965 status = cli_close(cli1, fnum1);
4966 if (!NT_STATUS_IS_OK(status)) {
4967 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
4968 return False;
4971 status = cli_close(cli2, fnum2);
4972 if (!NT_STATUS_IS_OK(status)) {
4973 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
4974 return False;
4977 printf("non-io open test #1 passed.\n");
4979 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4981 printf("TEST #2 testing 2 non-io opens (first with delete)\n");
4983 status = cli_ntcreate(cli1, fname, 0,
4984 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
4985 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4986 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4987 if (!NT_STATUS_IS_OK(status)) {
4988 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4989 return False;
4992 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
4993 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4994 FILE_OPEN_IF, 0, 0, &fnum2);
4995 if (!NT_STATUS_IS_OK(status)) {
4996 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4997 return False;
5000 status = cli_close(cli1, fnum1);
5001 if (!NT_STATUS_IS_OK(status)) {
5002 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5003 return False;
5006 status = cli_close(cli2, fnum2);
5007 if (!NT_STATUS_IS_OK(status)) {
5008 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5009 return False;
5012 printf("non-io open test #2 passed.\n");
5014 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5016 printf("TEST #3 testing 2 non-io opens (second with delete)\n");
5018 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5019 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5020 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5021 if (!NT_STATUS_IS_OK(status)) {
5022 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5023 return False;
5026 status = cli_ntcreate(cli2, fname, 0,
5027 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5028 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5029 FILE_OPEN_IF, 0, 0, &fnum2);
5030 if (!NT_STATUS_IS_OK(status)) {
5031 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5032 return False;
5035 status = cli_close(cli1, fnum1);
5036 if (!NT_STATUS_IS_OK(status)) {
5037 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5038 return False;
5041 status = cli_close(cli2, fnum2);
5042 if (!NT_STATUS_IS_OK(status)) {
5043 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5044 return False;
5047 printf("non-io open test #3 passed.\n");
5049 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5051 printf("TEST #4 testing 2 non-io opens (both with delete)\n");
5053 status = cli_ntcreate(cli1, fname, 0,
5054 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5055 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5056 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5057 if (!NT_STATUS_IS_OK(status)) {
5058 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5059 return False;
5062 status = cli_ntcreate(cli2, fname, 0,
5063 DELETE_ACCESS|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 #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5068 return False;
5071 printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5073 status = cli_close(cli1, fnum1);
5074 if (!NT_STATUS_IS_OK(status)) {
5075 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5076 return False;
5079 printf("non-io open test #4 passed.\n");
5081 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5083 printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
5085 status = cli_ntcreate(cli1, fname, 0,
5086 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5087 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5088 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5089 if (!NT_STATUS_IS_OK(status)) {
5090 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5091 return False;
5094 status = cli_ntcreate(cli2, fname, 0,
5095 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5096 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5097 FILE_OPEN_IF, 0, 0, &fnum2);
5098 if (!NT_STATUS_IS_OK(status)) {
5099 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5100 return False;
5103 status = cli_close(cli1, fnum1);
5104 if (!NT_STATUS_IS_OK(status)) {
5105 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5106 return False;
5109 status = cli_close(cli2, fnum2);
5110 if (!NT_STATUS_IS_OK(status)) {
5111 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5112 return False;
5115 printf("non-io open test #5 passed.\n");
5117 printf("TEST #6 testing 1 non-io open, one io open\n");
5119 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5121 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5122 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5123 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5124 if (!NT_STATUS_IS_OK(status)) {
5125 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5126 return False;
5129 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5130 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
5131 FILE_OPEN_IF, 0, 0, &fnum2);
5132 if (!NT_STATUS_IS_OK(status)) {
5133 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5134 return False;
5137 status = cli_close(cli1, fnum1);
5138 if (!NT_STATUS_IS_OK(status)) {
5139 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5140 return False;
5143 status = cli_close(cli2, fnum2);
5144 if (!NT_STATUS_IS_OK(status)) {
5145 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5146 return False;
5149 printf("non-io open test #6 passed.\n");
5151 printf("TEST #7 testing 1 non-io open, one io open with delete\n");
5153 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5155 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5156 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5157 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5158 if (!NT_STATUS_IS_OK(status)) {
5159 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5160 return False;
5163 status = cli_ntcreate(cli2, fname, 0,
5164 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5165 FILE_ATTRIBUTE_NORMAL,
5166 FILE_SHARE_READ|FILE_SHARE_DELETE,
5167 FILE_OPEN_IF, 0, 0, &fnum2);
5168 if (NT_STATUS_IS_OK(status)) {
5169 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5170 return False;
5173 printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5175 status = cli_close(cli1, fnum1);
5176 if (!NT_STATUS_IS_OK(status)) {
5177 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5178 return False;
5181 printf("non-io open test #7 passed.\n");
5183 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5185 printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
5186 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
5187 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5188 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5189 if (!NT_STATUS_IS_OK(status)) {
5190 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
5191 correct = false;
5192 goto out;
5195 /* Write to ensure we have to update the file time. */
5196 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5197 NULL);
5198 if (!NT_STATUS_IS_OK(status)) {
5199 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
5200 correct = false;
5201 goto out;
5204 status = cli_close(cli1, fnum1);
5205 if (!NT_STATUS_IS_OK(status)) {
5206 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
5207 correct = false;
5210 out:
5212 if (!torture_close_connection(cli1)) {
5213 correct = False;
5215 if (!torture_close_connection(cli2)) {
5216 correct = False;
5219 return correct;
5222 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
5224 uint16 major, minor;
5225 uint32 caplow, caphigh;
5226 NTSTATUS status;
5228 if (!SERVER_HAS_UNIX_CIFS(cli)) {
5229 printf("Server doesn't support UNIX CIFS extensions.\n");
5230 return NT_STATUS_NOT_SUPPORTED;
5233 status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
5234 &caphigh);
5235 if (!NT_STATUS_IS_OK(status)) {
5236 printf("Server didn't return UNIX CIFS extensions: %s\n",
5237 nt_errstr(status));
5238 return status;
5241 status = cli_set_unix_extensions_capabilities(cli, major, minor,
5242 caplow, caphigh);
5243 if (!NT_STATUS_IS_OK(status)) {
5244 printf("Server doesn't support setting UNIX CIFS extensions: "
5245 "%s.\n", nt_errstr(status));
5246 return status;
5249 return NT_STATUS_OK;
5253 Test POSIX open /mkdir calls.
5255 static bool run_simple_posix_open_test(int dummy)
5257 static struct cli_state *cli1;
5258 const char *fname = "posix:file";
5259 const char *hname = "posix:hlink";
5260 const char *sname = "posix:symlink";
5261 const char *dname = "posix:dir";
5262 char buf[10];
5263 char namebuf[11];
5264 uint16_t fnum1 = (uint16_t)-1;
5265 SMB_STRUCT_STAT sbuf;
5266 bool correct = false;
5267 NTSTATUS status;
5269 printf("Starting simple POSIX open test\n");
5271 if (!torture_open_connection(&cli1, 0)) {
5272 return false;
5275 cli_sockopt(cli1, sockops);
5277 status = torture_setup_unix_extensions(cli1);
5278 if (!NT_STATUS_IS_OK(status)) {
5279 return false;
5282 cli_setatr(cli1, fname, 0, 0);
5283 cli_posix_unlink(cli1, fname);
5284 cli_setatr(cli1, dname, 0, 0);
5285 cli_posix_rmdir(cli1, dname);
5286 cli_setatr(cli1, hname, 0, 0);
5287 cli_posix_unlink(cli1, hname);
5288 cli_setatr(cli1, sname, 0, 0);
5289 cli_posix_unlink(cli1, sname);
5291 /* Create a directory. */
5292 status = cli_posix_mkdir(cli1, dname, 0777);
5293 if (!NT_STATUS_IS_OK(status)) {
5294 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
5295 goto out;
5298 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5299 0600, &fnum1);
5300 if (!NT_STATUS_IS_OK(status)) {
5301 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5302 goto out;
5305 /* Test ftruncate - set file size. */
5306 status = cli_ftruncate(cli1, fnum1, 1000);
5307 if (!NT_STATUS_IS_OK(status)) {
5308 printf("ftruncate failed (%s)\n", nt_errstr(status));
5309 goto out;
5312 /* Ensure st_size == 1000 */
5313 status = cli_posix_stat(cli1, fname, &sbuf);
5314 if (!NT_STATUS_IS_OK(status)) {
5315 printf("stat failed (%s)\n", nt_errstr(status));
5316 goto out;
5319 if (sbuf.st_ex_size != 1000) {
5320 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5321 goto out;
5324 /* Test ftruncate - set file size back to zero. */
5325 status = cli_ftruncate(cli1, fnum1, 0);
5326 if (!NT_STATUS_IS_OK(status)) {
5327 printf("ftruncate failed (%s)\n", nt_errstr(status));
5328 goto out;
5331 status = cli_close(cli1, fnum1);
5332 if (!NT_STATUS_IS_OK(status)) {
5333 printf("close failed (%s)\n", nt_errstr(status));
5334 goto out;
5337 /* Now open the file again for read only. */
5338 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5339 if (!NT_STATUS_IS_OK(status)) {
5340 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
5341 goto out;
5344 /* Now unlink while open. */
5345 status = cli_posix_unlink(cli1, fname);
5346 if (!NT_STATUS_IS_OK(status)) {
5347 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5348 goto out;
5351 status = cli_close(cli1, fnum1);
5352 if (!NT_STATUS_IS_OK(status)) {
5353 printf("close(2) failed (%s)\n", nt_errstr(status));
5354 goto out;
5357 /* Ensure the file has gone. */
5358 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5359 if (NT_STATUS_IS_OK(status)) {
5360 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
5361 goto out;
5364 /* Create again to test open with O_TRUNC. */
5365 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
5366 if (!NT_STATUS_IS_OK(status)) {
5367 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5368 goto out;
5371 /* Test ftruncate - set file size. */
5372 status = cli_ftruncate(cli1, fnum1, 1000);
5373 if (!NT_STATUS_IS_OK(status)) {
5374 printf("ftruncate failed (%s)\n", nt_errstr(status));
5375 goto out;
5378 /* Ensure st_size == 1000 */
5379 status = cli_posix_stat(cli1, fname, &sbuf);
5380 if (!NT_STATUS_IS_OK(status)) {
5381 printf("stat failed (%s)\n", nt_errstr(status));
5382 goto out;
5385 if (sbuf.st_ex_size != 1000) {
5386 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5387 goto out;
5390 status = cli_close(cli1, fnum1);
5391 if (!NT_STATUS_IS_OK(status)) {
5392 printf("close(2) failed (%s)\n", nt_errstr(status));
5393 goto out;
5396 /* Re-open with O_TRUNC. */
5397 status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
5398 if (!NT_STATUS_IS_OK(status)) {
5399 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5400 goto out;
5403 /* Ensure st_size == 0 */
5404 status = cli_posix_stat(cli1, fname, &sbuf);
5405 if (!NT_STATUS_IS_OK(status)) {
5406 printf("stat failed (%s)\n", nt_errstr(status));
5407 goto out;
5410 if (sbuf.st_ex_size != 0) {
5411 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
5412 goto out;
5415 status = cli_close(cli1, fnum1);
5416 if (!NT_STATUS_IS_OK(status)) {
5417 printf("close failed (%s)\n", nt_errstr(status));
5418 goto out;
5421 status = cli_posix_unlink(cli1, fname);
5422 if (!NT_STATUS_IS_OK(status)) {
5423 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5424 goto out;
5427 status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
5428 if (!NT_STATUS_IS_OK(status)) {
5429 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
5430 dname, nt_errstr(status));
5431 goto out;
5434 cli_close(cli1, fnum1);
5436 /* What happens when we try and POSIX open a directory for write ? */
5437 status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
5438 if (NT_STATUS_IS_OK(status)) {
5439 printf("POSIX open of directory %s succeeded, should have failed.\n", fname);
5440 goto out;
5441 } else {
5442 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
5443 NT_STATUS_FILE_IS_A_DIRECTORY)) {
5444 goto out;
5448 /* Create the file. */
5449 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5450 0600, &fnum1);
5451 if (!NT_STATUS_IS_OK(status)) {
5452 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5453 goto out;
5456 /* Write some data into it. */
5457 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5458 NULL);
5459 if (!NT_STATUS_IS_OK(status)) {
5460 printf("cli_write failed: %s\n", nt_errstr(status));
5461 goto out;
5464 cli_close(cli1, fnum1);
5466 /* Now create a hardlink. */
5467 status = cli_posix_hardlink(cli1, fname, hname);
5468 if (!NT_STATUS_IS_OK(status)) {
5469 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
5470 goto out;
5473 /* Now create a symlink. */
5474 status = cli_posix_symlink(cli1, fname, sname);
5475 if (!NT_STATUS_IS_OK(status)) {
5476 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
5477 goto out;
5480 /* Open the hardlink for read. */
5481 status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
5482 if (!NT_STATUS_IS_OK(status)) {
5483 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
5484 goto out;
5487 if (cli_read(cli1, fnum1, buf, 0, 10) != 10) {
5488 printf("POSIX read of %s failed (%s)\n", hname, cli_errstr(cli1));
5489 goto out;
5492 if (memcmp(buf, "TEST DATA\n", 10)) {
5493 printf("invalid data read from hardlink\n");
5494 goto out;
5497 /* Do a POSIX lock/unlock. */
5498 status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
5499 if (!NT_STATUS_IS_OK(status)) {
5500 printf("POSIX lock failed %s\n", nt_errstr(status));
5501 goto out;
5504 /* Punch a hole in the locked area. */
5505 status = cli_posix_unlock(cli1, fnum1, 10, 80);
5506 if (!NT_STATUS_IS_OK(status)) {
5507 printf("POSIX unlock failed %s\n", nt_errstr(status));
5508 goto out;
5511 cli_close(cli1, fnum1);
5513 /* Open the symlink for read - this should fail. A POSIX
5514 client should not be doing opens on a symlink. */
5515 status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
5516 if (NT_STATUS_IS_OK(status)) {
5517 printf("POSIX open of %s succeeded (should have failed)\n", sname);
5518 goto out;
5519 } else {
5520 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
5521 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
5522 printf("POSIX open of %s should have failed "
5523 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
5524 "failed with %s instead.\n",
5525 sname, nt_errstr(status));
5526 goto out;
5530 status = cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf));
5531 if (!NT_STATUS_IS_OK(status)) {
5532 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
5533 goto out;
5536 if (strcmp(namebuf, fname) != 0) {
5537 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
5538 sname, fname, namebuf);
5539 goto out;
5542 status = cli_posix_rmdir(cli1, dname);
5543 if (!NT_STATUS_IS_OK(status)) {
5544 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
5545 goto out;
5548 printf("Simple POSIX open test passed\n");
5549 correct = true;
5551 out:
5553 if (fnum1 != (uint16_t)-1) {
5554 cli_close(cli1, fnum1);
5555 fnum1 = (uint16_t)-1;
5558 cli_setatr(cli1, sname, 0, 0);
5559 cli_posix_unlink(cli1, sname);
5560 cli_setatr(cli1, hname, 0, 0);
5561 cli_posix_unlink(cli1, hname);
5562 cli_setatr(cli1, fname, 0, 0);
5563 cli_posix_unlink(cli1, fname);
5564 cli_setatr(cli1, dname, 0, 0);
5565 cli_posix_rmdir(cli1, dname);
5567 if (!torture_close_connection(cli1)) {
5568 correct = false;
5571 return correct;
5575 static uint32 open_attrs_table[] = {
5576 FILE_ATTRIBUTE_NORMAL,
5577 FILE_ATTRIBUTE_ARCHIVE,
5578 FILE_ATTRIBUTE_READONLY,
5579 FILE_ATTRIBUTE_HIDDEN,
5580 FILE_ATTRIBUTE_SYSTEM,
5582 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
5583 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
5584 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
5585 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5586 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5587 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5589 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5590 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5591 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5592 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
5595 struct trunc_open_results {
5596 unsigned int num;
5597 uint32 init_attr;
5598 uint32 trunc_attr;
5599 uint32 result_attr;
5602 static struct trunc_open_results attr_results[] = {
5603 { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5604 { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5605 { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5606 { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5607 { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5608 { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5609 { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5610 { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5611 { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5612 { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5613 { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5614 { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
5615 { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5616 { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5617 { 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 },
5618 { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5619 { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5620 { 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 },
5621 { 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 },
5622 { 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 },
5623 { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5624 { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5625 { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5626 { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5627 { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5628 { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
5631 static bool run_openattrtest(int dummy)
5633 static struct cli_state *cli1;
5634 const char *fname = "\\openattr.file";
5635 uint16_t fnum1;
5636 bool correct = True;
5637 uint16 attr;
5638 unsigned int i, j, k, l;
5639 NTSTATUS status;
5641 printf("starting open attr test\n");
5643 if (!torture_open_connection(&cli1, 0)) {
5644 return False;
5647 cli_sockopt(cli1, sockops);
5649 for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32); i++) {
5650 cli_setatr(cli1, fname, 0, 0);
5651 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5653 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
5654 open_attrs_table[i], FILE_SHARE_NONE,
5655 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5656 if (!NT_STATUS_IS_OK(status)) {
5657 printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5658 return False;
5661 status = cli_close(cli1, fnum1);
5662 if (!NT_STATUS_IS_OK(status)) {
5663 printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5664 return False;
5667 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32); j++) {
5668 status = cli_ntcreate(cli1, fname, 0,
5669 FILE_READ_DATA|FILE_WRITE_DATA,
5670 open_attrs_table[j],
5671 FILE_SHARE_NONE, FILE_OVERWRITE,
5672 0, 0, &fnum1);
5673 if (!NT_STATUS_IS_OK(status)) {
5674 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5675 if (attr_results[l].num == k) {
5676 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
5677 k, open_attrs_table[i],
5678 open_attrs_table[j],
5679 fname, NT_STATUS_V(status), nt_errstr(status));
5680 correct = False;
5684 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5685 printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
5686 k, open_attrs_table[i], open_attrs_table[j],
5687 nt_errstr(status));
5688 correct = False;
5690 #if 0
5691 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
5692 #endif
5693 k++;
5694 continue;
5697 status = cli_close(cli1, fnum1);
5698 if (!NT_STATUS_IS_OK(status)) {
5699 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
5700 return False;
5703 status = cli_getatr(cli1, fname, &attr, NULL, NULL);
5704 if (!NT_STATUS_IS_OK(status)) {
5705 printf("getatr(2) failed (%s)\n", nt_errstr(status));
5706 return False;
5709 #if 0
5710 printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
5711 k, open_attrs_table[i], open_attrs_table[j], attr );
5712 #endif
5714 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5715 if (attr_results[l].num == k) {
5716 if (attr != attr_results[l].result_attr ||
5717 open_attrs_table[i] != attr_results[l].init_attr ||
5718 open_attrs_table[j] != attr_results[l].trunc_attr) {
5719 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
5720 open_attrs_table[i],
5721 open_attrs_table[j],
5722 (unsigned int)attr,
5723 attr_results[l].result_attr);
5724 correct = False;
5726 break;
5729 k++;
5733 cli_setatr(cli1, fname, 0, 0);
5734 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5736 printf("open attr test %s.\n", correct ? "passed" : "failed");
5738 if (!torture_close_connection(cli1)) {
5739 correct = False;
5741 return correct;
5744 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
5745 const char *name, void *state)
5747 int *matched = (int *)state;
5748 if (matched != NULL) {
5749 *matched += 1;
5751 return NT_STATUS_OK;
5755 test directory listing speed
5757 static bool run_dirtest(int dummy)
5759 int i;
5760 static struct cli_state *cli;
5761 uint16_t fnum;
5762 struct timeval core_start;
5763 bool correct = True;
5764 int matched;
5766 printf("starting directory test\n");
5768 if (!torture_open_connection(&cli, 0)) {
5769 return False;
5772 cli_sockopt(cli, sockops);
5774 srandom(0);
5775 for (i=0;i<torture_numops;i++) {
5776 fstring fname;
5777 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5778 if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
5779 fprintf(stderr,"Failed to open %s\n", fname);
5780 return False;
5782 cli_close(cli, fnum);
5785 core_start = timeval_current();
5787 matched = 0;
5788 cli_list(cli, "a*.*", 0, list_fn, &matched);
5789 printf("Matched %d\n", matched);
5791 matched = 0;
5792 cli_list(cli, "b*.*", 0, list_fn, &matched);
5793 printf("Matched %d\n", matched);
5795 matched = 0;
5796 cli_list(cli, "xyzabc", 0, list_fn, &matched);
5797 printf("Matched %d\n", matched);
5799 printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
5801 srandom(0);
5802 for (i=0;i<torture_numops;i++) {
5803 fstring fname;
5804 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5805 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5808 if (!torture_close_connection(cli)) {
5809 correct = False;
5812 printf("finished dirtest\n");
5814 return correct;
5817 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
5818 void *state)
5820 struct cli_state *pcli = (struct cli_state *)state;
5821 fstring fname;
5822 slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
5824 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
5825 return NT_STATUS_OK;
5827 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
5828 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
5829 printf("del_fn: failed to rmdir %s\n,", fname );
5830 } else {
5831 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
5832 printf("del_fn: failed to unlink %s\n,", fname );
5834 return NT_STATUS_OK;
5839 sees what IOCTLs are supported
5841 bool torture_ioctl_test(int dummy)
5843 static struct cli_state *cli;
5844 uint16_t device, function;
5845 uint16_t fnum;
5846 const char *fname = "\\ioctl.dat";
5847 DATA_BLOB blob;
5848 NTSTATUS status;
5850 if (!torture_open_connection(&cli, 0)) {
5851 return False;
5854 printf("starting ioctl test\n");
5856 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5858 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5859 if (!NT_STATUS_IS_OK(status)) {
5860 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5861 return False;
5864 status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
5865 printf("ioctl device info: %s\n", nt_errstr(status));
5867 status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
5868 printf("ioctl job info: %s\n", nt_errstr(status));
5870 for (device=0;device<0x100;device++) {
5871 printf("ioctl test with device = 0x%x\n", device);
5872 for (function=0;function<0x100;function++) {
5873 uint32 code = (device<<16) | function;
5875 status = cli_raw_ioctl(cli, fnum, code, &blob);
5877 if (NT_STATUS_IS_OK(status)) {
5878 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
5879 (int)blob.length);
5880 data_blob_free(&blob);
5885 if (!torture_close_connection(cli)) {
5886 return False;
5889 return True;
5894 tries varients of chkpath
5896 bool torture_chkpath_test(int dummy)
5898 static struct cli_state *cli;
5899 uint16_t fnum;
5900 bool ret;
5901 NTSTATUS status;
5903 if (!torture_open_connection(&cli, 0)) {
5904 return False;
5907 printf("starting chkpath test\n");
5909 /* cleanup from an old run */
5910 cli_rmdir(cli, "\\chkpath.dir\\dir2");
5911 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5912 cli_rmdir(cli, "\\chkpath.dir");
5914 status = cli_mkdir(cli, "\\chkpath.dir");
5915 if (!NT_STATUS_IS_OK(status)) {
5916 printf("mkdir1 failed : %s\n", nt_errstr(status));
5917 return False;
5920 status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
5921 if (!NT_STATUS_IS_OK(status)) {
5922 printf("mkdir2 failed : %s\n", nt_errstr(status));
5923 return False;
5926 status = cli_open(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
5927 DENY_NONE, &fnum);
5928 if (!NT_STATUS_IS_OK(status)) {
5929 printf("open1 failed (%s)\n", nt_errstr(status));
5930 return False;
5932 cli_close(cli, fnum);
5934 status = cli_chkpath(cli, "\\chkpath.dir");
5935 if (!NT_STATUS_IS_OK(status)) {
5936 printf("chkpath1 failed: %s\n", nt_errstr(status));
5937 ret = False;
5940 status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
5941 if (!NT_STATUS_IS_OK(status)) {
5942 printf("chkpath2 failed: %s\n", nt_errstr(status));
5943 ret = False;
5946 status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
5947 if (!NT_STATUS_IS_OK(status)) {
5948 ret = check_error(__LINE__, cli, ERRDOS, ERRbadpath,
5949 NT_STATUS_NOT_A_DIRECTORY);
5950 } else {
5951 printf("* chkpath on a file should fail\n");
5952 ret = False;
5955 if (!NT_STATUS_IS_OK(cli_chkpath(cli, "\\chkpath.dir\\bar.txt"))) {
5956 ret = check_error(__LINE__, cli, ERRDOS, ERRbadfile,
5957 NT_STATUS_OBJECT_NAME_NOT_FOUND);
5958 } else {
5959 printf("* chkpath on a non existant file should fail\n");
5960 ret = False;
5963 if (!NT_STATUS_IS_OK(cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt"))) {
5964 ret = check_error(__LINE__, cli, ERRDOS, ERRbadpath,
5965 NT_STATUS_OBJECT_PATH_NOT_FOUND);
5966 } else {
5967 printf("* chkpath on a non existent component should fail\n");
5968 ret = False;
5971 cli_rmdir(cli, "\\chkpath.dir\\dir2");
5972 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5973 cli_rmdir(cli, "\\chkpath.dir");
5975 if (!torture_close_connection(cli)) {
5976 return False;
5979 return ret;
5982 static bool run_eatest(int dummy)
5984 static struct cli_state *cli;
5985 const char *fname = "\\eatest.txt";
5986 bool correct = True;
5987 uint16_t fnum;
5988 int i;
5989 size_t num_eas;
5990 struct ea_struct *ea_list = NULL;
5991 TALLOC_CTX *mem_ctx = talloc_init("eatest");
5992 NTSTATUS status;
5994 printf("starting eatest\n");
5996 if (!torture_open_connection(&cli, 0)) {
5997 talloc_destroy(mem_ctx);
5998 return False;
6001 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6003 status = cli_ntcreate(cli, fname, 0,
6004 FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6005 FILE_SHARE_NONE, FILE_OVERWRITE_IF,
6006 0x4044, 0, &fnum);
6007 if (!NT_STATUS_IS_OK(status)) {
6008 printf("open failed - %s\n", nt_errstr(status));
6009 talloc_destroy(mem_ctx);
6010 return False;
6013 for (i = 0; i < 10; i++) {
6014 fstring ea_name, ea_val;
6016 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
6017 memset(ea_val, (char)i+1, i+1);
6018 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
6019 if (!NT_STATUS_IS_OK(status)) {
6020 printf("ea_set of name %s failed - %s\n", ea_name,
6021 nt_errstr(status));
6022 talloc_destroy(mem_ctx);
6023 return False;
6027 cli_close(cli, fnum);
6028 for (i = 0; i < 10; i++) {
6029 fstring ea_name, ea_val;
6031 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
6032 memset(ea_val, (char)i+1, i+1);
6033 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
6034 if (!NT_STATUS_IS_OK(status)) {
6035 printf("ea_set of name %s failed - %s\n", ea_name,
6036 nt_errstr(status));
6037 talloc_destroy(mem_ctx);
6038 return False;
6042 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6043 if (!NT_STATUS_IS_OK(status)) {
6044 printf("ea_get list failed - %s\n", nt_errstr(status));
6045 correct = False;
6048 printf("num_eas = %d\n", (int)num_eas);
6050 if (num_eas != 20) {
6051 printf("Should be 20 EA's stored... failing.\n");
6052 correct = False;
6055 for (i = 0; i < num_eas; i++) {
6056 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6057 dump_data(0, ea_list[i].value.data,
6058 ea_list[i].value.length);
6061 /* Setting EA's to zero length deletes them. Test this */
6062 printf("Now deleting all EA's - case indepenent....\n");
6064 #if 1
6065 cli_set_ea_path(cli, fname, "", "", 0);
6066 #else
6067 for (i = 0; i < 20; i++) {
6068 fstring ea_name;
6069 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
6070 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
6071 if (!NT_STATUS_IS_OK(status)) {
6072 printf("ea_set of name %s failed - %s\n", ea_name,
6073 nt_errstr(status));
6074 talloc_destroy(mem_ctx);
6075 return False;
6078 #endif
6080 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6081 if (!NT_STATUS_IS_OK(status)) {
6082 printf("ea_get list failed - %s\n", nt_errstr(status));
6083 correct = False;
6086 printf("num_eas = %d\n", (int)num_eas);
6087 for (i = 0; i < num_eas; i++) {
6088 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6089 dump_data(0, ea_list[i].value.data,
6090 ea_list[i].value.length);
6093 if (num_eas != 0) {
6094 printf("deleting EA's failed.\n");
6095 correct = False;
6098 /* Try and delete a non existant EA. */
6099 status = cli_set_ea_path(cli, fname, "foo", "", 0);
6100 if (!NT_STATUS_IS_OK(status)) {
6101 printf("deleting non-existant EA 'foo' should succeed. %s\n",
6102 nt_errstr(status));
6103 correct = False;
6106 talloc_destroy(mem_ctx);
6107 if (!torture_close_connection(cli)) {
6108 correct = False;
6111 return correct;
6114 static bool run_dirtest1(int dummy)
6116 int i;
6117 static struct cli_state *cli;
6118 uint16_t fnum;
6119 int num_seen;
6120 bool correct = True;
6122 printf("starting directory test\n");
6124 if (!torture_open_connection(&cli, 0)) {
6125 return False;
6128 cli_sockopt(cli, sockops);
6130 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6131 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6132 cli_rmdir(cli, "\\LISTDIR");
6133 cli_mkdir(cli, "\\LISTDIR");
6135 /* Create 1000 files and 1000 directories. */
6136 for (i=0;i<1000;i++) {
6137 fstring fname;
6138 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
6139 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6140 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum))) {
6141 fprintf(stderr,"Failed to open %s\n", fname);
6142 return False;
6144 cli_close(cli, fnum);
6146 for (i=0;i<1000;i++) {
6147 fstring fname;
6148 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
6149 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
6150 fprintf(stderr,"Failed to open %s\n", fname);
6151 return False;
6155 /* Now ensure that doing an old list sees both files and directories. */
6156 num_seen = 0;
6157 cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6158 printf("num_seen = %d\n", num_seen );
6159 /* We should see 100 files + 1000 directories + . and .. */
6160 if (num_seen != 2002)
6161 correct = False;
6163 /* Ensure if we have the "must have" bits we only see the
6164 * relevent entries.
6166 num_seen = 0;
6167 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6168 printf("num_seen = %d\n", num_seen );
6169 if (num_seen != 1002)
6170 correct = False;
6172 num_seen = 0;
6173 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6174 printf("num_seen = %d\n", num_seen );
6175 if (num_seen != 1000)
6176 correct = False;
6178 /* Delete everything. */
6179 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6180 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6181 cli_rmdir(cli, "\\LISTDIR");
6183 #if 0
6184 printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
6185 printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
6186 printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
6187 #endif
6189 if (!torture_close_connection(cli)) {
6190 correct = False;
6193 printf("finished dirtest1\n");
6195 return correct;
6198 static bool run_error_map_extract(int dummy) {
6200 static struct cli_state *c_dos;
6201 static struct cli_state *c_nt;
6202 NTSTATUS status;
6204 uint32 error;
6206 uint32 errnum;
6207 uint8 errclass;
6209 NTSTATUS nt_status;
6211 fstring user;
6213 /* NT-Error connection */
6215 if (!(c_nt = open_nbt_connection())) {
6216 return False;
6219 c_nt->use_spnego = False;
6221 status = cli_negprot(c_nt);
6223 if (!NT_STATUS_IS_OK(status)) {
6224 printf("%s rejected the NT-error negprot (%s)\n", host,
6225 nt_errstr(status));
6226 cli_shutdown(c_nt);
6227 return False;
6230 status = cli_session_setup(c_nt, "", "", 0, "", 0, workgroup);
6231 if (!NT_STATUS_IS_OK(status)) {
6232 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
6233 return False;
6236 /* DOS-Error connection */
6238 if (!(c_dos = open_nbt_connection())) {
6239 return False;
6242 c_dos->use_spnego = False;
6243 c_dos->force_dos_errors = True;
6245 status = cli_negprot(c_dos);
6246 if (!NT_STATUS_IS_OK(status)) {
6247 printf("%s rejected the DOS-error negprot (%s)\n", host,
6248 nt_errstr(status));
6249 cli_shutdown(c_dos);
6250 return False;
6253 status = cli_session_setup(c_dos, "", "", 0, "", 0, workgroup);
6254 if (!NT_STATUS_IS_OK(status)) {
6255 printf("%s rejected the DOS-error initial session setup (%s)\n",
6256 host, nt_errstr(status));
6257 return False;
6260 for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
6261 fstr_sprintf(user, "%X", error);
6263 status = cli_session_setup(c_nt, user,
6264 password, strlen(password),
6265 password, strlen(password),
6266 workgroup);
6267 if (NT_STATUS_IS_OK(status)) {
6268 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
6271 /* Case #1: 32-bit NT errors */
6272 if (cli_is_nt_error(c_nt)) {
6273 nt_status = cli_nt_error(c_nt);
6274 } else {
6275 printf("/** Dos error on NT connection! (%s) */\n",
6276 cli_errstr(c_nt));
6277 nt_status = NT_STATUS(0xc0000000);
6280 status = cli_session_setup(c_dos, user,
6281 password, strlen(password),
6282 password, strlen(password),
6283 workgroup);
6284 if (NT_STATUS_IS_OK(status)) {
6285 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
6288 /* Case #1: 32-bit NT errors */
6289 if (!cli_is_dos_error(c_dos)) {
6290 printf("/** NT error on DOS connection! (%s) */\n",
6291 cli_errstr(c_dos));
6292 errnum = errclass = 0;
6293 } else {
6294 cli_dos_error(c_dos, &errclass, &errnum);
6297 if (NT_STATUS_V(nt_status) != error) {
6298 printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
6299 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
6300 get_nt_error_c_code(talloc_tos(), nt_status));
6303 printf("\t{%s,\t%s,\t%s},\n",
6304 smb_dos_err_class(errclass),
6305 smb_dos_err_name(errclass, errnum),
6306 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
6308 return True;
6311 static bool run_sesssetup_bench(int dummy)
6313 static struct cli_state *c;
6314 const char *fname = "\\file.dat";
6315 uint16_t fnum;
6316 NTSTATUS status;
6317 int i;
6319 if (!torture_open_connection(&c, 0)) {
6320 return false;
6323 status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6324 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6325 FILE_DELETE_ON_CLOSE, 0, &fnum);
6326 if (!NT_STATUS_IS_OK(status)) {
6327 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
6328 return false;
6331 for (i=0; i<torture_numops; i++) {
6332 status = cli_session_setup(
6333 c, username,
6334 password, strlen(password),
6335 password, strlen(password),
6336 workgroup);
6337 if (!NT_STATUS_IS_OK(status)) {
6338 d_printf("(%s) cli_session_setup failed: %s\n",
6339 __location__, nt_errstr(status));
6340 return false;
6343 d_printf("\r%d ", (int)c->vuid);
6345 status = cli_ulogoff(c);
6346 if (!NT_STATUS_IS_OK(status)) {
6347 d_printf("(%s) cli_ulogoff failed: %s\n",
6348 __location__, nt_errstr(status));
6349 return false;
6351 c->vuid = 0;
6354 return true;
6357 static bool subst_test(const char *str, const char *user, const char *domain,
6358 uid_t uid, gid_t gid, const char *expected)
6360 char *subst;
6361 bool result = true;
6363 subst = talloc_sub_specified(talloc_tos(), str, user, domain, uid, gid);
6365 if (strcmp(subst, expected) != 0) {
6366 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
6367 "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
6368 expected);
6369 result = false;
6372 TALLOC_FREE(subst);
6373 return result;
6376 static void chain1_open_completion(struct tevent_req *req)
6378 uint16_t fnum;
6379 NTSTATUS status;
6380 status = cli_open_recv(req, &fnum);
6381 TALLOC_FREE(req);
6383 d_printf("cli_open_recv returned %s: %d\n",
6384 nt_errstr(status),
6385 NT_STATUS_IS_OK(status) ? fnum : -1);
6388 static void chain1_write_completion(struct tevent_req *req)
6390 size_t written;
6391 NTSTATUS status;
6392 status = cli_write_andx_recv(req, &written);
6393 TALLOC_FREE(req);
6395 d_printf("cli_write_andx_recv returned %s: %d\n",
6396 nt_errstr(status),
6397 NT_STATUS_IS_OK(status) ? (int)written : -1);
6400 static void chain1_close_completion(struct tevent_req *req)
6402 NTSTATUS status;
6403 bool *done = (bool *)tevent_req_callback_data_void(req);
6405 status = cli_close_recv(req);
6406 *done = true;
6408 TALLOC_FREE(req);
6410 d_printf("cli_close returned %s\n", nt_errstr(status));
6413 static bool run_chain1(int dummy)
6415 struct cli_state *cli1;
6416 struct event_context *evt = event_context_init(NULL);
6417 struct tevent_req *reqs[3], *smbreqs[3];
6418 bool done = false;
6419 const char *str = "foobar";
6420 NTSTATUS status;
6422 printf("starting chain1 test\n");
6423 if (!torture_open_connection(&cli1, 0)) {
6424 return False;
6427 cli_sockopt(cli1, sockops);
6429 reqs[0] = cli_open_create(talloc_tos(), evt, cli1, "\\test",
6430 O_CREAT|O_RDWR, 0, &smbreqs[0]);
6431 if (reqs[0] == NULL) return false;
6432 tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
6435 reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
6436 (const uint8_t *)str, 0, strlen(str)+1,
6437 smbreqs, 1, &smbreqs[1]);
6438 if (reqs[1] == NULL) return false;
6439 tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
6441 reqs[2] = cli_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
6442 if (reqs[2] == NULL) return false;
6443 tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
6445 status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
6446 if (!NT_STATUS_IS_OK(status)) {
6447 return false;
6450 while (!done) {
6451 event_loop_once(evt);
6454 torture_close_connection(cli1);
6455 return True;
6458 static void chain2_sesssetup_completion(struct tevent_req *req)
6460 NTSTATUS status;
6461 status = cli_session_setup_guest_recv(req);
6462 d_printf("sesssetup returned %s\n", nt_errstr(status));
6465 static void chain2_tcon_completion(struct tevent_req *req)
6467 bool *done = (bool *)tevent_req_callback_data_void(req);
6468 NTSTATUS status;
6469 status = cli_tcon_andx_recv(req);
6470 d_printf("tcon_and_x returned %s\n", nt_errstr(status));
6471 *done = true;
6474 static bool run_chain2(int dummy)
6476 struct cli_state *cli1;
6477 struct event_context *evt = event_context_init(NULL);
6478 struct tevent_req *reqs[2], *smbreqs[2];
6479 bool done = false;
6480 NTSTATUS status;
6482 printf("starting chain2 test\n");
6483 status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
6484 port_to_use, Undefined, 0);
6485 if (!NT_STATUS_IS_OK(status)) {
6486 return False;
6489 cli_sockopt(cli1, sockops);
6491 reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
6492 &smbreqs[0]);
6493 if (reqs[0] == NULL) return false;
6494 tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
6496 reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
6497 "?????", NULL, 0, &smbreqs[1]);
6498 if (reqs[1] == NULL) return false;
6499 tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
6501 status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
6502 if (!NT_STATUS_IS_OK(status)) {
6503 return false;
6506 while (!done) {
6507 event_loop_once(evt);
6510 torture_close_connection(cli1);
6511 return True;
6515 struct torture_createdel_state {
6516 struct tevent_context *ev;
6517 struct cli_state *cli;
6520 static void torture_createdel_created(struct tevent_req *subreq);
6521 static void torture_createdel_closed(struct tevent_req *subreq);
6523 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
6524 struct tevent_context *ev,
6525 struct cli_state *cli,
6526 const char *name)
6528 struct tevent_req *req, *subreq;
6529 struct torture_createdel_state *state;
6531 req = tevent_req_create(mem_ctx, &state,
6532 struct torture_createdel_state);
6533 if (req == NULL) {
6534 return NULL;
6536 state->ev = ev;
6537 state->cli = cli;
6539 subreq = cli_ntcreate_send(
6540 state, ev, cli, name, 0,
6541 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
6542 FILE_ATTRIBUTE_NORMAL,
6543 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6544 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
6546 if (tevent_req_nomem(subreq, req)) {
6547 return tevent_req_post(req, ev);
6549 tevent_req_set_callback(subreq, torture_createdel_created, req);
6550 return req;
6553 static void torture_createdel_created(struct tevent_req *subreq)
6555 struct tevent_req *req = tevent_req_callback_data(
6556 subreq, struct tevent_req);
6557 struct torture_createdel_state *state = tevent_req_data(
6558 req, struct torture_createdel_state);
6559 NTSTATUS status;
6560 uint16_t fnum;
6562 status = cli_ntcreate_recv(subreq, &fnum);
6563 TALLOC_FREE(subreq);
6564 if (!NT_STATUS_IS_OK(status)) {
6565 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
6566 nt_errstr(status)));
6567 tevent_req_nterror(req, status);
6568 return;
6571 subreq = cli_close_send(state, state->ev, state->cli, fnum);
6572 if (tevent_req_nomem(subreq, req)) {
6573 return;
6575 tevent_req_set_callback(subreq, torture_createdel_closed, req);
6578 static void torture_createdel_closed(struct tevent_req *subreq)
6580 struct tevent_req *req = tevent_req_callback_data(
6581 subreq, struct tevent_req);
6582 NTSTATUS status;
6584 status = cli_close_recv(subreq);
6585 if (!NT_STATUS_IS_OK(status)) {
6586 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
6587 tevent_req_nterror(req, status);
6588 return;
6590 tevent_req_done(req);
6593 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
6595 return tevent_req_simple_recv_ntstatus(req);
6598 struct torture_createdels_state {
6599 struct tevent_context *ev;
6600 struct cli_state *cli;
6601 const char *base_name;
6602 int sent;
6603 int received;
6604 int num_files;
6605 struct tevent_req **reqs;
6608 static void torture_createdels_done(struct tevent_req *subreq);
6610 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
6611 struct tevent_context *ev,
6612 struct cli_state *cli,
6613 const char *base_name,
6614 int num_parallel,
6615 int num_files)
6617 struct tevent_req *req;
6618 struct torture_createdels_state *state;
6619 int i;
6621 req = tevent_req_create(mem_ctx, &state,
6622 struct torture_createdels_state);
6623 if (req == NULL) {
6624 return NULL;
6626 state->ev = ev;
6627 state->cli = cli;
6628 state->base_name = talloc_strdup(state, base_name);
6629 if (tevent_req_nomem(state->base_name, req)) {
6630 return tevent_req_post(req, ev);
6632 state->num_files = MAX(num_parallel, num_files);
6633 state->sent = 0;
6634 state->received = 0;
6636 state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
6637 if (tevent_req_nomem(state->reqs, req)) {
6638 return tevent_req_post(req, ev);
6641 for (i=0; i<num_parallel; i++) {
6642 char *name;
6644 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6645 state->sent);
6646 if (tevent_req_nomem(name, req)) {
6647 return tevent_req_post(req, ev);
6649 state->reqs[i] = torture_createdel_send(
6650 state->reqs, state->ev, state->cli, name);
6651 if (tevent_req_nomem(state->reqs[i], req)) {
6652 return tevent_req_post(req, ev);
6654 name = talloc_move(state->reqs[i], &name);
6655 tevent_req_set_callback(state->reqs[i],
6656 torture_createdels_done, req);
6657 state->sent += 1;
6659 return req;
6662 static void torture_createdels_done(struct tevent_req *subreq)
6664 struct tevent_req *req = tevent_req_callback_data(
6665 subreq, struct tevent_req);
6666 struct torture_createdels_state *state = tevent_req_data(
6667 req, struct torture_createdels_state);
6668 size_t num_parallel = talloc_array_length(state->reqs);
6669 NTSTATUS status;
6670 char *name;
6671 int i;
6673 status = torture_createdel_recv(subreq);
6674 if (!NT_STATUS_IS_OK(status)){
6675 DEBUG(10, ("torture_createdel_recv returned %s\n",
6676 nt_errstr(status)));
6677 TALLOC_FREE(subreq);
6678 tevent_req_nterror(req, status);
6679 return;
6682 for (i=0; i<num_parallel; i++) {
6683 if (subreq == state->reqs[i]) {
6684 break;
6687 if (i == num_parallel) {
6688 DEBUG(10, ("received something we did not send\n"));
6689 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
6690 return;
6692 TALLOC_FREE(state->reqs[i]);
6694 if (state->sent >= state->num_files) {
6695 tevent_req_done(req);
6696 return;
6699 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6700 state->sent);
6701 if (tevent_req_nomem(name, req)) {
6702 return;
6704 state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
6705 state->cli, name);
6706 if (tevent_req_nomem(state->reqs[i], req)) {
6707 return;
6709 name = talloc_move(state->reqs[i], &name);
6710 tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
6711 state->sent += 1;
6714 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
6716 return tevent_req_simple_recv_ntstatus(req);
6719 struct swallow_notify_state {
6720 struct tevent_context *ev;
6721 struct cli_state *cli;
6722 uint16_t fnum;
6723 uint32_t completion_filter;
6724 bool recursive;
6725 bool (*fn)(uint32_t action, const char *name, void *priv);
6726 void *priv;
6729 static void swallow_notify_done(struct tevent_req *subreq);
6731 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
6732 struct tevent_context *ev,
6733 struct cli_state *cli,
6734 uint16_t fnum,
6735 uint32_t completion_filter,
6736 bool recursive,
6737 bool (*fn)(uint32_t action,
6738 const char *name,
6739 void *priv),
6740 void *priv)
6742 struct tevent_req *req, *subreq;
6743 struct swallow_notify_state *state;
6745 req = tevent_req_create(mem_ctx, &state,
6746 struct swallow_notify_state);
6747 if (req == NULL) {
6748 return NULL;
6750 state->ev = ev;
6751 state->cli = cli;
6752 state->fnum = fnum;
6753 state->completion_filter = completion_filter;
6754 state->recursive = recursive;
6755 state->fn = fn;
6756 state->priv = priv;
6758 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6759 0xffff, state->completion_filter,
6760 state->recursive);
6761 if (tevent_req_nomem(subreq, req)) {
6762 return tevent_req_post(req, ev);
6764 tevent_req_set_callback(subreq, swallow_notify_done, req);
6765 return req;
6768 static void swallow_notify_done(struct tevent_req *subreq)
6770 struct tevent_req *req = tevent_req_callback_data(
6771 subreq, struct tevent_req);
6772 struct swallow_notify_state *state = tevent_req_data(
6773 req, struct swallow_notify_state);
6774 NTSTATUS status;
6775 uint32_t i, num_changes;
6776 struct notify_change *changes;
6778 status = cli_notify_recv(subreq, state, &num_changes, &changes);
6779 TALLOC_FREE(subreq);
6780 if (!NT_STATUS_IS_OK(status)) {
6781 DEBUG(10, ("cli_notify_recv returned %s\n",
6782 nt_errstr(status)));
6783 tevent_req_nterror(req, status);
6784 return;
6787 for (i=0; i<num_changes; i++) {
6788 state->fn(changes[i].action, changes[i].name, state->priv);
6790 TALLOC_FREE(changes);
6792 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6793 0xffff, state->completion_filter,
6794 state->recursive);
6795 if (tevent_req_nomem(subreq, req)) {
6796 return;
6798 tevent_req_set_callback(subreq, swallow_notify_done, req);
6801 static bool print_notifies(uint32_t action, const char *name, void *priv)
6803 if (DEBUGLEVEL > 5) {
6804 d_printf("%d %s\n", (int)action, name);
6806 return true;
6809 static void notify_bench_done(struct tevent_req *req)
6811 int *num_finished = (int *)tevent_req_callback_data_void(req);
6812 *num_finished += 1;
6815 static bool run_notify_bench(int dummy)
6817 const char *dname = "\\notify-bench";
6818 struct tevent_context *ev;
6819 NTSTATUS status;
6820 uint16_t dnum;
6821 struct tevent_req *req1;
6822 struct tevent_req *req2 = NULL;
6823 int i, num_unc_names;
6824 int num_finished = 0;
6826 printf("starting notify-bench test\n");
6828 if (use_multishare_conn) {
6829 char **unc_list;
6830 unc_list = file_lines_load(multishare_conn_fname,
6831 &num_unc_names, 0, NULL);
6832 if (!unc_list || num_unc_names <= 0) {
6833 d_printf("Failed to load unc names list from '%s'\n",
6834 multishare_conn_fname);
6835 return false;
6837 TALLOC_FREE(unc_list);
6838 } else {
6839 num_unc_names = 1;
6842 ev = tevent_context_init(talloc_tos());
6843 if (ev == NULL) {
6844 d_printf("tevent_context_init failed\n");
6845 return false;
6848 for (i=0; i<num_unc_names; i++) {
6849 struct cli_state *cli;
6850 char *base_fname;
6852 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
6853 dname, i);
6854 if (base_fname == NULL) {
6855 return false;
6858 if (!torture_open_connection(&cli, i)) {
6859 return false;
6862 status = cli_ntcreate(cli, dname, 0,
6863 MAXIMUM_ALLOWED_ACCESS,
6864 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
6865 FILE_SHARE_DELETE,
6866 FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
6867 &dnum);
6869 if (!NT_STATUS_IS_OK(status)) {
6870 d_printf("Could not create %s: %s\n", dname,
6871 nt_errstr(status));
6872 return false;
6875 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
6876 FILE_NOTIFY_CHANGE_FILE_NAME |
6877 FILE_NOTIFY_CHANGE_DIR_NAME |
6878 FILE_NOTIFY_CHANGE_ATTRIBUTES |
6879 FILE_NOTIFY_CHANGE_LAST_WRITE,
6880 false, print_notifies, NULL);
6881 if (req1 == NULL) {
6882 d_printf("Could not create notify request\n");
6883 return false;
6886 req2 = torture_createdels_send(talloc_tos(), ev, cli,
6887 base_fname, 10, torture_numops);
6888 if (req2 == NULL) {
6889 d_printf("Could not create createdels request\n");
6890 return false;
6892 TALLOC_FREE(base_fname);
6894 tevent_req_set_callback(req2, notify_bench_done,
6895 &num_finished);
6898 while (num_finished < num_unc_names) {
6899 int ret;
6900 ret = tevent_loop_once(ev);
6901 if (ret != 0) {
6902 d_printf("tevent_loop_once failed\n");
6903 return false;
6907 if (!tevent_req_poll(req2, ev)) {
6908 d_printf("tevent_req_poll failed\n");
6911 status = torture_createdels_recv(req2);
6912 d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
6914 return true;
6917 static bool run_mangle1(int dummy)
6919 struct cli_state *cli;
6920 const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
6921 uint16_t fnum;
6922 fstring alt_name;
6923 NTSTATUS status;
6924 time_t change_time, access_time, write_time;
6925 SMB_OFF_T size;
6926 uint16_t mode;
6928 printf("starting mangle1 test\n");
6929 if (!torture_open_connection(&cli, 0)) {
6930 return False;
6933 cli_sockopt(cli, sockops);
6935 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6936 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6937 0, 0, &fnum);
6938 if (!NT_STATUS_IS_OK(status)) {
6939 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
6940 return false;
6942 cli_close(cli, fnum);
6944 status = cli_qpathinfo_alt_name(cli, fname, alt_name);
6945 if (!NT_STATUS_IS_OK(status)) {
6946 d_printf("cli_qpathinfo_alt_name failed: %s\n",
6947 nt_errstr(status));
6948 return false;
6950 d_printf("alt_name: %s\n", alt_name);
6952 status = cli_open(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
6953 if (!NT_STATUS_IS_OK(status)) {
6954 d_printf("cli_open(%s) failed: %s\n", alt_name,
6955 nt_errstr(status));
6956 return false;
6958 cli_close(cli, fnum);
6960 status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
6961 &write_time, &size, &mode);
6962 if (!NT_STATUS_IS_OK(status)) {
6963 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
6964 nt_errstr(status));
6965 return false;
6968 return true;
6971 static size_t null_source(uint8_t *buf, size_t n, void *priv)
6973 size_t *to_pull = (size_t *)priv;
6974 size_t thistime = *to_pull;
6976 thistime = MIN(thistime, n);
6977 if (thistime == 0) {
6978 return 0;
6981 memset(buf, 0, thistime);
6982 *to_pull -= thistime;
6983 return thistime;
6986 static bool run_windows_write(int dummy)
6988 struct cli_state *cli1;
6989 uint16_t fnum;
6990 int i;
6991 bool ret = false;
6992 const char *fname = "\\writetest.txt";
6993 struct timeval start_time;
6994 double seconds;
6995 double kbytes;
6996 NTSTATUS status;
6998 printf("starting windows_write test\n");
6999 if (!torture_open_connection(&cli1, 0)) {
7000 return False;
7003 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
7004 if (!NT_STATUS_IS_OK(status)) {
7005 printf("open failed (%s)\n", nt_errstr(status));
7006 return False;
7009 cli_sockopt(cli1, sockops);
7011 start_time = timeval_current();
7013 for (i=0; i<torture_numops; i++) {
7014 uint8_t c = 0;
7015 off_t start = i * torture_blocksize;
7016 size_t to_pull = torture_blocksize - 1;
7018 status = cli_writeall(cli1, fnum, 0, &c,
7019 start + torture_blocksize - 1, 1, NULL);
7020 if (!NT_STATUS_IS_OK(status)) {
7021 printf("cli_write failed: %s\n", nt_errstr(status));
7022 goto fail;
7025 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
7026 null_source, &to_pull);
7027 if (!NT_STATUS_IS_OK(status)) {
7028 printf("cli_push returned: %s\n", nt_errstr(status));
7029 goto fail;
7033 seconds = timeval_elapsed(&start_time);
7034 kbytes = (double)torture_blocksize * torture_numops;
7035 kbytes /= 1024;
7037 printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
7038 (double)seconds, (int)(kbytes/seconds));
7040 ret = true;
7041 fail:
7042 cli_close(cli1, fnum);
7043 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7044 torture_close_connection(cli1);
7045 return ret;
7048 static bool run_cli_echo(int dummy)
7050 struct cli_state *cli;
7051 NTSTATUS status;
7053 printf("starting cli_echo test\n");
7054 if (!torture_open_connection(&cli, 0)) {
7055 return false;
7057 cli_sockopt(cli, sockops);
7059 status = cli_echo(cli, 5, data_blob_const("hello", 5));
7061 d_printf("cli_echo returned %s\n", nt_errstr(status));
7063 torture_close_connection(cli);
7064 return NT_STATUS_IS_OK(status);
7067 static bool run_uid_regression_test(int dummy)
7069 static struct cli_state *cli;
7070 int16_t old_vuid;
7071 int16_t old_cnum;
7072 bool correct = True;
7073 NTSTATUS status;
7075 printf("starting uid regression test\n");
7077 if (!torture_open_connection(&cli, 0)) {
7078 return False;
7081 cli_sockopt(cli, sockops);
7083 /* Ok - now save then logoff our current user. */
7084 old_vuid = cli->vuid;
7086 status = cli_ulogoff(cli);
7087 if (!NT_STATUS_IS_OK(status)) {
7088 d_printf("(%s) cli_ulogoff failed: %s\n",
7089 __location__, nt_errstr(status));
7090 correct = false;
7091 goto out;
7094 cli->vuid = old_vuid;
7096 /* Try an operation. */
7097 status = cli_mkdir(cli, "\\uid_reg_test");
7098 if (NT_STATUS_IS_OK(status)) {
7099 d_printf("(%s) cli_mkdir succeeded\n",
7100 __location__);
7101 correct = false;
7102 goto out;
7103 } else {
7104 /* Should be bad uid. */
7105 if (!check_error(__LINE__, cli, ERRSRV, ERRbaduid,
7106 NT_STATUS_USER_SESSION_DELETED)) {
7107 correct = false;
7108 goto out;
7112 old_cnum = cli->cnum;
7114 /* Now try a SMBtdis with the invald vuid set to zero. */
7115 cli->vuid = 0;
7117 /* This should succeed. */
7118 status = cli_tdis(cli);
7120 if (NT_STATUS_IS_OK(status)) {
7121 d_printf("First tdis with invalid vuid should succeed.\n");
7122 } else {
7123 d_printf("First tdis failed (%s)\n", nt_errstr(status));
7124 correct = false;
7125 goto out;
7128 cli->vuid = old_vuid;
7129 cli->cnum = old_cnum;
7131 /* This should fail. */
7132 status = cli_tdis(cli);
7133 if (NT_STATUS_IS_OK(status)) {
7134 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
7135 correct = false;
7136 goto out;
7137 } else {
7138 /* Should be bad tid. */
7139 if (!check_error(__LINE__, cli, ERRSRV, ERRinvnid,
7140 NT_STATUS_NETWORK_NAME_DELETED)) {
7141 correct = false;
7142 goto out;
7146 cli_rmdir(cli, "\\uid_reg_test");
7148 out:
7150 cli_shutdown(cli);
7151 return correct;
7155 static const char *illegal_chars = "*\\/?<>|\":";
7156 static char force_shortname_chars[] = " +,.[];=\177";
7158 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
7159 const char *mask, void *state)
7161 struct cli_state *pcli = (struct cli_state *)state;
7162 fstring fname;
7163 NTSTATUS status = NT_STATUS_OK;
7165 slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
7167 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
7168 return NT_STATUS_OK;
7170 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
7171 status = cli_rmdir(pcli, fname);
7172 if (!NT_STATUS_IS_OK(status)) {
7173 printf("del_fn: failed to rmdir %s\n,", fname );
7175 } else {
7176 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7177 if (!NT_STATUS_IS_OK(status)) {
7178 printf("del_fn: failed to unlink %s\n,", fname );
7181 return status;
7184 struct sn_state {
7185 int matched;
7186 int i;
7187 bool val;
7190 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
7191 const char *name, void *state)
7193 struct sn_state *s = (struct sn_state *)state;
7194 int i = s->i;
7196 #if 0
7197 printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
7198 i, finfo->name, finfo->short_name);
7199 #endif
7201 if (strchr(force_shortname_chars, i)) {
7202 if (!finfo->short_name) {
7203 /* Shortname not created when it should be. */
7204 d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
7205 __location__, finfo->name, i);
7206 s->val = true;
7208 } else if (finfo->short_name){
7209 /* Shortname created when it should not be. */
7210 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
7211 __location__, finfo->short_name, finfo->name);
7212 s->val = true;
7214 s->matched += 1;
7215 return NT_STATUS_OK;
7218 static bool run_shortname_test(int dummy)
7220 static struct cli_state *cli;
7221 bool correct = True;
7222 int i;
7223 struct sn_state s;
7224 char fname[20];
7225 NTSTATUS status;
7227 printf("starting shortname test\n");
7229 if (!torture_open_connection(&cli, 0)) {
7230 return False;
7233 cli_sockopt(cli, sockops);
7235 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7236 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7237 cli_rmdir(cli, "\\shortname");
7239 status = cli_mkdir(cli, "\\shortname");
7240 if (!NT_STATUS_IS_OK(status)) {
7241 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
7242 __location__, nt_errstr(status));
7243 correct = false;
7244 goto out;
7247 strlcpy(fname, "\\shortname\\", sizeof(fname));
7248 strlcat(fname, "test .txt", sizeof(fname));
7250 s.val = false;
7252 for (i = 32; i < 128; i++) {
7253 uint16_t fnum = (uint16_t)-1;
7255 s.i = i;
7257 if (strchr(illegal_chars, i)) {
7258 continue;
7260 fname[15] = i;
7262 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
7263 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum);
7264 if (!NT_STATUS_IS_OK(status)) {
7265 d_printf("(%s) cli_nt_create of %s failed: %s\n",
7266 __location__, fname, nt_errstr(status));
7267 correct = false;
7268 goto out;
7270 cli_close(cli, fnum);
7272 s.matched = 0;
7273 status = cli_list(cli, "\\shortname\\test*.*", 0,
7274 shortname_list_fn, &s);
7275 if (s.matched != 1) {
7276 d_printf("(%s) failed to list %s: %s\n",
7277 __location__, fname, nt_errstr(status));
7278 correct = false;
7279 goto out;
7282 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7283 if (!NT_STATUS_IS_OK(status)) {
7284 d_printf("(%s) failed to delete %s: %s\n",
7285 __location__, fname, nt_errstr(status));
7286 correct = false;
7287 goto out;
7290 if (s.val) {
7291 correct = false;
7292 goto out;
7296 out:
7298 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7299 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7300 cli_rmdir(cli, "\\shortname");
7301 torture_close_connection(cli);
7302 return correct;
7305 static void pagedsearch_cb(struct tevent_req *req)
7307 int rc;
7308 struct tldap_message *msg;
7309 char *dn;
7311 rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
7312 if (rc != TLDAP_SUCCESS) {
7313 d_printf("tldap_search_paged_recv failed: %s\n",
7314 tldap_err2string(rc));
7315 return;
7317 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
7318 TALLOC_FREE(msg);
7319 return;
7321 if (!tldap_entry_dn(msg, &dn)) {
7322 d_printf("tldap_entry_dn failed\n");
7323 return;
7325 d_printf("%s\n", dn);
7326 TALLOC_FREE(msg);
7329 static bool run_tldap(int dummy)
7331 struct tldap_context *ld;
7332 int fd, rc;
7333 NTSTATUS status;
7334 struct sockaddr_storage addr;
7335 struct tevent_context *ev;
7336 struct tevent_req *req;
7337 char *basedn;
7338 const char *filter;
7340 if (!resolve_name(host, &addr, 0, false)) {
7341 d_printf("could not find host %s\n", host);
7342 return false;
7344 status = open_socket_out(&addr, 389, 9999, &fd);
7345 if (!NT_STATUS_IS_OK(status)) {
7346 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
7347 return false;
7350 ld = tldap_context_create(talloc_tos(), fd);
7351 if (ld == NULL) {
7352 close(fd);
7353 d_printf("tldap_context_create failed\n");
7354 return false;
7357 rc = tldap_fetch_rootdse(ld);
7358 if (rc != TLDAP_SUCCESS) {
7359 d_printf("tldap_fetch_rootdse failed: %s\n",
7360 tldap_errstr(talloc_tos(), ld, rc));
7361 return false;
7364 basedn = tldap_talloc_single_attribute(
7365 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
7366 if (basedn == NULL) {
7367 d_printf("no defaultNamingContext\n");
7368 return false;
7370 d_printf("defaultNamingContext: %s\n", basedn);
7372 ev = tevent_context_init(talloc_tos());
7373 if (ev == NULL) {
7374 d_printf("tevent_context_init failed\n");
7375 return false;
7378 req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
7379 TLDAP_SCOPE_SUB, "(objectclass=*)",
7380 NULL, 0, 0,
7381 NULL, 0, NULL, 0, 0, 0, 0, 5);
7382 if (req == NULL) {
7383 d_printf("tldap_search_paged_send failed\n");
7384 return false;
7386 tevent_req_set_callback(req, pagedsearch_cb, NULL);
7388 tevent_req_poll(req, ev);
7390 TALLOC_FREE(req);
7392 /* test search filters against rootDSE */
7393 filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
7394 "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
7396 rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
7397 NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
7398 talloc_tos(), NULL, NULL);
7399 if (rc != TLDAP_SUCCESS) {
7400 d_printf("tldap_search with complex filter failed: %s\n",
7401 tldap_errstr(talloc_tos(), ld, rc));
7402 return false;
7405 TALLOC_FREE(ld);
7406 return true;
7409 /* Torture test to ensure no regression of :
7410 https://bugzilla.samba.org/show_bug.cgi?id=7084
7413 static bool run_dir_createtime(int dummy)
7415 struct cli_state *cli;
7416 const char *dname = "\\testdir";
7417 const char *fname = "\\testdir\\testfile";
7418 NTSTATUS status;
7419 struct timespec create_time;
7420 struct timespec create_time1;
7421 uint16_t fnum;
7422 bool ret = false;
7424 if (!torture_open_connection(&cli, 0)) {
7425 return false;
7428 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7429 cli_rmdir(cli, dname);
7431 status = cli_mkdir(cli, dname);
7432 if (!NT_STATUS_IS_OK(status)) {
7433 printf("mkdir failed: %s\n", nt_errstr(status));
7434 goto out;
7437 status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
7438 NULL, NULL, NULL);
7439 if (!NT_STATUS_IS_OK(status)) {
7440 printf("cli_qpathinfo2 returned %s\n",
7441 nt_errstr(status));
7442 goto out;
7445 /* Sleep 3 seconds, then create a file. */
7446 sleep(3);
7448 status = cli_open(cli, fname, O_RDWR | O_CREAT | O_EXCL,
7449 DENY_NONE, &fnum);
7450 if (!NT_STATUS_IS_OK(status)) {
7451 printf("cli_open failed: %s\n", nt_errstr(status));
7452 goto out;
7455 status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
7456 NULL, NULL, NULL);
7457 if (!NT_STATUS_IS_OK(status)) {
7458 printf("cli_qpathinfo2 (2) returned %s\n",
7459 nt_errstr(status));
7460 goto out;
7463 if (timespec_compare(&create_time1, &create_time)) {
7464 printf("run_dir_createtime: create time was updated (error)\n");
7465 } else {
7466 printf("run_dir_createtime: create time was not updated (correct)\n");
7467 ret = true;
7470 out:
7472 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7473 cli_rmdir(cli, dname);
7474 if (!torture_close_connection(cli)) {
7475 ret = false;
7477 return ret;
7481 static bool run_streamerror(int dummy)
7483 struct cli_state *cli;
7484 const char *dname = "\\testdir";
7485 const char *streamname =
7486 "testdir:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
7487 NTSTATUS status;
7488 time_t change_time, access_time, write_time;
7489 SMB_OFF_T size;
7490 uint16_t mode, fnum;
7491 bool ret = true;
7493 if (!torture_open_connection(&cli, 0)) {
7494 return false;
7497 cli_unlink(cli, "\\testdir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7498 cli_rmdir(cli, dname);
7500 status = cli_mkdir(cli, dname);
7501 if (!NT_STATUS_IS_OK(status)) {
7502 printf("mkdir failed: %s\n", nt_errstr(status));
7503 return false;
7506 cli_qpathinfo1(cli, streamname, &change_time, &access_time, &write_time,
7507 &size, &mode);
7508 status = cli_nt_error(cli);
7510 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7511 printf("pathinfo returned %s, expected "
7512 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
7513 nt_errstr(status));
7514 ret = false;
7517 status = cli_ntcreate(cli, streamname, 0x16,
7518 FILE_READ_DATA|FILE_READ_EA|
7519 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
7520 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7521 FILE_OPEN, 0, 0, &fnum);
7523 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7524 printf("ntcreate returned %s, expected "
7525 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
7526 nt_errstr(status));
7527 ret = false;
7531 cli_rmdir(cli, dname);
7532 return ret;
7535 static bool run_local_substitute(int dummy)
7537 bool ok = true;
7539 ok &= subst_test("%U", "bla", "", -1, -1, "bla");
7540 ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
7541 ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
7542 ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
7543 ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
7544 ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
7545 ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
7546 ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
7548 /* Different captialization rules in sub_basic... */
7550 ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
7551 "blaDOM") == 0);
7553 return ok;
7556 static bool run_local_base64(int dummy)
7558 int i;
7559 bool ret = true;
7561 for (i=1; i<2000; i++) {
7562 DATA_BLOB blob1, blob2;
7563 char *b64;
7565 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
7566 blob1.length = i;
7567 generate_random_buffer(blob1.data, blob1.length);
7569 b64 = base64_encode_data_blob(talloc_tos(), blob1);
7570 if (b64 == NULL) {
7571 d_fprintf(stderr, "base64_encode_data_blob failed "
7572 "for %d bytes\n", i);
7573 ret = false;
7575 blob2 = base64_decode_data_blob(b64);
7576 TALLOC_FREE(b64);
7578 if (data_blob_cmp(&blob1, &blob2)) {
7579 d_fprintf(stderr, "data_blob_cmp failed for %d "
7580 "bytes\n", i);
7581 ret = false;
7583 TALLOC_FREE(blob1.data);
7584 data_blob_free(&blob2);
7586 return ret;
7589 static bool run_local_gencache(int dummy)
7591 char *val;
7592 time_t tm;
7593 DATA_BLOB blob;
7595 if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
7596 d_printf("%s: gencache_set() failed\n", __location__);
7597 return False;
7600 if (!gencache_get("foo", NULL, NULL)) {
7601 d_printf("%s: gencache_get() failed\n", __location__);
7602 return False;
7605 if (!gencache_get("foo", &val, &tm)) {
7606 d_printf("%s: gencache_get() failed\n", __location__);
7607 return False;
7610 if (strcmp(val, "bar") != 0) {
7611 d_printf("%s: gencache_get() returned %s, expected %s\n",
7612 __location__, val, "bar");
7613 SAFE_FREE(val);
7614 return False;
7617 SAFE_FREE(val);
7619 if (!gencache_del("foo")) {
7620 d_printf("%s: gencache_del() failed\n", __location__);
7621 return False;
7623 if (gencache_del("foo")) {
7624 d_printf("%s: second gencache_del() succeeded\n",
7625 __location__);
7626 return False;
7629 if (gencache_get("foo", &val, &tm)) {
7630 d_printf("%s: gencache_get() on deleted entry "
7631 "succeeded\n", __location__);
7632 return False;
7635 blob = data_blob_string_const_null("bar");
7636 tm = time(NULL) + 60;
7638 if (!gencache_set_data_blob("foo", &blob, tm)) {
7639 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
7640 return False;
7643 if (!gencache_get_data_blob("foo", &blob, NULL, NULL)) {
7644 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
7645 return False;
7648 if (strcmp((const char *)blob.data, "bar") != 0) {
7649 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
7650 __location__, (const char *)blob.data, "bar");
7651 data_blob_free(&blob);
7652 return False;
7655 data_blob_free(&blob);
7657 if (!gencache_del("foo")) {
7658 d_printf("%s: gencache_del() failed\n", __location__);
7659 return False;
7661 if (gencache_del("foo")) {
7662 d_printf("%s: second gencache_del() succeeded\n",
7663 __location__);
7664 return False;
7667 if (gencache_get_data_blob("foo", &blob, NULL, NULL)) {
7668 d_printf("%s: gencache_get_data_blob() on deleted entry "
7669 "succeeded\n", __location__);
7670 return False;
7673 return True;
7676 static bool rbt_testval(struct db_context *db, const char *key,
7677 const char *value)
7679 struct db_record *rec;
7680 TDB_DATA data = string_tdb_data(value);
7681 bool ret = false;
7682 NTSTATUS status;
7684 rec = db->fetch_locked(db, db, string_tdb_data(key));
7685 if (rec == NULL) {
7686 d_fprintf(stderr, "fetch_locked failed\n");
7687 goto done;
7689 status = rec->store(rec, data, 0);
7690 if (!NT_STATUS_IS_OK(status)) {
7691 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
7692 goto done;
7694 TALLOC_FREE(rec);
7696 rec = db->fetch_locked(db, db, string_tdb_data(key));
7697 if (rec == NULL) {
7698 d_fprintf(stderr, "second fetch_locked failed\n");
7699 goto done;
7701 if ((rec->value.dsize != data.dsize)
7702 || (memcmp(rec->value.dptr, data.dptr, data.dsize) != 0)) {
7703 d_fprintf(stderr, "Got wrong data back\n");
7704 goto done;
7707 ret = true;
7708 done:
7709 TALLOC_FREE(rec);
7710 return ret;
7713 static bool run_local_rbtree(int dummy)
7715 struct db_context *db;
7716 bool ret = false;
7717 int i;
7719 db = db_open_rbt(NULL);
7721 if (db == NULL) {
7722 d_fprintf(stderr, "db_open_rbt failed\n");
7723 return false;
7726 for (i=0; i<1000; i++) {
7727 char *key, *value;
7729 if (asprintf(&key, "key%ld", random()) == -1) {
7730 goto done;
7732 if (asprintf(&value, "value%ld", random()) == -1) {
7733 SAFE_FREE(key);
7734 goto done;
7737 if (!rbt_testval(db, key, value)) {
7738 SAFE_FREE(key);
7739 SAFE_FREE(value);
7740 goto done;
7743 SAFE_FREE(value);
7744 if (asprintf(&value, "value%ld", random()) == -1) {
7745 SAFE_FREE(key);
7746 goto done;
7749 if (!rbt_testval(db, key, value)) {
7750 SAFE_FREE(key);
7751 SAFE_FREE(value);
7752 goto done;
7755 SAFE_FREE(key);
7756 SAFE_FREE(value);
7759 ret = true;
7761 done:
7762 TALLOC_FREE(db);
7763 return ret;
7768 local test for character set functions
7770 This is a very simple test for the functionality in convert_string_error()
7772 static bool run_local_convert_string(int dummy)
7774 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
7775 const char *test_strings[2] = { "March", "M\303\244rz" };
7776 char dst[7];
7777 int i;
7779 for (i=0; i<2; i++) {
7780 const char *str = test_strings[i];
7781 int len = strlen(str);
7782 size_t converted_size;
7783 bool ret;
7785 memset(dst, 'X', sizeof(dst));
7787 /* first try with real source length */
7788 ret = convert_string_error(CH_UNIX, CH_UTF8,
7789 str, len,
7790 dst, sizeof(dst),
7791 &converted_size);
7792 if (ret != true) {
7793 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
7794 goto failed;
7797 if (converted_size != len) {
7798 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
7799 str, len, (int)converted_size);
7800 goto failed;
7803 if (strncmp(str, dst, converted_size) != 0) {
7804 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
7805 goto failed;
7808 if (strlen(str) != converted_size) {
7809 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
7810 (int)strlen(str), (int)converted_size);
7811 goto failed;
7814 if (dst[converted_size] != 'X') {
7815 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
7816 goto failed;
7819 /* now with srclen==-1, this causes the nul to be
7820 * converted too */
7821 ret = convert_string_error(CH_UNIX, CH_UTF8,
7822 str, -1,
7823 dst, sizeof(dst),
7824 &converted_size);
7825 if (ret != true) {
7826 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
7827 goto failed;
7830 if (converted_size != len+1) {
7831 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
7832 str, len, (int)converted_size);
7833 goto failed;
7836 if (strncmp(str, dst, converted_size) != 0) {
7837 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
7838 goto failed;
7841 if (len+1 != converted_size) {
7842 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
7843 len+1, (int)converted_size);
7844 goto failed;
7847 if (dst[converted_size] != 'X') {
7848 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
7849 goto failed;
7855 TALLOC_FREE(tmp_ctx);
7856 return true;
7857 failed:
7858 TALLOC_FREE(tmp_ctx);
7859 return false;
7863 struct talloc_dict_test {
7864 int content;
7867 static int talloc_dict_traverse_fn(DATA_BLOB key, void *data, void *priv)
7869 int *count = (int *)priv;
7870 *count += 1;
7871 return 0;
7874 static bool run_local_talloc_dict(int dummy)
7876 struct talloc_dict *dict;
7877 struct talloc_dict_test *t;
7878 int key, count;
7880 dict = talloc_dict_init(talloc_tos());
7881 if (dict == NULL) {
7882 return false;
7885 t = talloc(talloc_tos(), struct talloc_dict_test);
7886 if (t == NULL) {
7887 return false;
7890 key = 1;
7891 t->content = 1;
7892 if (!talloc_dict_set(dict, data_blob_const(&key, sizeof(key)), t)) {
7893 return false;
7896 count = 0;
7897 if (talloc_dict_traverse(dict, talloc_dict_traverse_fn, &count) != 0) {
7898 return false;
7901 if (count != 1) {
7902 return false;
7905 TALLOC_FREE(dict);
7907 return true;
7910 static bool run_local_string_to_sid(int dummy) {
7911 struct dom_sid sid;
7913 if (string_to_sid(&sid, "S--1-5-32-545")) {
7914 printf("allowing S--1-5-32-545\n");
7915 return false;
7917 if (string_to_sid(&sid, "S-1-5-32-+545")) {
7918 printf("allowing S-1-5-32-+545\n");
7919 return false;
7921 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")) {
7922 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
7923 return false;
7925 if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
7926 printf("allowing S-1-5-32-545-abc\n");
7927 return false;
7929 if (!string_to_sid(&sid, "S-1-5-32-545")) {
7930 printf("could not parse S-1-5-32-545\n");
7931 return false;
7933 if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
7934 printf("mis-parsed S-1-5-32-545 as %s\n",
7935 sid_string_tos(&sid));
7936 return false;
7938 return true;
7941 static bool run_local_binary_to_sid(int dummy) {
7942 struct dom_sid *sid = talloc(NULL, struct dom_sid);
7943 static const char good_binary_sid[] = {
7944 0x1, /* revision number */
7945 15, /* num auths */
7946 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
7947 0x1, 0x1, 0x1, 0x1, /* auth[0] */
7948 0x1, 0x1, 0x1, 0x1, /* auth[1] */
7949 0x1, 0x1, 0x1, 0x1, /* auth[2] */
7950 0x1, 0x1, 0x1, 0x1, /* auth[3] */
7951 0x1, 0x1, 0x1, 0x1, /* auth[4] */
7952 0x1, 0x1, 0x1, 0x1, /* auth[5] */
7953 0x1, 0x1, 0x1, 0x1, /* auth[6] */
7954 0x1, 0x1, 0x1, 0x1, /* auth[7] */
7955 0x1, 0x1, 0x1, 0x1, /* auth[8] */
7956 0x1, 0x1, 0x1, 0x1, /* auth[9] */
7957 0x1, 0x1, 0x1, 0x1, /* auth[10] */
7958 0x1, 0x1, 0x1, 0x1, /* auth[11] */
7959 0x1, 0x1, 0x1, 0x1, /* auth[12] */
7960 0x1, 0x1, 0x1, 0x1, /* auth[13] */
7961 0x1, 0x1, 0x1, 0x1, /* auth[14] */
7964 static const char long_binary_sid[] = {
7965 0x1, /* revision number */
7966 15, /* num auths */
7967 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
7968 0x1, 0x1, 0x1, 0x1, /* auth[0] */
7969 0x1, 0x1, 0x1, 0x1, /* auth[1] */
7970 0x1, 0x1, 0x1, 0x1, /* auth[2] */
7971 0x1, 0x1, 0x1, 0x1, /* auth[3] */
7972 0x1, 0x1, 0x1, 0x1, /* auth[4] */
7973 0x1, 0x1, 0x1, 0x1, /* auth[5] */
7974 0x1, 0x1, 0x1, 0x1, /* auth[6] */
7975 0x1, 0x1, 0x1, 0x1, /* auth[7] */
7976 0x1, 0x1, 0x1, 0x1, /* auth[8] */
7977 0x1, 0x1, 0x1, 0x1, /* auth[9] */
7978 0x1, 0x1, 0x1, 0x1, /* auth[10] */
7979 0x1, 0x1, 0x1, 0x1, /* auth[11] */
7980 0x1, 0x1, 0x1, 0x1, /* auth[12] */
7981 0x1, 0x1, 0x1, 0x1, /* auth[13] */
7982 0x1, 0x1, 0x1, 0x1, /* auth[14] */
7983 0x1, 0x1, 0x1, 0x1, /* auth[15] */
7984 0x1, 0x1, 0x1, 0x1, /* auth[16] */
7985 0x1, 0x1, 0x1, 0x1, /* auth[17] */
7988 static const char long_binary_sid2[] = {
7989 0x1, /* revision number */
7990 32, /* num auths */
7991 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
7992 0x1, 0x1, 0x1, 0x1, /* auth[0] */
7993 0x1, 0x1, 0x1, 0x1, /* auth[1] */
7994 0x1, 0x1, 0x1, 0x1, /* auth[2] */
7995 0x1, 0x1, 0x1, 0x1, /* auth[3] */
7996 0x1, 0x1, 0x1, 0x1, /* auth[4] */
7997 0x1, 0x1, 0x1, 0x1, /* auth[5] */
7998 0x1, 0x1, 0x1, 0x1, /* auth[6] */
7999 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8000 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8001 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8002 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8003 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8004 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8005 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8006 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8007 0x1, 0x1, 0x1, 0x1, /* auth[15] */
8008 0x1, 0x1, 0x1, 0x1, /* auth[16] */
8009 0x1, 0x1, 0x1, 0x1, /* auth[17] */
8010 0x1, 0x1, 0x1, 0x1, /* auth[18] */
8011 0x1, 0x1, 0x1, 0x1, /* auth[19] */
8012 0x1, 0x1, 0x1, 0x1, /* auth[20] */
8013 0x1, 0x1, 0x1, 0x1, /* auth[21] */
8014 0x1, 0x1, 0x1, 0x1, /* auth[22] */
8015 0x1, 0x1, 0x1, 0x1, /* auth[23] */
8016 0x1, 0x1, 0x1, 0x1, /* auth[24] */
8017 0x1, 0x1, 0x1, 0x1, /* auth[25] */
8018 0x1, 0x1, 0x1, 0x1, /* auth[26] */
8019 0x1, 0x1, 0x1, 0x1, /* auth[27] */
8020 0x1, 0x1, 0x1, 0x1, /* auth[28] */
8021 0x1, 0x1, 0x1, 0x1, /* auth[29] */
8022 0x1, 0x1, 0x1, 0x1, /* auth[30] */
8023 0x1, 0x1, 0x1, 0x1, /* auth[31] */
8026 if (!sid_parse(good_binary_sid, sizeof(good_binary_sid), sid)) {
8027 return false;
8029 if (sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid)) {
8030 return false;
8032 if (sid_parse(long_binary_sid, sizeof(long_binary_sid), sid)) {
8033 return false;
8035 return true;
8038 /* Split a path name into filename and stream name components. Canonicalise
8039 * such that an implicit $DATA token is always explicit.
8041 * The "specification" of this function can be found in the
8042 * run_local_stream_name() function in torture.c, I've tried those
8043 * combinations against a W2k3 server.
8046 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
8047 char **pbase, char **pstream)
8049 char *base = NULL;
8050 char *stream = NULL;
8051 char *sname; /* stream name */
8052 const char *stype; /* stream type */
8054 DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
8056 sname = strchr_m(fname, ':');
8058 if (lp_posix_pathnames() || (sname == NULL)) {
8059 if (pbase != NULL) {
8060 base = talloc_strdup(mem_ctx, fname);
8061 NT_STATUS_HAVE_NO_MEMORY(base);
8063 goto done;
8066 if (pbase != NULL) {
8067 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
8068 NT_STATUS_HAVE_NO_MEMORY(base);
8071 sname += 1;
8073 stype = strchr_m(sname, ':');
8075 if (stype == NULL) {
8076 sname = talloc_strdup(mem_ctx, sname);
8077 stype = "$DATA";
8079 else {
8080 if (strcasecmp_m(stype, ":$DATA") != 0) {
8082 * If there is an explicit stream type, so far we only
8083 * allow $DATA. Is there anything else allowed? -- vl
8085 DEBUG(10, ("[%s] is an invalid stream type\n", stype));
8086 TALLOC_FREE(base);
8087 return NT_STATUS_OBJECT_NAME_INVALID;
8089 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
8090 stype += 1;
8093 if (sname == NULL) {
8094 TALLOC_FREE(base);
8095 return NT_STATUS_NO_MEMORY;
8098 if (sname[0] == '\0') {
8100 * no stream name, so no stream
8102 goto done;
8105 if (pstream != NULL) {
8106 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
8107 if (stream == NULL) {
8108 TALLOC_FREE(sname);
8109 TALLOC_FREE(base);
8110 return NT_STATUS_NO_MEMORY;
8113 * upper-case the type field
8115 strupper_m(strchr_m(stream, ':')+1);
8118 done:
8119 if (pbase != NULL) {
8120 *pbase = base;
8122 if (pstream != NULL) {
8123 *pstream = stream;
8125 return NT_STATUS_OK;
8128 static bool test_stream_name(const char *fname, const char *expected_base,
8129 const char *expected_stream,
8130 NTSTATUS expected_status)
8132 NTSTATUS status;
8133 char *base = NULL;
8134 char *stream = NULL;
8136 status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
8137 if (!NT_STATUS_EQUAL(status, expected_status)) {
8138 goto error;
8141 if (!NT_STATUS_IS_OK(status)) {
8142 return true;
8145 if (base == NULL) goto error;
8147 if (strcmp(expected_base, base) != 0) goto error;
8149 if ((expected_stream != NULL) && (stream == NULL)) goto error;
8150 if ((expected_stream == NULL) && (stream != NULL)) goto error;
8152 if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
8153 goto error;
8155 TALLOC_FREE(base);
8156 TALLOC_FREE(stream);
8157 return true;
8159 error:
8160 d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
8161 fname, expected_base ? expected_base : "<NULL>",
8162 expected_stream ? expected_stream : "<NULL>",
8163 nt_errstr(expected_status));
8164 d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
8165 base ? base : "<NULL>", stream ? stream : "<NULL>",
8166 nt_errstr(status));
8167 TALLOC_FREE(base);
8168 TALLOC_FREE(stream);
8169 return false;
8172 static bool run_local_stream_name(int dummy)
8174 bool ret = true;
8176 ret &= test_stream_name(
8177 "bla", "bla", NULL, NT_STATUS_OK);
8178 ret &= test_stream_name(
8179 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
8180 ret &= test_stream_name(
8181 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8182 ret &= test_stream_name(
8183 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
8184 ret &= test_stream_name(
8185 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8186 ret &= test_stream_name(
8187 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
8188 ret &= test_stream_name(
8189 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
8190 ret &= test_stream_name(
8191 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
8193 return ret;
8196 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
8198 if (a.length != b.length) {
8199 printf("a.length=%d != b.length=%d\n",
8200 (int)a.length, (int)b.length);
8201 return false;
8203 if (memcmp(a.data, b.data, a.length) != 0) {
8204 printf("a.data and b.data differ\n");
8205 return false;
8207 return true;
8210 static bool run_local_memcache(int dummy)
8212 struct memcache *cache;
8213 DATA_BLOB k1, k2;
8214 DATA_BLOB d1, d2, d3;
8215 DATA_BLOB v1, v2, v3;
8217 TALLOC_CTX *mem_ctx;
8218 char *str1, *str2;
8219 size_t size1, size2;
8220 bool ret = false;
8222 cache = memcache_init(NULL, 100);
8224 if (cache == NULL) {
8225 printf("memcache_init failed\n");
8226 return false;
8229 d1 = data_blob_const("d1", 2);
8230 d2 = data_blob_const("d2", 2);
8231 d3 = data_blob_const("d3", 2);
8233 k1 = data_blob_const("d1", 2);
8234 k2 = data_blob_const("d2", 2);
8236 memcache_add(cache, STAT_CACHE, k1, d1);
8237 memcache_add(cache, GETWD_CACHE, k2, d2);
8239 if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
8240 printf("could not find k1\n");
8241 return false;
8243 if (!data_blob_equal(d1, v1)) {
8244 return false;
8247 if (!memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8248 printf("could not find k2\n");
8249 return false;
8251 if (!data_blob_equal(d2, v2)) {
8252 return false;
8255 memcache_add(cache, STAT_CACHE, k1, d3);
8257 if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
8258 printf("could not find replaced k1\n");
8259 return false;
8261 if (!data_blob_equal(d3, v3)) {
8262 return false;
8265 memcache_add(cache, GETWD_CACHE, k1, d1);
8267 if (memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8268 printf("Did find k2, should have been purged\n");
8269 return false;
8272 TALLOC_FREE(cache);
8274 cache = memcache_init(NULL, 0);
8276 mem_ctx = talloc_init("foo");
8278 str1 = talloc_strdup(mem_ctx, "string1");
8279 str2 = talloc_strdup(mem_ctx, "string2");
8281 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8282 data_blob_string_const("torture"), &str1);
8283 size1 = talloc_total_size(cache);
8285 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8286 data_blob_string_const("torture"), &str2);
8287 size2 = talloc_total_size(cache);
8289 printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
8291 if (size2 > size1) {
8292 printf("memcache leaks memory!\n");
8293 goto fail;
8296 ret = true;
8297 fail:
8298 TALLOC_FREE(cache);
8299 return ret;
8302 static void wbclient_done(struct tevent_req *req)
8304 wbcErr wbc_err;
8305 struct winbindd_response *wb_resp;
8306 int *i = (int *)tevent_req_callback_data_void(req);
8308 wbc_err = wb_trans_recv(req, req, &wb_resp);
8309 TALLOC_FREE(req);
8310 *i += 1;
8311 d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
8314 static bool run_local_wbclient(int dummy)
8316 struct event_context *ev;
8317 struct wb_context **wb_ctx;
8318 struct winbindd_request wb_req;
8319 bool result = false;
8320 int i, j;
8322 BlockSignals(True, SIGPIPE);
8324 ev = tevent_context_init_byname(talloc_tos(), "epoll");
8325 if (ev == NULL) {
8326 goto fail;
8329 wb_ctx = talloc_array(ev, struct wb_context *, nprocs);
8330 if (wb_ctx == NULL) {
8331 goto fail;
8334 ZERO_STRUCT(wb_req);
8335 wb_req.cmd = WINBINDD_PING;
8337 d_printf("nprocs=%d, numops=%d\n", (int)nprocs, (int)torture_numops);
8339 for (i=0; i<nprocs; i++) {
8340 wb_ctx[i] = wb_context_init(ev, NULL);
8341 if (wb_ctx[i] == NULL) {
8342 goto fail;
8344 for (j=0; j<torture_numops; j++) {
8345 struct tevent_req *req;
8346 req = wb_trans_send(ev, ev, wb_ctx[i],
8347 (j % 2) == 0, &wb_req);
8348 if (req == NULL) {
8349 goto fail;
8351 tevent_req_set_callback(req, wbclient_done, &i);
8355 i = 0;
8357 while (i < nprocs * torture_numops) {
8358 event_loop_once(ev);
8361 result = true;
8362 fail:
8363 TALLOC_FREE(ev);
8364 return result;
8367 static void getaddrinfo_finished(struct tevent_req *req)
8369 char *name = (char *)tevent_req_callback_data_void(req);
8370 struct addrinfo *ainfo;
8371 int res;
8373 res = getaddrinfo_recv(req, &ainfo);
8374 if (res != 0) {
8375 d_printf("gai(%s) returned %s\n", name, gai_strerror(res));
8376 return;
8378 d_printf("gai(%s) succeeded\n", name);
8379 freeaddrinfo(ainfo);
8382 static bool run_getaddrinfo_send(int dummy)
8384 TALLOC_CTX *frame = talloc_stackframe();
8385 struct fncall_context *ctx;
8386 struct tevent_context *ev;
8387 bool result = false;
8388 const char *names[4] = { "www.samba.org", "notfound.samba.org",
8389 "www.slashdot.org", "heise.de" };
8390 struct tevent_req *reqs[4];
8391 int i;
8393 ev = event_context_init(frame);
8394 if (ev == NULL) {
8395 goto fail;
8398 ctx = fncall_context_init(frame, 4);
8400 for (i=0; i<ARRAY_SIZE(names); i++) {
8401 reqs[i] = getaddrinfo_send(frame, ev, ctx, names[i], NULL,
8402 NULL);
8403 if (reqs[i] == NULL) {
8404 goto fail;
8406 tevent_req_set_callback(reqs[i], getaddrinfo_finished,
8407 discard_const_p(void, names[i]));
8410 for (i=0; i<ARRAY_SIZE(reqs); i++) {
8411 tevent_loop_once(ev);
8414 result = true;
8415 fail:
8416 TALLOC_FREE(frame);
8417 return result;
8420 static bool dbtrans_inc(struct db_context *db)
8422 struct db_record *rec;
8423 uint32_t *val;
8424 bool ret = false;
8425 NTSTATUS status;
8427 rec = db->fetch_locked(db, db, string_term_tdb_data("transtest"));
8428 if (rec == NULL) {
8429 printf(__location__ "fetch_lock failed\n");
8430 return false;
8433 if (rec->value.dsize != sizeof(uint32_t)) {
8434 printf(__location__ "value.dsize = %d\n",
8435 (int)rec->value.dsize);
8436 goto fail;
8439 val = (uint32_t *)rec->value.dptr;
8440 *val += 1;
8442 status = rec->store(rec, make_tdb_data((uint8_t *)val,
8443 sizeof(uint32_t)),
8445 if (!NT_STATUS_IS_OK(status)) {
8446 printf(__location__ "store failed: %s\n",
8447 nt_errstr(status));
8448 goto fail;
8451 ret = true;
8452 fail:
8453 TALLOC_FREE(rec);
8454 return ret;
8457 static bool run_local_dbtrans(int dummy)
8459 struct db_context *db;
8460 struct db_record *rec;
8461 NTSTATUS status;
8462 uint32_t initial;
8463 int res;
8465 db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
8466 O_RDWR|O_CREAT, 0600);
8467 if (db == NULL) {
8468 printf("Could not open transtest.db\n");
8469 return false;
8472 res = db->transaction_start(db);
8473 if (res != 0) {
8474 printf(__location__ "transaction_start failed\n");
8475 return false;
8478 rec = db->fetch_locked(db, db, string_term_tdb_data("transtest"));
8479 if (rec == NULL) {
8480 printf(__location__ "fetch_lock failed\n");
8481 return false;
8484 if (rec->value.dptr == NULL) {
8485 initial = 0;
8486 status = rec->store(
8487 rec, make_tdb_data((uint8_t *)&initial,
8488 sizeof(initial)),
8490 if (!NT_STATUS_IS_OK(status)) {
8491 printf(__location__ "store returned %s\n",
8492 nt_errstr(status));
8493 return false;
8497 TALLOC_FREE(rec);
8499 res = db->transaction_commit(db);
8500 if (res != 0) {
8501 printf(__location__ "transaction_commit failed\n");
8502 return false;
8505 while (true) {
8506 uint32_t val, val2;
8507 int i;
8509 res = db->transaction_start(db);
8510 if (res != 0) {
8511 printf(__location__ "transaction_start failed\n");
8512 break;
8515 if (!dbwrap_fetch_uint32(db, "transtest", &val)) {
8516 printf(__location__ "dbwrap_fetch_uint32 failed\n");
8517 break;
8520 for (i=0; i<10; i++) {
8521 if (!dbtrans_inc(db)) {
8522 return false;
8526 if (!dbwrap_fetch_uint32(db, "transtest", &val2)) {
8527 printf(__location__ "dbwrap_fetch_uint32 failed\n");
8528 break;
8531 if (val2 != val + 10) {
8532 printf(__location__ "val=%d, val2=%d\n",
8533 (int)val, (int)val2);
8534 break;
8537 printf("val2=%d\r", val2);
8539 res = db->transaction_commit(db);
8540 if (res != 0) {
8541 printf(__location__ "transaction_commit failed\n");
8542 break;
8546 TALLOC_FREE(db);
8547 return true;
8551 * Just a dummy test to be run under a debugger. There's no real way
8552 * to inspect the tevent_select specific function from outside of
8553 * tevent_select.c.
8556 static bool run_local_tevent_select(int dummy)
8558 struct tevent_context *ev;
8559 struct tevent_fd *fd1, *fd2;
8560 bool result = false;
8562 ev = tevent_context_init_byname(NULL, "select");
8563 if (ev == NULL) {
8564 d_fprintf(stderr, "tevent_context_init_byname failed\n");
8565 goto fail;
8568 fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
8569 if (fd1 == NULL) {
8570 d_fprintf(stderr, "tevent_add_fd failed\n");
8571 goto fail;
8573 fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
8574 if (fd2 == NULL) {
8575 d_fprintf(stderr, "tevent_add_fd failed\n");
8576 goto fail;
8578 TALLOC_FREE(fd2);
8580 fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
8581 if (fd2 == NULL) {
8582 d_fprintf(stderr, "tevent_add_fd failed\n");
8583 goto fail;
8586 result = true;
8587 fail:
8588 TALLOC_FREE(ev);
8589 return result;
8592 static double create_procs(bool (*fn)(int), bool *result)
8594 int i, status;
8595 volatile pid_t *child_status;
8596 volatile bool *child_status_out;
8597 int synccount;
8598 int tries = 8;
8599 struct timeval start;
8601 synccount = 0;
8603 child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*nprocs);
8604 if (!child_status) {
8605 printf("Failed to setup shared memory\n");
8606 return -1;
8609 child_status_out = (volatile bool *)shm_setup(sizeof(bool)*nprocs);
8610 if (!child_status_out) {
8611 printf("Failed to setup result status shared memory\n");
8612 return -1;
8615 for (i = 0; i < nprocs; i++) {
8616 child_status[i] = 0;
8617 child_status_out[i] = True;
8620 start = timeval_current();
8622 for (i=0;i<nprocs;i++) {
8623 procnum = i;
8624 if (fork() == 0) {
8625 pid_t mypid = getpid();
8626 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
8628 slprintf(myname,sizeof(myname),"CLIENT%d", i);
8630 while (1) {
8631 if (torture_open_connection(&current_cli, i)) break;
8632 if (tries-- == 0) {
8633 printf("pid %d failed to start\n", (int)getpid());
8634 _exit(1);
8636 smb_msleep(10);
8639 child_status[i] = getpid();
8641 while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
8643 child_status_out[i] = fn(i);
8644 _exit(0);
8648 do {
8649 synccount = 0;
8650 for (i=0;i<nprocs;i++) {
8651 if (child_status[i]) synccount++;
8653 if (synccount == nprocs) break;
8654 smb_msleep(10);
8655 } while (timeval_elapsed(&start) < 30);
8657 if (synccount != nprocs) {
8658 printf("FAILED TO START %d CLIENTS (started %d)\n", nprocs, synccount);
8659 *result = False;
8660 return timeval_elapsed(&start);
8663 /* start the client load */
8664 start = timeval_current();
8666 for (i=0;i<nprocs;i++) {
8667 child_status[i] = 0;
8670 printf("%d clients started\n", nprocs);
8672 for (i=0;i<nprocs;i++) {
8673 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
8676 printf("\n");
8678 for (i=0;i<nprocs;i++) {
8679 if (!child_status_out[i]) {
8680 *result = False;
8683 return timeval_elapsed(&start);
8686 #define FLAG_MULTIPROC 1
8688 static struct {
8689 const char *name;
8690 bool (*fn)(int);
8691 unsigned flags;
8692 } torture_ops[] = {
8693 {"FDPASS", run_fdpasstest, 0},
8694 {"LOCK1", run_locktest1, 0},
8695 {"LOCK2", run_locktest2, 0},
8696 {"LOCK3", run_locktest3, 0},
8697 {"LOCK4", run_locktest4, 0},
8698 {"LOCK5", run_locktest5, 0},
8699 {"LOCK6", run_locktest6, 0},
8700 {"LOCK7", run_locktest7, 0},
8701 {"LOCK8", run_locktest8, 0},
8702 {"LOCK9", run_locktest9, 0},
8703 {"UNLINK", run_unlinktest, 0},
8704 {"BROWSE", run_browsetest, 0},
8705 {"ATTR", run_attrtest, 0},
8706 {"TRANS2", run_trans2test, 0},
8707 {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
8708 {"TORTURE",run_torture, FLAG_MULTIPROC},
8709 {"RANDOMIPC", run_randomipc, 0},
8710 {"NEGNOWAIT", run_negprot_nowait, 0},
8711 {"NBENCH", run_nbench, 0},
8712 {"NBENCH2", run_nbench2, 0},
8713 {"OPLOCK1", run_oplock1, 0},
8714 {"OPLOCK2", run_oplock2, 0},
8715 {"OPLOCK4", run_oplock4, 0},
8716 {"DIR", run_dirtest, 0},
8717 {"DIR1", run_dirtest1, 0},
8718 {"DIR-CREATETIME", run_dir_createtime, 0},
8719 {"DENY1", torture_denytest1, 0},
8720 {"DENY2", torture_denytest2, 0},
8721 {"TCON", run_tcon_test, 0},
8722 {"TCONDEV", run_tcon_devtype_test, 0},
8723 {"RW1", run_readwritetest, 0},
8724 {"RW2", run_readwritemulti, FLAG_MULTIPROC},
8725 {"RW3", run_readwritelarge, 0},
8726 {"RW-SIGNING", run_readwritelarge_signtest, 0},
8727 {"OPEN", run_opentest, 0},
8728 {"POSIX", run_simple_posix_open_test, 0},
8729 {"POSIX-APPEND", run_posix_append, 0},
8730 {"CASE-INSENSITIVE-CREATE", run_case_insensitive_create, 0},
8731 {"ASYNC-ECHO", run_async_echo, 0},
8732 { "UID-REGRESSION-TEST", run_uid_regression_test, 0},
8733 { "SHORTNAME-TEST", run_shortname_test, 0},
8734 { "ADDRCHANGE", run_addrchange, 0},
8735 #if 1
8736 {"OPENATTR", run_openattrtest, 0},
8737 #endif
8738 {"XCOPY", run_xcopy, 0},
8739 {"RENAME", run_rename, 0},
8740 {"DELETE", run_deletetest, 0},
8741 {"DELETE-LN", run_deletetest_ln, 0},
8742 {"PROPERTIES", run_properties, 0},
8743 {"MANGLE", torture_mangle, 0},
8744 {"MANGLE1", run_mangle1, 0},
8745 {"W2K", run_w2ktest, 0},
8746 {"TRANS2SCAN", torture_trans2_scan, 0},
8747 {"NTTRANSSCAN", torture_nttrans_scan, 0},
8748 {"UTABLE", torture_utable, 0},
8749 {"CASETABLE", torture_casetable, 0},
8750 {"ERRMAPEXTRACT", run_error_map_extract, 0},
8751 {"PIPE_NUMBER", run_pipe_number, 0},
8752 {"TCON2", run_tcon2_test, 0},
8753 {"IOCTL", torture_ioctl_test, 0},
8754 {"CHKPATH", torture_chkpath_test, 0},
8755 {"FDSESS", run_fdsesstest, 0},
8756 { "EATEST", run_eatest, 0},
8757 { "SESSSETUP_BENCH", run_sesssetup_bench, 0},
8758 { "CHAIN1", run_chain1, 0},
8759 { "CHAIN2", run_chain2, 0},
8760 { "WINDOWS-WRITE", run_windows_write, 0},
8761 { "NTTRANS-CREATE", run_nttrans_create, 0},
8762 { "CLI_ECHO", run_cli_echo, 0},
8763 { "GETADDRINFO", run_getaddrinfo_send, 0},
8764 { "TLDAP", run_tldap },
8765 { "STREAMERROR", run_streamerror },
8766 { "NOTIFY-BENCH", run_notify_bench },
8767 { "BAD-NBT-SESSION", run_bad_nbt_session },
8768 { "SMB-ANY-CONNECT", run_smb_any_connect },
8769 { "NOTIFY-ONLINE", run_notify_online },
8770 { "SMB2-BASIC", run_smb2_basic },
8771 { "LOCAL-SUBSTITUTE", run_local_substitute, 0},
8772 { "LOCAL-GENCACHE", run_local_gencache, 0},
8773 { "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0},
8774 { "LOCAL-BASE64", run_local_base64, 0},
8775 { "LOCAL-RBTREE", run_local_rbtree, 0},
8776 { "LOCAL-MEMCACHE", run_local_memcache, 0},
8777 { "LOCAL-STREAM-NAME", run_local_stream_name, 0},
8778 { "LOCAL-WBCLIENT", run_local_wbclient, 0},
8779 { "LOCAL-string_to_sid", run_local_string_to_sid, 0},
8780 { "LOCAL-binary_to_sid", run_local_binary_to_sid, 0},
8781 { "LOCAL-DBTRANS", run_local_dbtrans, 0},
8782 { "LOCAL-TEVENT-SELECT", run_local_tevent_select, 0},
8783 { "LOCAL-CONVERT-STRING", run_local_convert_string, 0},
8784 {NULL, NULL, 0}};
8788 /****************************************************************************
8789 run a specified test or "ALL"
8790 ****************************************************************************/
8791 static bool run_test(const char *name)
8793 bool ret = True;
8794 bool result = True;
8795 bool found = False;
8796 int i;
8797 double t;
8798 if (strequal(name,"ALL")) {
8799 for (i=0;torture_ops[i].name;i++) {
8800 run_test(torture_ops[i].name);
8802 found = True;
8805 for (i=0;torture_ops[i].name;i++) {
8806 fstr_sprintf(randomfname, "\\XX%x",
8807 (unsigned)random());
8809 if (strequal(name, torture_ops[i].name)) {
8810 found = True;
8811 printf("Running %s\n", name);
8812 if (torture_ops[i].flags & FLAG_MULTIPROC) {
8813 t = create_procs(torture_ops[i].fn, &result);
8814 if (!result) {
8815 ret = False;
8816 printf("TEST %s FAILED!\n", name);
8818 } else {
8819 struct timeval start;
8820 start = timeval_current();
8821 if (!torture_ops[i].fn(0)) {
8822 ret = False;
8823 printf("TEST %s FAILED!\n", name);
8825 t = timeval_elapsed(&start);
8827 printf("%s took %g secs\n\n", name, t);
8831 if (!found) {
8832 printf("Did not find a test named %s\n", name);
8833 ret = False;
8836 return ret;
8840 static void usage(void)
8842 int i;
8844 printf("WARNING samba4 test suite is much more complete nowadays.\n");
8845 printf("Please use samba4 torture.\n\n");
8847 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
8849 printf("\t-d debuglevel\n");
8850 printf("\t-U user%%pass\n");
8851 printf("\t-k use kerberos\n");
8852 printf("\t-N numprocs\n");
8853 printf("\t-n my_netbios_name\n");
8854 printf("\t-W workgroup\n");
8855 printf("\t-o num_operations\n");
8856 printf("\t-O socket_options\n");
8857 printf("\t-m maximum protocol\n");
8858 printf("\t-L use oplocks\n");
8859 printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
8860 printf("\t-A showall\n");
8861 printf("\t-p port\n");
8862 printf("\t-s seed\n");
8863 printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
8864 printf("\t-f filename filename to test\n");
8865 printf("\n\n");
8867 printf("tests are:");
8868 for (i=0;torture_ops[i].name;i++) {
8869 printf(" %s", torture_ops[i].name);
8871 printf("\n");
8873 printf("default test is ALL\n");
8875 exit(1);
8878 /****************************************************************************
8879 main program
8880 ****************************************************************************/
8881 int main(int argc,char *argv[])
8883 int opt, i;
8884 char *p;
8885 int gotuser = 0;
8886 int gotpass = 0;
8887 bool correct = True;
8888 TALLOC_CTX *frame = talloc_stackframe();
8889 int seed = time(NULL);
8891 #ifdef HAVE_SETBUFFER
8892 setbuffer(stdout, NULL, 0);
8893 #endif
8895 setup_logging("smbtorture", DEBUG_STDOUT);
8897 load_case_tables();
8899 if (is_default_dyn_CONFIGFILE()) {
8900 if(getenv("SMB_CONF_PATH")) {
8901 set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
8904 lp_load(get_dyn_CONFIGFILE(),True,False,False,True);
8905 load_interfaces();
8907 if (argc < 2) {
8908 usage();
8911 for(p = argv[1]; *p; p++)
8912 if(*p == '\\')
8913 *p = '/';
8915 if (strncmp(argv[1], "//", 2)) {
8916 usage();
8919 fstrcpy(host, &argv[1][2]);
8920 p = strchr_m(&host[2],'/');
8921 if (!p) {
8922 usage();
8924 *p = 0;
8925 fstrcpy(share, p+1);
8927 fstrcpy(myname, get_myname(talloc_tos()));
8928 if (!*myname) {
8929 fprintf(stderr, "Failed to get my hostname.\n");
8930 return 1;
8933 if (*username == 0 && getenv("LOGNAME")) {
8934 fstrcpy(username,getenv("LOGNAME"));
8937 argc--;
8938 argv++;
8940 fstrcpy(workgroup, lp_workgroup());
8942 while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
8943 != EOF) {
8944 switch (opt) {
8945 case 'p':
8946 port_to_use = atoi(optarg);
8947 break;
8948 case 's':
8949 seed = atoi(optarg);
8950 break;
8951 case 'W':
8952 fstrcpy(workgroup,optarg);
8953 break;
8954 case 'm':
8955 max_protocol = interpret_protocol(optarg, max_protocol);
8956 break;
8957 case 'N':
8958 nprocs = atoi(optarg);
8959 break;
8960 case 'o':
8961 torture_numops = atoi(optarg);
8962 break;
8963 case 'd':
8964 lp_set_cmdline("log level", optarg);
8965 break;
8966 case 'O':
8967 sockops = optarg;
8968 break;
8969 case 'L':
8970 use_oplocks = True;
8971 break;
8972 case 'l':
8973 local_path = optarg;
8974 break;
8975 case 'A':
8976 torture_showall = True;
8977 break;
8978 case 'n':
8979 fstrcpy(myname, optarg);
8980 break;
8981 case 'c':
8982 client_txt = optarg;
8983 break;
8984 case 'e':
8985 do_encrypt = true;
8986 break;
8987 case 'k':
8988 #ifdef HAVE_KRB5
8989 use_kerberos = True;
8990 #else
8991 d_printf("No kerberos support compiled in\n");
8992 exit(1);
8993 #endif
8994 break;
8995 case 'U':
8996 gotuser = 1;
8997 fstrcpy(username,optarg);
8998 p = strchr_m(username,'%');
8999 if (p) {
9000 *p = 0;
9001 fstrcpy(password, p+1);
9002 gotpass = 1;
9004 break;
9005 case 'b':
9006 fstrcpy(multishare_conn_fname, optarg);
9007 use_multishare_conn = True;
9008 break;
9009 case 'B':
9010 torture_blocksize = atoi(optarg);
9011 break;
9012 case 'f':
9013 test_filename = SMB_STRDUP(optarg);
9014 break;
9015 default:
9016 printf("Unknown option %c (%d)\n", (char)opt, opt);
9017 usage();
9021 d_printf("using seed %d\n", seed);
9023 srandom(seed);
9025 if(use_kerberos && !gotuser) gotpass = True;
9027 while (!gotpass) {
9028 p = getpass("Password:");
9029 if (p) {
9030 fstrcpy(password, p);
9031 gotpass = 1;
9035 printf("host=%s share=%s user=%s myname=%s\n",
9036 host, share, username, myname);
9038 if (argc == optind) {
9039 correct = run_test("ALL");
9040 } else {
9041 for (i=optind;i<argc;i++) {
9042 if (!run_test(argv[i])) {
9043 correct = False;
9048 TALLOC_FREE(frame);
9050 if (correct) {
9051 return(0);
9052 } else {
9053 return(1);