s3:smbd: check the share level access mask in smbd_calculate_access_mask()
[Samba/gebeck_regimport.git] / source3 / torture / torture.c
blobd40d5aa26cd86617b1653d85fa10c4eca1a294d7
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;
1800 if (!cli_lock(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
1801 printf("lock1 %d failed (%s)\n",
1803 cli_errstr(cli1));
1804 return False;
1807 if (!cli_lock(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK)) {
1808 printf("lock2 %d failed (%s)\n",
1810 cli_errstr(cli1));
1811 return False;
1815 for (offset=i=0;i<torture_numops;i++) {
1816 NEXT_OFFSET;
1818 if (cli_lock(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK)) {
1819 printf("error: lock1 %d succeeded!\n", i);
1820 return False;
1823 if (cli_lock(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK)) {
1824 printf("error: lock2 %d succeeded!\n", i);
1825 return False;
1828 if (cli_lock(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
1829 printf("error: lock3 %d succeeded!\n", i);
1830 return False;
1833 if (cli_lock(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK)) {
1834 printf("error: lock4 %d succeeded!\n", i);
1835 return False;
1839 for (offset=i=0;i<torture_numops;i++) {
1840 NEXT_OFFSET;
1842 status = cli_unlock(cli1, fnum1, offset-1, 1);
1843 if (!NT_STATUS_IS_OK(status)) {
1844 printf("unlock1 %d failed (%s)\n",
1846 nt_errstr(status));
1847 return False;
1850 status = cli_unlock(cli2, fnum2, offset-2, 1);
1851 if (!NT_STATUS_IS_OK(status)) {
1852 printf("unlock2 %d failed (%s)\n",
1854 nt_errstr(status));
1855 return False;
1859 status = cli_close(cli1, fnum1);
1860 if (!NT_STATUS_IS_OK(status)) {
1861 printf("close1 failed (%s)\n", nt_errstr(status));
1862 return False;
1865 status = cli_close(cli2, fnum2);
1866 if (!NT_STATUS_IS_OK(status)) {
1867 printf("close2 failed (%s)\n", nt_errstr(status));
1868 return False;
1871 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1872 if (!NT_STATUS_IS_OK(status)) {
1873 printf("unlink failed (%s)\n", nt_errstr(status));
1874 return False;
1877 if (!torture_close_connection(cli1)) {
1878 correct = False;
1881 if (!torture_close_connection(cli2)) {
1882 correct = False;
1885 printf("finished locktest3\n");
1887 return correct;
1890 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1891 printf("** "); correct = False; \
1895 looks at overlapping locks
1897 static bool run_locktest4(int dummy)
1899 static struct cli_state *cli1, *cli2;
1900 const char *fname = "\\lockt4.lck";
1901 uint16_t fnum1, fnum2, f;
1902 bool ret;
1903 char buf[1000];
1904 bool correct = True;
1905 NTSTATUS status;
1907 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1908 return False;
1911 cli_sockopt(cli1, sockops);
1912 cli_sockopt(cli2, sockops);
1914 printf("starting locktest4\n");
1916 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1918 cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1919 cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1921 memset(buf, 0, sizeof(buf));
1923 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
1924 NULL);
1925 if (!NT_STATUS_IS_OK(status)) {
1926 printf("Failed to create file: %s\n", nt_errstr(status));
1927 correct = False;
1928 goto fail;
1931 ret = cli_lock(cli1, fnum1, 0, 4, 0, WRITE_LOCK) &&
1932 cli_lock(cli1, fnum1, 2, 4, 0, WRITE_LOCK);
1933 EXPECTED(ret, False);
1934 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1936 ret = cli_lock(cli1, fnum1, 10, 4, 0, READ_LOCK) &&
1937 cli_lock(cli1, fnum1, 12, 4, 0, READ_LOCK);
1938 EXPECTED(ret, True);
1939 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1941 ret = cli_lock(cli1, fnum1, 20, 4, 0, WRITE_LOCK) &&
1942 cli_lock(cli2, fnum2, 22, 4, 0, WRITE_LOCK);
1943 EXPECTED(ret, False);
1944 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1946 ret = cli_lock(cli1, fnum1, 30, 4, 0, READ_LOCK) &&
1947 cli_lock(cli2, fnum2, 32, 4, 0, READ_LOCK);
1948 EXPECTED(ret, True);
1949 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1951 ret = (cli_setpid(cli1, 1), cli_lock(cli1, fnum1, 40, 4, 0, WRITE_LOCK)) &&
1952 (cli_setpid(cli1, 2), cli_lock(cli1, fnum1, 42, 4, 0, WRITE_LOCK));
1953 EXPECTED(ret, False);
1954 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1956 ret = (cli_setpid(cli1, 1), cli_lock(cli1, fnum1, 50, 4, 0, READ_LOCK)) &&
1957 (cli_setpid(cli1, 2), cli_lock(cli1, fnum1, 52, 4, 0, READ_LOCK));
1958 EXPECTED(ret, True);
1959 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1961 ret = cli_lock(cli1, fnum1, 60, 4, 0, READ_LOCK) &&
1962 cli_lock(cli1, fnum1, 60, 4, 0, READ_LOCK);
1963 EXPECTED(ret, True);
1964 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1966 ret = cli_lock(cli1, fnum1, 70, 4, 0, WRITE_LOCK) &&
1967 cli_lock(cli1, fnum1, 70, 4, 0, WRITE_LOCK);
1968 EXPECTED(ret, False);
1969 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1971 ret = cli_lock(cli1, fnum1, 80, 4, 0, READ_LOCK) &&
1972 cli_lock(cli1, fnum1, 80, 4, 0, WRITE_LOCK);
1973 EXPECTED(ret, False);
1974 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
1976 ret = cli_lock(cli1, fnum1, 90, 4, 0, WRITE_LOCK) &&
1977 cli_lock(cli1, fnum1, 90, 4, 0, READ_LOCK);
1978 EXPECTED(ret, True);
1979 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1981 ret = (cli_setpid(cli1, 1), cli_lock(cli1, fnum1, 100, 4, 0, WRITE_LOCK)) &&
1982 (cli_setpid(cli1, 2), cli_lock(cli1, fnum1, 100, 4, 0, READ_LOCK));
1983 EXPECTED(ret, False);
1984 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1986 ret = cli_lock(cli1, fnum1, 110, 4, 0, READ_LOCK) &&
1987 cli_lock(cli1, fnum1, 112, 4, 0, READ_LOCK) &&
1988 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
1989 EXPECTED(ret, False);
1990 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
1993 ret = cli_lock(cli1, fnum1, 120, 4, 0, WRITE_LOCK) &&
1994 (cli_read(cli2, fnum2, buf, 120, 4) == 4);
1995 EXPECTED(ret, False);
1996 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
1998 ret = cli_lock(cli1, fnum1, 130, 4, 0, READ_LOCK);
1999 if (ret) {
2000 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2001 NULL);
2002 ret = NT_STATUS_IS_OK(status);
2004 EXPECTED(ret, False);
2005 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2008 ret = cli_lock(cli1, fnum1, 140, 4, 0, READ_LOCK) &&
2009 cli_lock(cli1, fnum1, 140, 4, 0, READ_LOCK) &&
2010 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2011 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2012 EXPECTED(ret, True);
2013 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2016 ret = cli_lock(cli1, fnum1, 150, 4, 0, WRITE_LOCK) &&
2017 cli_lock(cli1, fnum1, 150, 4, 0, READ_LOCK) &&
2018 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2019 (cli_read(cli2, fnum2, buf, 150, 4) == 4) &&
2020 !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2021 150, 4, NULL))) &&
2022 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2023 EXPECTED(ret, True);
2024 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2026 ret = cli_lock(cli1, fnum1, 160, 4, 0, READ_LOCK) &&
2027 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2028 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2029 160, 4, NULL)) &&
2030 (cli_read(cli2, fnum2, buf, 160, 4) == 4);
2031 EXPECTED(ret, True);
2032 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2034 ret = cli_lock(cli1, fnum1, 170, 4, 0, WRITE_LOCK) &&
2035 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2036 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2037 170, 4, NULL)) &&
2038 (cli_read(cli2, fnum2, buf, 170, 4) == 4);
2039 EXPECTED(ret, True);
2040 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2042 ret = cli_lock(cli1, fnum1, 190, 4, 0, WRITE_LOCK) &&
2043 cli_lock(cli1, fnum1, 190, 4, 0, READ_LOCK) &&
2044 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2045 !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2046 190, 4, NULL)) &&
2047 (cli_read(cli2, fnum2, buf, 190, 4) == 4);
2048 EXPECTED(ret, True);
2049 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2051 cli_close(cli1, fnum1);
2052 cli_close(cli2, fnum2);
2053 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2054 cli_open(cli1, fname, O_RDWR, DENY_NONE, &f);
2055 ret = cli_lock(cli1, fnum1, 0, 8, 0, READ_LOCK) &&
2056 cli_lock(cli1, f, 0, 1, 0, READ_LOCK) &&
2057 NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2058 NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2059 cli_lock(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2060 cli_close(cli1, f);
2061 cli_close(cli1, fnum1);
2062 EXPECTED(ret, True);
2063 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2065 fail:
2066 cli_close(cli1, fnum1);
2067 cli_close(cli2, fnum2);
2068 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2069 torture_close_connection(cli1);
2070 torture_close_connection(cli2);
2072 printf("finished locktest4\n");
2073 return correct;
2077 looks at lock upgrade/downgrade.
2079 static bool run_locktest5(int dummy)
2081 static struct cli_state *cli1, *cli2;
2082 const char *fname = "\\lockt5.lck";
2083 uint16_t fnum1, fnum2, fnum3;
2084 bool ret;
2085 char buf[1000];
2086 bool correct = True;
2087 NTSTATUS status;
2089 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2090 return False;
2093 cli_sockopt(cli1, sockops);
2094 cli_sockopt(cli2, sockops);
2096 printf("starting locktest5\n");
2098 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2100 cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2101 cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2102 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2104 memset(buf, 0, sizeof(buf));
2106 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2107 NULL);
2108 if (!NT_STATUS_IS_OK(status)) {
2109 printf("Failed to create file: %s\n", nt_errstr(status));
2110 correct = False;
2111 goto fail;
2114 /* Check for NT bug... */
2115 ret = cli_lock(cli1, fnum1, 0, 8, 0, READ_LOCK) &&
2116 cli_lock(cli1, fnum3, 0, 1, 0, READ_LOCK);
2117 cli_close(cli1, fnum1);
2118 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2119 ret = cli_lock(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2120 EXPECTED(ret, True);
2121 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2122 cli_close(cli1, fnum1);
2123 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2124 cli_unlock(cli1, fnum3, 0, 1);
2126 ret = cli_lock(cli1, fnum1, 0, 4, 0, WRITE_LOCK) &&
2127 cli_lock(cli1, fnum1, 1, 1, 0, READ_LOCK);
2128 EXPECTED(ret, True);
2129 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2131 ret = cli_lock(cli2, fnum2, 0, 4, 0, READ_LOCK);
2132 EXPECTED(ret, False);
2134 printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2136 /* Unlock the process 2 lock. */
2137 cli_unlock(cli2, fnum2, 0, 4);
2139 ret = cli_lock(cli1, fnum3, 0, 4, 0, READ_LOCK);
2140 EXPECTED(ret, False);
2142 printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
2144 /* Unlock the process 1 fnum3 lock. */
2145 cli_unlock(cli1, fnum3, 0, 4);
2147 /* Stack 2 more locks here. */
2148 ret = cli_lock(cli1, fnum1, 0, 4, 0, READ_LOCK) &&
2149 cli_lock(cli1, fnum1, 0, 4, 0, READ_LOCK);
2151 EXPECTED(ret, True);
2152 printf("the same process %s stack read locks\n", ret?"can":"cannot");
2154 /* Unlock the first process lock, then check this was the WRITE lock that was
2155 removed. */
2157 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2158 cli_lock(cli2, fnum2, 0, 4, 0, READ_LOCK);
2160 EXPECTED(ret, True);
2161 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2163 /* Unlock the process 2 lock. */
2164 cli_unlock(cli2, fnum2, 0, 4);
2166 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2168 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2169 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2170 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2172 EXPECTED(ret, True);
2173 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2175 /* Ensure the next unlock fails. */
2176 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2177 EXPECTED(ret, False);
2178 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2180 /* Ensure connection 2 can get a write lock. */
2181 ret = cli_lock(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2182 EXPECTED(ret, True);
2184 printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2187 fail:
2188 cli_close(cli1, fnum1);
2189 cli_close(cli2, fnum2);
2190 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2191 if (!torture_close_connection(cli1)) {
2192 correct = False;
2194 if (!torture_close_connection(cli2)) {
2195 correct = False;
2198 printf("finished locktest5\n");
2200 return correct;
2204 tries the unusual lockingX locktype bits
2206 static bool run_locktest6(int dummy)
2208 static struct cli_state *cli;
2209 const char *fname[1] = { "\\lock6.txt" };
2210 int i;
2211 uint16_t fnum;
2212 NTSTATUS status;
2214 if (!torture_open_connection(&cli, 0)) {
2215 return False;
2218 cli_sockopt(cli, sockops);
2220 printf("starting locktest6\n");
2222 for (i=0;i<1;i++) {
2223 printf("Testing %s\n", fname[i]);
2225 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2227 cli_open(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2228 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2229 cli_close(cli, fnum);
2230 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2232 cli_open(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2233 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2234 cli_close(cli, fnum);
2235 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2237 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2240 torture_close_connection(cli);
2242 printf("finished locktest6\n");
2243 return True;
2246 static bool run_locktest7(int dummy)
2248 struct cli_state *cli1;
2249 const char *fname = "\\lockt7.lck";
2250 uint16_t fnum1;
2251 char buf[200];
2252 bool correct = False;
2253 NTSTATUS status;
2255 if (!torture_open_connection(&cli1, 0)) {
2256 return False;
2259 cli_sockopt(cli1, sockops);
2261 printf("starting locktest7\n");
2263 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2265 cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2267 memset(buf, 0, sizeof(buf));
2269 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2270 NULL);
2271 if (!NT_STATUS_IS_OK(status)) {
2272 printf("Failed to create file: %s\n", nt_errstr(status));
2273 goto fail;
2276 cli_setpid(cli1, 1);
2278 if (!cli_lock(cli1, fnum1, 130, 4, 0, READ_LOCK)) {
2279 printf("Unable to apply read lock on range 130:4, error was %s\n", cli_errstr(cli1));
2280 goto fail;
2281 } else {
2282 printf("pid1 successfully locked range 130:4 for READ\n");
2285 if (cli_read(cli1, fnum1, buf, 130, 4) != 4) {
2286 printf("pid1 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2287 goto fail;
2288 } else {
2289 printf("pid1 successfully read the range 130:4\n");
2292 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2293 if (!NT_STATUS_IS_OK(status)) {
2294 printf("pid1 unable to write to the range 130:4, error was "
2295 "%s\n", nt_errstr(status));
2296 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2297 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2298 goto fail;
2300 } else {
2301 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2302 goto fail;
2305 cli_setpid(cli1, 2);
2307 if (cli_read(cli1, fnum1, buf, 130, 4) != 4) {
2308 printf("pid2 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2309 } else {
2310 printf("pid2 successfully read the range 130:4\n");
2313 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2314 if (!NT_STATUS_IS_OK(status)) {
2315 printf("pid2 unable to write to the range 130:4, error was "
2316 "%s\n", nt_errstr(status));
2317 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2318 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2319 goto fail;
2321 } else {
2322 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2323 goto fail;
2326 cli_setpid(cli1, 1);
2327 cli_unlock(cli1, fnum1, 130, 4);
2329 if (!cli_lock(cli1, fnum1, 130, 4, 0, WRITE_LOCK)) {
2330 printf("Unable to apply write lock on range 130:4, error was %s\n", cli_errstr(cli1));
2331 goto fail;
2332 } else {
2333 printf("pid1 successfully locked range 130:4 for WRITE\n");
2336 if (cli_read(cli1, fnum1, buf, 130, 4) != 4) {
2337 printf("pid1 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2338 goto fail;
2339 } else {
2340 printf("pid1 successfully read the range 130:4\n");
2343 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2344 if (!NT_STATUS_IS_OK(status)) {
2345 printf("pid1 unable to write to the range 130:4, error was "
2346 "%s\n", nt_errstr(status));
2347 goto fail;
2348 } else {
2349 printf("pid1 successfully wrote to the range 130:4\n");
2352 cli_setpid(cli1, 2);
2354 if (cli_read(cli1, fnum1, buf, 130, 4) != 4) {
2355 printf("pid2 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2356 if (NT_STATUS_V(cli_nt_error(cli1)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
2357 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2358 goto fail;
2360 } else {
2361 printf("pid2 successfully read the range 130:4 (should be denied)\n");
2362 goto fail;
2365 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2366 if (!NT_STATUS_IS_OK(status)) {
2367 printf("pid2 unable to write to the range 130:4, error was "
2368 "%s\n", nt_errstr(status));
2369 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2370 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2371 goto fail;
2373 } else {
2374 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2375 goto fail;
2378 cli_unlock(cli1, fnum1, 130, 0);
2379 correct = True;
2381 fail:
2382 cli_close(cli1, fnum1);
2383 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2384 torture_close_connection(cli1);
2386 printf("finished locktest7\n");
2387 return correct;
2391 * This demonstrates a problem with our use of GPFS share modes: A file
2392 * descriptor sitting in the pending close queue holding a GPFS share mode
2393 * blocks opening a file another time. Happens with Word 2007 temp files.
2394 * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2395 * open is denied with NT_STATUS_SHARING_VIOLATION.
2398 static bool run_locktest8(int dummy)
2400 struct cli_state *cli1;
2401 const char *fname = "\\lockt8.lck";
2402 uint16_t fnum1, fnum2;
2403 char buf[200];
2404 bool correct = False;
2405 NTSTATUS status;
2407 if (!torture_open_connection(&cli1, 0)) {
2408 return False;
2411 cli_sockopt(cli1, sockops);
2413 printf("starting locktest8\n");
2415 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2417 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2418 &fnum1);
2419 if (!NT_STATUS_IS_OK(status)) {
2420 d_fprintf(stderr, "cli_open returned %s\n", nt_errstr(status));
2421 return false;
2424 memset(buf, 0, sizeof(buf));
2426 status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2427 if (!NT_STATUS_IS_OK(status)) {
2428 d_fprintf(stderr, "cli_open second time returned %s\n",
2429 nt_errstr(status));
2430 goto fail;
2433 if (!cli_lock(cli1, fnum2, 1, 1, 0, READ_LOCK)) {
2434 printf("Unable to apply read lock on range 1:1, error was "
2435 "%s\n", cli_errstr(cli1));
2436 goto fail;
2439 status = cli_close(cli1, fnum1);
2440 if (!NT_STATUS_IS_OK(status)) {
2441 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2442 goto fail;
2445 status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2446 if (!NT_STATUS_IS_OK(status)) {
2447 d_fprintf(stderr, "cli_open third time returned %s\n",
2448 nt_errstr(status));
2449 goto fail;
2452 correct = true;
2454 fail:
2455 cli_close(cli1, fnum1);
2456 cli_close(cli1, fnum2);
2457 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2458 torture_close_connection(cli1);
2460 printf("finished locktest8\n");
2461 return correct;
2465 * This test is designed to be run in conjunction with
2466 * external NFS or POSIX locks taken in the filesystem.
2467 * It checks that the smbd server will block until the
2468 * lock is released and then acquire it. JRA.
2471 static bool got_alarm;
2472 static int alarm_fd;
2474 static void alarm_handler(int dummy)
2476 got_alarm = True;
2479 static void alarm_handler_parent(int dummy)
2481 close(alarm_fd);
2484 static void do_local_lock(int read_fd, int write_fd)
2486 int fd;
2487 char c = '\0';
2488 struct flock lock;
2489 const char *local_pathname = NULL;
2490 int ret;
2492 local_pathname = talloc_asprintf(talloc_tos(),
2493 "%s/lockt9.lck", local_path);
2494 if (!local_pathname) {
2495 printf("child: alloc fail\n");
2496 exit(1);
2499 unlink(local_pathname);
2500 fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2501 if (fd == -1) {
2502 printf("child: open of %s failed %s.\n",
2503 local_pathname, strerror(errno));
2504 exit(1);
2507 /* Now take a fcntl lock. */
2508 lock.l_type = F_WRLCK;
2509 lock.l_whence = SEEK_SET;
2510 lock.l_start = 0;
2511 lock.l_len = 4;
2512 lock.l_pid = getpid();
2514 ret = fcntl(fd,F_SETLK,&lock);
2515 if (ret == -1) {
2516 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2517 local_pathname, strerror(errno));
2518 exit(1);
2519 } else {
2520 printf("child: got lock 0:4 on file %s.\n",
2521 local_pathname );
2522 fflush(stdout);
2525 CatchSignal(SIGALRM, alarm_handler);
2526 alarm(5);
2527 /* Signal the parent. */
2528 if (write(write_fd, &c, 1) != 1) {
2529 printf("child: start signal fail %s.\n",
2530 strerror(errno));
2531 exit(1);
2533 alarm(0);
2535 alarm(10);
2536 /* Wait for the parent to be ready. */
2537 if (read(read_fd, &c, 1) != 1) {
2538 printf("child: reply signal fail %s.\n",
2539 strerror(errno));
2540 exit(1);
2542 alarm(0);
2544 sleep(5);
2545 close(fd);
2546 printf("child: released lock 0:4 on file %s.\n",
2547 local_pathname );
2548 fflush(stdout);
2549 exit(0);
2552 static bool run_locktest9(int dummy)
2554 struct cli_state *cli1;
2555 const char *fname = "\\lockt9.lck";
2556 uint16_t fnum;
2557 bool correct = False;
2558 int pipe_in[2], pipe_out[2];
2559 pid_t child_pid;
2560 char c = '\0';
2561 int ret;
2562 struct timeval start;
2563 double seconds;
2564 NTSTATUS status;
2566 printf("starting locktest9\n");
2568 if (local_path == NULL) {
2569 d_fprintf(stderr, "locktest9 must be given a local path via -l <localpath>\n");
2570 return false;
2573 if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2574 return false;
2577 child_pid = fork();
2578 if (child_pid == -1) {
2579 return false;
2582 if (child_pid == 0) {
2583 /* Child. */
2584 do_local_lock(pipe_out[0], pipe_in[1]);
2585 exit(0);
2588 close(pipe_out[0]);
2589 close(pipe_in[1]);
2590 pipe_out[0] = -1;
2591 pipe_in[1] = -1;
2593 /* Parent. */
2594 ret = read(pipe_in[0], &c, 1);
2595 if (ret != 1) {
2596 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2597 strerror(errno));
2598 return false;
2601 if (!torture_open_connection(&cli1, 0)) {
2602 return false;
2605 cli_sockopt(cli1, sockops);
2607 status = cli_open(cli1, fname, O_RDWR, DENY_NONE,
2608 &fnum);
2609 if (!NT_STATUS_IS_OK(status)) {
2610 d_fprintf(stderr, "cli_open returned %s\n", nt_errstr(status));
2611 return false;
2614 /* Ensure the child has the lock. */
2615 if (cli_lock(cli1, fnum, 0, 4, 0, WRITE_LOCK)) {
2616 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2617 goto fail;
2618 } else {
2619 d_printf("Child has the lock.\n");
2622 /* Tell the child to wait 5 seconds then exit. */
2623 ret = write(pipe_out[1], &c, 1);
2624 if (ret != 1) {
2625 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2626 strerror(errno));
2627 goto fail;
2630 /* Wait 20 seconds for the lock. */
2631 alarm_fd = cli1->fd;
2632 CatchSignal(SIGALRM, alarm_handler_parent);
2633 alarm(20);
2635 start = timeval_current();
2637 if (!cli_lock(cli1, fnum, 0, 4, -1, WRITE_LOCK)) {
2638 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2639 "%s\n", cli_errstr(cli1));
2640 goto fail_nofd;
2642 alarm(0);
2644 seconds = timeval_elapsed(&start);
2646 printf("Parent got the lock after %.2f seconds.\n",
2647 seconds);
2649 status = cli_close(cli1, fnum);
2650 if (!NT_STATUS_IS_OK(status)) {
2651 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2652 goto fail;
2655 correct = true;
2657 fail:
2658 cli_close(cli1, fnum);
2659 torture_close_connection(cli1);
2661 fail_nofd:
2663 printf("finished locktest9\n");
2664 return correct;
2668 test whether fnums and tids open on one VC are available on another (a major
2669 security hole)
2671 static bool run_fdpasstest(int dummy)
2673 struct cli_state *cli1, *cli2;
2674 const char *fname = "\\fdpass.tst";
2675 uint16_t fnum1;
2676 char buf[1024];
2677 NTSTATUS status;
2679 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2680 return False;
2682 cli_sockopt(cli1, sockops);
2683 cli_sockopt(cli2, sockops);
2685 printf("starting fdpasstest\n");
2687 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2689 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
2690 &fnum1);
2691 if (!NT_STATUS_IS_OK(status)) {
2692 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2693 return False;
2696 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
2697 13, NULL);
2698 if (!NT_STATUS_IS_OK(status)) {
2699 printf("write failed (%s)\n", nt_errstr(status));
2700 return False;
2703 cli2->vuid = cli1->vuid;
2704 cli2->cnum = cli1->cnum;
2705 cli2->pid = cli1->pid;
2707 if (cli_read(cli2, fnum1, buf, 0, 13) == 13) {
2708 printf("read succeeded! nasty security hole [%s]\n",
2709 buf);
2710 return False;
2713 cli_close(cli1, fnum1);
2714 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2716 torture_close_connection(cli1);
2717 torture_close_connection(cli2);
2719 printf("finished fdpasstest\n");
2720 return True;
2723 static bool run_fdsesstest(int dummy)
2725 struct cli_state *cli;
2726 uint16 new_vuid;
2727 uint16 saved_vuid;
2728 uint16 new_cnum;
2729 uint16 saved_cnum;
2730 const char *fname = "\\fdsess.tst";
2731 const char *fname1 = "\\fdsess1.tst";
2732 uint16_t fnum1;
2733 uint16_t fnum2;
2734 char buf[1024];
2735 bool ret = True;
2736 NTSTATUS status;
2738 if (!torture_open_connection(&cli, 0))
2739 return False;
2740 cli_sockopt(cli, sockops);
2742 if (!torture_cli_session_setup2(cli, &new_vuid))
2743 return False;
2745 saved_cnum = cli->cnum;
2746 if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, share, "?????", "", 1)))
2747 return False;
2748 new_cnum = cli->cnum;
2749 cli->cnum = saved_cnum;
2751 printf("starting fdsesstest\n");
2753 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2754 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2756 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2757 if (!NT_STATUS_IS_OK(status)) {
2758 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2759 return False;
2762 status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
2763 NULL);
2764 if (!NT_STATUS_IS_OK(status)) {
2765 printf("write failed (%s)\n", nt_errstr(status));
2766 return False;
2769 saved_vuid = cli->vuid;
2770 cli->vuid = new_vuid;
2772 if (cli_read(cli, fnum1, buf, 0, 13) == 13) {
2773 printf("read succeeded with different vuid! nasty security hole [%s]\n",
2774 buf);
2775 ret = False;
2777 /* Try to open a file with different vuid, samba cnum. */
2778 if (NT_STATUS_IS_OK(cli_open(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
2779 printf("create with different vuid, same cnum succeeded.\n");
2780 cli_close(cli, fnum2);
2781 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2782 } else {
2783 printf("create with different vuid, same cnum failed.\n");
2784 printf("This will cause problems with service clients.\n");
2785 ret = False;
2788 cli->vuid = saved_vuid;
2790 /* Try with same vuid, different cnum. */
2791 cli->cnum = new_cnum;
2793 if (cli_read(cli, fnum1, buf, 0, 13) == 13) {
2794 printf("read succeeded with different cnum![%s]\n",
2795 buf);
2796 ret = False;
2799 cli->cnum = saved_cnum;
2800 cli_close(cli, fnum1);
2801 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2803 torture_close_connection(cli);
2805 printf("finished fdsesstest\n");
2806 return ret;
2810 This test checks that
2812 1) the server does not allow an unlink on a file that is open
2814 static bool run_unlinktest(int dummy)
2816 struct cli_state *cli;
2817 const char *fname = "\\unlink.tst";
2818 uint16_t fnum;
2819 bool correct = True;
2820 NTSTATUS status;
2822 if (!torture_open_connection(&cli, 0)) {
2823 return False;
2826 cli_sockopt(cli, sockops);
2828 printf("starting unlink test\n");
2830 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2832 cli_setpid(cli, 1);
2834 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2835 if (!NT_STATUS_IS_OK(status)) {
2836 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2837 return False;
2840 status = cli_unlink(cli, fname,
2841 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2842 if (NT_STATUS_IS_OK(status)) {
2843 printf("error: server allowed unlink on an open file\n");
2844 correct = False;
2845 } else {
2846 correct = check_error(__LINE__, cli, ERRDOS, ERRbadshare,
2847 NT_STATUS_SHARING_VIOLATION);
2850 cli_close(cli, fnum);
2851 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2853 if (!torture_close_connection(cli)) {
2854 correct = False;
2857 printf("unlink test finished\n");
2859 return correct;
2864 test how many open files this server supports on the one socket
2866 static bool run_maxfidtest(int dummy)
2868 struct cli_state *cli;
2869 fstring fname;
2870 uint16_t fnums[0x11000];
2871 int i;
2872 int retries=4;
2873 bool correct = True;
2874 NTSTATUS status;
2876 cli = current_cli;
2878 if (retries <= 0) {
2879 printf("failed to connect\n");
2880 return False;
2883 cli_sockopt(cli, sockops);
2885 for (i=0; i<0x11000; i++) {
2886 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2887 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
2888 &fnums[i]);
2889 if (!NT_STATUS_IS_OK(status)) {
2890 printf("open of %s failed (%s)\n",
2891 fname, nt_errstr(status));
2892 printf("maximum fnum is %d\n", i);
2893 break;
2895 printf("%6d\r", i);
2897 printf("%6d\n", i);
2898 i--;
2900 printf("cleaning up\n");
2901 for (;i>=0;i--) {
2902 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2903 cli_close(cli, fnums[i]);
2905 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2906 if (!NT_STATUS_IS_OK(status)) {
2907 printf("unlink of %s failed (%s)\n",
2908 fname, nt_errstr(status));
2909 correct = False;
2911 printf("%6d\r", i);
2913 printf("%6d\n", 0);
2915 printf("maxfid test finished\n");
2916 if (!torture_close_connection(cli)) {
2917 correct = False;
2919 return correct;
2922 /* generate a random buffer */
2923 static void rand_buf(char *buf, int len)
2925 while (len--) {
2926 *buf = (char)sys_random();
2927 buf++;
2931 /* send smb negprot commands, not reading the response */
2932 static bool run_negprot_nowait(int dummy)
2934 struct tevent_context *ev;
2935 int i;
2936 struct cli_state *cli;
2937 bool correct = True;
2939 printf("starting negprot nowait test\n");
2941 ev = tevent_context_init(talloc_tos());
2942 if (ev == NULL) {
2943 return false;
2946 if (!(cli = open_nbt_connection())) {
2947 TALLOC_FREE(ev);
2948 return False;
2951 for (i=0;i<50000;i++) {
2952 struct tevent_req *req;
2954 req = cli_negprot_send(ev, ev, cli);
2955 if (req == NULL) {
2956 TALLOC_FREE(ev);
2957 return false;
2959 if (!tevent_req_poll(req, ev)) {
2960 d_fprintf(stderr, "tevent_req_poll failed: %s\n",
2961 strerror(errno));
2962 TALLOC_FREE(ev);
2963 return false;
2965 TALLOC_FREE(req);
2968 if (torture_close_connection(cli)) {
2969 correct = False;
2972 printf("finished negprot nowait test\n");
2974 return correct;
2977 /* send smb negprot commands, not reading the response */
2978 static bool run_bad_nbt_session(int dummy)
2980 struct nmb_name called, calling;
2981 struct sockaddr_storage ss;
2982 NTSTATUS status;
2983 int fd;
2984 bool ret;
2986 printf("starting bad nbt session test\n");
2988 make_nmb_name(&calling, myname, 0x0);
2989 make_nmb_name(&called , host, 0x20);
2991 if (!resolve_name(host, &ss, 0x20, true)) {
2992 d_fprintf(stderr, "Could not resolve name %s\n", host);
2993 return false;
2996 status = open_socket_out(&ss, 139, 10000, &fd);
2997 if (!NT_STATUS_IS_OK(status)) {
2998 d_fprintf(stderr, "open_socket_out failed: %s\n",
2999 nt_errstr(status));
3000 return false;
3003 ret = cli_bad_session_request(fd, &calling, &called);
3004 close(fd);
3005 if (!ret) {
3006 d_fprintf(stderr, "open_socket_out failed: %s\n",
3007 nt_errstr(status));
3008 return false;
3011 printf("finished bad nbt session test\n");
3012 return true;
3015 /* send random IPC commands */
3016 static bool run_randomipc(int dummy)
3018 char *rparam = NULL;
3019 char *rdata = NULL;
3020 unsigned int rdrcnt,rprcnt;
3021 char param[1024];
3022 int api, param_len, i;
3023 struct cli_state *cli;
3024 bool correct = True;
3025 int count = 50000;
3027 printf("starting random ipc test\n");
3029 if (!torture_open_connection(&cli, 0)) {
3030 return False;
3033 for (i=0;i<count;i++) {
3034 api = sys_random() % 500;
3035 param_len = (sys_random() % 64);
3037 rand_buf(param, param_len);
3039 SSVAL(param,0,api);
3041 cli_api(cli,
3042 param, param_len, 8,
3043 NULL, 0, BUFFER_SIZE,
3044 &rparam, &rprcnt,
3045 &rdata, &rdrcnt);
3046 if (i % 100 == 0) {
3047 printf("%d/%d\r", i,count);
3050 printf("%d/%d\n", i, count);
3052 if (!torture_close_connection(cli)) {
3053 correct = False;
3056 printf("finished random ipc test\n");
3058 return correct;
3063 static void browse_callback(const char *sname, uint32 stype,
3064 const char *comment, void *state)
3066 printf("\t%20.20s %08x %s\n", sname, stype, comment);
3072 This test checks the browse list code
3075 static bool run_browsetest(int dummy)
3077 static struct cli_state *cli;
3078 bool correct = True;
3080 printf("starting browse test\n");
3082 if (!torture_open_connection(&cli, 0)) {
3083 return False;
3086 printf("domain list:\n");
3087 cli_NetServerEnum(cli, cli->server_domain,
3088 SV_TYPE_DOMAIN_ENUM,
3089 browse_callback, NULL);
3091 printf("machine list:\n");
3092 cli_NetServerEnum(cli, cli->server_domain,
3093 SV_TYPE_ALL,
3094 browse_callback, NULL);
3096 if (!torture_close_connection(cli)) {
3097 correct = False;
3100 printf("browse test finished\n");
3102 return correct;
3108 This checks how the getatr calls works
3110 static bool run_attrtest(int dummy)
3112 struct cli_state *cli;
3113 uint16_t fnum;
3114 time_t t, t2;
3115 const char *fname = "\\attrib123456789.tst";
3116 bool correct = True;
3117 NTSTATUS status;
3119 printf("starting attrib test\n");
3121 if (!torture_open_connection(&cli, 0)) {
3122 return False;
3125 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3126 cli_open(cli, fname,
3127 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3128 cli_close(cli, fnum);
3130 status = cli_getatr(cli, fname, NULL, NULL, &t);
3131 if (!NT_STATUS_IS_OK(status)) {
3132 printf("getatr failed (%s)\n", nt_errstr(status));
3133 correct = False;
3136 if (abs(t - time(NULL)) > 60*60*24*10) {
3137 printf("ERROR: SMBgetatr bug. time is %s",
3138 ctime(&t));
3139 t = time(NULL);
3140 correct = True;
3143 t2 = t-60*60*24; /* 1 day ago */
3145 status = cli_setatr(cli, fname, 0, t2);
3146 if (!NT_STATUS_IS_OK(status)) {
3147 printf("setatr failed (%s)\n", nt_errstr(status));
3148 correct = True;
3151 status = cli_getatr(cli, fname, NULL, NULL, &t);
3152 if (!NT_STATUS_IS_OK(status)) {
3153 printf("getatr failed (%s)\n", nt_errstr(status));
3154 correct = True;
3157 if (t != t2) {
3158 printf("ERROR: getatr/setatr bug. times are\n%s",
3159 ctime(&t));
3160 printf("%s", ctime(&t2));
3161 correct = True;
3164 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3166 if (!torture_close_connection(cli)) {
3167 correct = False;
3170 printf("attrib test finished\n");
3172 return correct;
3177 This checks a couple of trans2 calls
3179 static bool run_trans2test(int dummy)
3181 struct cli_state *cli;
3182 uint16_t fnum;
3183 SMB_OFF_T size;
3184 time_t c_time, a_time, m_time;
3185 struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
3186 const char *fname = "\\trans2.tst";
3187 const char *dname = "\\trans2";
3188 const char *fname2 = "\\trans2\\trans2.tst";
3189 char *pname;
3190 bool correct = True;
3191 NTSTATUS status;
3192 uint32_t fs_attr;
3194 printf("starting trans2 test\n");
3196 if (!torture_open_connection(&cli, 0)) {
3197 return False;
3200 status = cli_get_fs_attr_info(cli, &fs_attr);
3201 if (!NT_STATUS_IS_OK(status)) {
3202 printf("ERROR: cli_get_fs_attr_info returned %s\n",
3203 nt_errstr(status));
3204 correct = false;
3207 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3208 cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3209 status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
3210 &a_time_ts, &w_time_ts, &m_time_ts, NULL);
3211 if (!NT_STATUS_IS_OK(status)) {
3212 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
3213 correct = False;
3216 status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
3217 if (!NT_STATUS_IS_OK(status)) {
3218 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
3219 correct = False;
3222 if (strcmp(pname, fname)) {
3223 printf("qfilename gave different name? [%s] [%s]\n",
3224 fname, pname);
3225 correct = False;
3228 cli_close(cli, fnum);
3230 sleep(2);
3232 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3233 status = cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
3234 &fnum);
3235 if (!NT_STATUS_IS_OK(status)) {
3236 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3237 return False;
3239 cli_close(cli, fnum);
3241 status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
3242 NULL);
3243 if (!NT_STATUS_IS_OK(status)) {
3244 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
3245 correct = False;
3246 } else {
3247 if (c_time != m_time) {
3248 printf("create time=%s", ctime(&c_time));
3249 printf("modify time=%s", ctime(&m_time));
3250 printf("This system appears to have sticky create times\n");
3252 if (a_time % (60*60) == 0) {
3253 printf("access time=%s", ctime(&a_time));
3254 printf("This system appears to set a midnight access time\n");
3255 correct = False;
3258 if (abs(m_time - time(NULL)) > 60*60*24*7) {
3259 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
3260 correct = False;
3265 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3266 cli_open(cli, fname,
3267 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3268 cli_close(cli, fnum);
3269 status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
3270 &m_time_ts, &size, NULL, NULL);
3271 if (!NT_STATUS_IS_OK(status)) {
3272 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3273 correct = False;
3274 } else {
3275 if (w_time_ts.tv_sec < 60*60*24*2) {
3276 printf("write time=%s", ctime(&w_time_ts.tv_sec));
3277 printf("This system appears to set a initial 0 write time\n");
3278 correct = False;
3282 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3285 /* check if the server updates the directory modification time
3286 when creating a new file */
3287 status = cli_mkdir(cli, dname);
3288 if (!NT_STATUS_IS_OK(status)) {
3289 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
3290 correct = False;
3292 sleep(3);
3293 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3294 &w_time_ts, &m_time_ts, &size, NULL, NULL);
3295 if (!NT_STATUS_IS_OK(status)) {
3296 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3297 correct = False;
3300 cli_open(cli, fname2,
3301 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3302 cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
3303 cli_close(cli, fnum);
3304 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3305 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
3306 if (!NT_STATUS_IS_OK(status)) {
3307 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3308 correct = False;
3309 } else {
3310 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
3311 == 0) {
3312 printf("This system does not update directory modification times\n");
3313 correct = False;
3316 cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3317 cli_rmdir(cli, dname);
3319 if (!torture_close_connection(cli)) {
3320 correct = False;
3323 printf("trans2 test finished\n");
3325 return correct;
3329 This checks new W2K calls.
3332 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
3334 uint8_t *buf = NULL;
3335 uint32 len;
3336 NTSTATUS status;
3338 status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
3339 pcli->max_xmit, NULL, &buf, &len);
3340 if (!NT_STATUS_IS_OK(status)) {
3341 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
3342 nt_errstr(status));
3343 } else {
3344 printf("qfileinfo: level %d, len = %u\n", level, len);
3345 dump_data(0, (uint8 *)buf, len);
3346 printf("\n");
3348 TALLOC_FREE(buf);
3349 return status;
3352 static bool run_w2ktest(int dummy)
3354 struct cli_state *cli;
3355 uint16_t fnum;
3356 const char *fname = "\\w2ktest\\w2k.tst";
3357 int level;
3358 bool correct = True;
3360 printf("starting w2k test\n");
3362 if (!torture_open_connection(&cli, 0)) {
3363 return False;
3366 cli_open(cli, fname,
3367 O_RDWR | O_CREAT , DENY_NONE, &fnum);
3369 for (level = 1004; level < 1040; level++) {
3370 new_trans(cli, fnum, level);
3373 cli_close(cli, fnum);
3375 if (!torture_close_connection(cli)) {
3376 correct = False;
3379 printf("w2k test finished\n");
3381 return correct;
3386 this is a harness for some oplock tests
3388 static bool run_oplock1(int dummy)
3390 struct cli_state *cli1;
3391 const char *fname = "\\lockt1.lck";
3392 uint16_t fnum1;
3393 bool correct = True;
3394 NTSTATUS status;
3396 printf("starting oplock test 1\n");
3398 if (!torture_open_connection(&cli1, 0)) {
3399 return False;
3402 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3404 cli_sockopt(cli1, sockops);
3406 cli1->use_oplocks = True;
3408 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3409 &fnum1);
3410 if (!NT_STATUS_IS_OK(status)) {
3411 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3412 return False;
3415 cli1->use_oplocks = False;
3417 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3418 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3420 status = cli_close(cli1, fnum1);
3421 if (!NT_STATUS_IS_OK(status)) {
3422 printf("close2 failed (%s)\n", nt_errstr(status));
3423 return False;
3426 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3427 if (!NT_STATUS_IS_OK(status)) {
3428 printf("unlink failed (%s)\n", nt_errstr(status));
3429 return False;
3432 if (!torture_close_connection(cli1)) {
3433 correct = False;
3436 printf("finished oplock test 1\n");
3438 return correct;
3441 static bool run_oplock2(int dummy)
3443 struct cli_state *cli1, *cli2;
3444 const char *fname = "\\lockt2.lck";
3445 uint16_t fnum1, fnum2;
3446 int saved_use_oplocks = use_oplocks;
3447 char buf[4];
3448 bool correct = True;
3449 volatile bool *shared_correct;
3450 NTSTATUS status;
3452 shared_correct = (volatile bool *)shm_setup(sizeof(bool));
3453 *shared_correct = True;
3455 use_level_II_oplocks = True;
3456 use_oplocks = True;
3458 printf("starting oplock test 2\n");
3460 if (!torture_open_connection(&cli1, 0)) {
3461 use_level_II_oplocks = False;
3462 use_oplocks = saved_use_oplocks;
3463 return False;
3466 cli1->use_oplocks = True;
3467 cli1->use_level_II_oplocks = True;
3469 if (!torture_open_connection(&cli2, 1)) {
3470 use_level_II_oplocks = False;
3471 use_oplocks = saved_use_oplocks;
3472 return False;
3475 cli2->use_oplocks = True;
3476 cli2->use_level_II_oplocks = True;
3478 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3480 cli_sockopt(cli1, sockops);
3481 cli_sockopt(cli2, sockops);
3483 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3484 &fnum1);
3485 if (!NT_STATUS_IS_OK(status)) {
3486 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3487 return False;
3490 /* Don't need the globals any more. */
3491 use_level_II_oplocks = False;
3492 use_oplocks = saved_use_oplocks;
3494 if (fork() == 0) {
3495 /* Child code */
3496 status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
3497 if (!NT_STATUS_IS_OK(status)) {
3498 printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
3499 *shared_correct = False;
3500 exit(0);
3503 sleep(2);
3505 status = cli_close(cli2, fnum2);
3506 if (!NT_STATUS_IS_OK(status)) {
3507 printf("close2 failed (%s)\n", nt_errstr(status));
3508 *shared_correct = False;
3511 exit(0);
3514 sleep(2);
3516 /* Ensure cli1 processes the break. Empty file should always return 0
3517 * bytes. */
3519 if (cli_read(cli1, fnum1, buf, 0, 4) != 0) {
3520 printf("read on fnum1 failed (%s)\n", cli_errstr(cli1));
3521 correct = False;
3524 /* Should now be at level II. */
3525 /* Test if sending a write locks causes a break to none. */
3527 if (!cli_lock(cli1, fnum1, 0, 4, 0, READ_LOCK)) {
3528 printf("lock failed (%s)\n", cli_errstr(cli1));
3529 correct = False;
3532 cli_unlock(cli1, fnum1, 0, 4);
3534 sleep(2);
3536 if (!cli_lock(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) {
3537 printf("lock failed (%s)\n", cli_errstr(cli1));
3538 correct = False;
3541 cli_unlock(cli1, fnum1, 0, 4);
3543 sleep(2);
3545 cli_read(cli1, fnum1, buf, 0, 4);
3547 status = cli_close(cli1, fnum1);
3548 if (!NT_STATUS_IS_OK(status)) {
3549 printf("close1 failed (%s)\n", nt_errstr(status));
3550 correct = False;
3553 sleep(4);
3555 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3556 if (!NT_STATUS_IS_OK(status)) {
3557 printf("unlink failed (%s)\n", nt_errstr(status));
3558 correct = False;
3561 if (!torture_close_connection(cli1)) {
3562 correct = False;
3565 if (!*shared_correct) {
3566 correct = False;
3569 printf("finished oplock test 2\n");
3571 return correct;
3574 struct oplock4_state {
3575 struct tevent_context *ev;
3576 struct cli_state *cli;
3577 bool *got_break;
3578 uint16_t *fnum2;
3581 static void oplock4_got_break(struct tevent_req *req);
3582 static void oplock4_got_open(struct tevent_req *req);
3584 static bool run_oplock4(int dummy)
3586 struct tevent_context *ev;
3587 struct cli_state *cli1, *cli2;
3588 struct tevent_req *oplock_req, *open_req;
3589 const char *fname = "\\lockt4.lck";
3590 const char *fname_ln = "\\lockt4_ln.lck";
3591 uint16_t fnum1, fnum2;
3592 int saved_use_oplocks = use_oplocks;
3593 NTSTATUS status;
3594 bool correct = true;
3596 bool got_break;
3598 struct oplock4_state *state;
3600 printf("starting oplock test 4\n");
3602 if (!torture_open_connection(&cli1, 0)) {
3603 use_level_II_oplocks = false;
3604 use_oplocks = saved_use_oplocks;
3605 return false;
3608 if (!torture_open_connection(&cli2, 1)) {
3609 use_level_II_oplocks = false;
3610 use_oplocks = saved_use_oplocks;
3611 return false;
3614 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3615 cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3617 cli_sockopt(cli1, sockops);
3618 cli_sockopt(cli2, sockops);
3620 /* Create the file. */
3621 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3622 &fnum1);
3623 if (!NT_STATUS_IS_OK(status)) {
3624 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3625 return false;
3628 status = cli_close(cli1, fnum1);
3629 if (!NT_STATUS_IS_OK(status)) {
3630 printf("close1 failed (%s)\n", nt_errstr(status));
3631 return false;
3634 /* Now create a hardlink. */
3635 status = cli_nt_hardlink(cli1, fname, fname_ln);
3636 if (!NT_STATUS_IS_OK(status)) {
3637 printf("nt hardlink failed (%s)\n", nt_errstr(status));
3638 return false;
3641 /* Prove that opening hardlinks cause deny modes to conflict. */
3642 status = cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
3643 if (!NT_STATUS_IS_OK(status)) {
3644 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3645 return false;
3648 status = cli_open(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
3649 if (NT_STATUS_IS_OK(status)) {
3650 printf("open of %s succeeded - should fail with sharing violation.\n",
3651 fname_ln);
3652 return false;
3655 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3656 printf("open of %s should fail with sharing violation. Got %s\n",
3657 fname_ln, nt_errstr(status));
3658 return false;
3661 status = cli_close(cli1, fnum1);
3662 if (!NT_STATUS_IS_OK(status)) {
3663 printf("close1 failed (%s)\n", nt_errstr(status));
3664 return false;
3667 cli1->use_oplocks = true;
3668 cli1->use_level_II_oplocks = true;
3670 cli2->use_oplocks = true;
3671 cli2->use_level_II_oplocks = true;
3673 status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3674 if (!NT_STATUS_IS_OK(status)) {
3675 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3676 return false;
3679 ev = tevent_context_init(talloc_tos());
3680 if (ev == NULL) {
3681 printf("tevent_req_create failed\n");
3682 return false;
3685 state = talloc(ev, struct oplock4_state);
3686 if (state == NULL) {
3687 printf("talloc failed\n");
3688 return false;
3690 state->ev = ev;
3691 state->cli = cli1;
3692 state->got_break = &got_break;
3693 state->fnum2 = &fnum2;
3695 oplock_req = cli_smb_oplock_break_waiter_send(
3696 talloc_tos(), ev, cli1);
3697 if (oplock_req == NULL) {
3698 printf("cli_smb_oplock_break_waiter_send failed\n");
3699 return false;
3701 tevent_req_set_callback(oplock_req, oplock4_got_break, state);
3703 open_req = cli_open_send(
3704 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
3705 if (oplock_req == NULL) {
3706 printf("cli_open_send failed\n");
3707 return false;
3709 tevent_req_set_callback(open_req, oplock4_got_open, state);
3711 got_break = false;
3712 fnum2 = 0xffff;
3714 while (!got_break || fnum2 == 0xffff) {
3715 int ret;
3716 ret = tevent_loop_once(ev);
3717 if (ret == -1) {
3718 printf("tevent_loop_once failed: %s\n",
3719 strerror(errno));
3720 return false;
3724 status = cli_close(cli2, fnum2);
3725 if (!NT_STATUS_IS_OK(status)) {
3726 printf("close2 failed (%s)\n", nt_errstr(status));
3727 correct = false;
3730 status = cli_close(cli1, fnum1);
3731 if (!NT_STATUS_IS_OK(status)) {
3732 printf("close1 failed (%s)\n", nt_errstr(status));
3733 correct = false;
3736 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3737 if (!NT_STATUS_IS_OK(status)) {
3738 printf("unlink failed (%s)\n", nt_errstr(status));
3739 correct = false;
3742 status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3743 if (!NT_STATUS_IS_OK(status)) {
3744 printf("unlink failed (%s)\n", nt_errstr(status));
3745 correct = false;
3748 if (!torture_close_connection(cli1)) {
3749 correct = false;
3752 if (!got_break) {
3753 correct = false;
3756 printf("finished oplock test 4\n");
3758 return correct;
3761 static void oplock4_got_break(struct tevent_req *req)
3763 struct oplock4_state *state = tevent_req_callback_data(
3764 req, struct oplock4_state);
3765 uint16_t fnum;
3766 uint8_t level;
3767 NTSTATUS status;
3769 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
3770 TALLOC_FREE(req);
3771 if (!NT_STATUS_IS_OK(status)) {
3772 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
3773 nt_errstr(status));
3774 return;
3776 *state->got_break = true;
3778 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
3779 NO_OPLOCK);
3780 if (req == NULL) {
3781 printf("cli_oplock_ack_send failed\n");
3782 return;
3786 static void oplock4_got_open(struct tevent_req *req)
3788 struct oplock4_state *state = tevent_req_callback_data(
3789 req, struct oplock4_state);
3790 NTSTATUS status;
3792 status = cli_open_recv(req, state->fnum2);
3793 if (!NT_STATUS_IS_OK(status)) {
3794 printf("cli_open_recv returned %s\n", nt_errstr(status));
3795 *state->fnum2 = 0xffff;
3800 Test delete on close semantics.
3802 static bool run_deletetest(int dummy)
3804 struct cli_state *cli1 = NULL;
3805 struct cli_state *cli2 = NULL;
3806 const char *fname = "\\delete.file";
3807 uint16_t fnum1 = (uint16_t)-1;
3808 uint16_t fnum2 = (uint16_t)-1;
3809 bool correct = True;
3810 NTSTATUS status;
3812 printf("starting delete test\n");
3814 if (!torture_open_connection(&cli1, 0)) {
3815 return False;
3818 cli_sockopt(cli1, sockops);
3820 /* Test 1 - this should delete the file on close. */
3822 cli_setatr(cli1, fname, 0, 0);
3823 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3825 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
3826 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
3827 FILE_DELETE_ON_CLOSE, 0, &fnum1);
3828 if (!NT_STATUS_IS_OK(status)) {
3829 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
3830 correct = False;
3831 goto fail;
3834 status = cli_close(cli1, fnum1);
3835 if (!NT_STATUS_IS_OK(status)) {
3836 printf("[1] close failed (%s)\n", nt_errstr(status));
3837 correct = False;
3838 goto fail;
3841 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1))) {
3842 printf("[1] open of %s succeeded (should fail)\n", fname);
3843 correct = False;
3844 goto fail;
3847 printf("first delete on close test succeeded.\n");
3849 /* Test 2 - this should delete the file on close. */
3851 cli_setatr(cli1, fname, 0, 0);
3852 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3854 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3855 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
3856 FILE_OVERWRITE_IF, 0, 0, &fnum1);
3857 if (!NT_STATUS_IS_OK(status)) {
3858 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
3859 correct = False;
3860 goto fail;
3863 status = cli_nt_delete_on_close(cli1, fnum1, true);
3864 if (!NT_STATUS_IS_OK(status)) {
3865 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
3866 correct = False;
3867 goto fail;
3870 status = cli_close(cli1, fnum1);
3871 if (!NT_STATUS_IS_OK(status)) {
3872 printf("[2] close failed (%s)\n", nt_errstr(status));
3873 correct = False;
3874 goto fail;
3877 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3878 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
3879 status = cli_close(cli1, fnum1);
3880 if (!NT_STATUS_IS_OK(status)) {
3881 printf("[2] close failed (%s)\n", nt_errstr(status));
3882 correct = False;
3883 goto fail;
3885 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3886 } else
3887 printf("second delete on close test succeeded.\n");
3889 /* Test 3 - ... */
3890 cli_setatr(cli1, fname, 0, 0);
3891 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3893 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3894 FILE_ATTRIBUTE_NORMAL,
3895 FILE_SHARE_READ|FILE_SHARE_WRITE,
3896 FILE_OVERWRITE_IF, 0, 0, &fnum1);
3897 if (!NT_STATUS_IS_OK(status)) {
3898 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
3899 correct = False;
3900 goto fail;
3903 /* This should fail with a sharing violation - open for delete is only compatible
3904 with SHARE_DELETE. */
3906 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
3907 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, 0, &fnum2))) {
3908 printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
3909 correct = False;
3910 goto fail;
3913 /* This should succeed. */
3914 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3915 FILE_ATTRIBUTE_NORMAL,
3916 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3917 FILE_OPEN, 0, 0, &fnum2);
3918 if (!NT_STATUS_IS_OK(status)) {
3919 printf("[3] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
3920 correct = False;
3921 goto fail;
3924 status = cli_nt_delete_on_close(cli1, fnum1, true);
3925 if (!NT_STATUS_IS_OK(status)) {
3926 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
3927 correct = False;
3928 goto fail;
3931 status = cli_close(cli1, fnum1);
3932 if (!NT_STATUS_IS_OK(status)) {
3933 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
3934 correct = False;
3935 goto fail;
3938 status = cli_close(cli1, fnum2);
3939 if (!NT_STATUS_IS_OK(status)) {
3940 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
3941 correct = False;
3942 goto fail;
3945 /* This should fail - file should no longer be there. */
3947 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3948 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
3949 status = cli_close(cli1, fnum1);
3950 if (!NT_STATUS_IS_OK(status)) {
3951 printf("[3] close failed (%s)\n", nt_errstr(status));
3953 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3954 correct = False;
3955 goto fail;
3956 } else
3957 printf("third delete on close test succeeded.\n");
3959 /* Test 4 ... */
3960 cli_setatr(cli1, fname, 0, 0);
3961 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3963 status = cli_ntcreate(cli1, fname, 0,
3964 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
3965 FILE_ATTRIBUTE_NORMAL,
3966 FILE_SHARE_READ|FILE_SHARE_WRITE,
3967 FILE_OVERWRITE_IF, 0, 0, &fnum1);
3968 if (!NT_STATUS_IS_OK(status)) {
3969 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
3970 correct = False;
3971 goto fail;
3974 /* This should succeed. */
3975 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3976 FILE_ATTRIBUTE_NORMAL,
3977 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3978 FILE_OPEN, 0, 0, &fnum2);
3979 if (!NT_STATUS_IS_OK(status)) {
3980 printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
3981 correct = False;
3982 goto fail;
3985 status = cli_close(cli1, fnum2);
3986 if (!NT_STATUS_IS_OK(status)) {
3987 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
3988 correct = False;
3989 goto fail;
3992 status = cli_nt_delete_on_close(cli1, fnum1, true);
3993 if (!NT_STATUS_IS_OK(status)) {
3994 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
3995 correct = False;
3996 goto fail;
3999 /* This should fail - no more opens once delete on close set. */
4000 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4001 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4002 FILE_OPEN, 0, 0, &fnum2))) {
4003 printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
4004 correct = False;
4005 goto fail;
4006 } else
4007 printf("fourth delete on close test succeeded.\n");
4009 status = cli_close(cli1, fnum1);
4010 if (!NT_STATUS_IS_OK(status)) {
4011 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
4012 correct = False;
4013 goto fail;
4016 /* Test 5 ... */
4017 cli_setatr(cli1, fname, 0, 0);
4018 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4020 status = cli_open(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
4021 if (!NT_STATUS_IS_OK(status)) {
4022 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4023 correct = False;
4024 goto fail;
4027 /* This should fail - only allowed on NT opens with DELETE access. */
4029 if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4030 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
4031 correct = False;
4032 goto fail;
4035 status = cli_close(cli1, fnum1);
4036 if (!NT_STATUS_IS_OK(status)) {
4037 printf("[5] close - 2 failed (%s)\n", nt_errstr(status));
4038 correct = False;
4039 goto fail;
4042 printf("fifth delete on close test succeeded.\n");
4044 /* Test 6 ... */
4045 cli_setatr(cli1, fname, 0, 0);
4046 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4048 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4049 FILE_ATTRIBUTE_NORMAL,
4050 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4051 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4052 if (!NT_STATUS_IS_OK(status)) {
4053 printf("[6] open of %s failed (%s)\n", fname,
4054 nt_errstr(status));
4055 correct = False;
4056 goto fail;
4059 /* This should fail - only allowed on NT opens with DELETE access. */
4061 if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4062 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
4063 correct = False;
4064 goto fail;
4067 status = cli_close(cli1, fnum1);
4068 if (!NT_STATUS_IS_OK(status)) {
4069 printf("[6] close - 2 failed (%s)\n", nt_errstr(status));
4070 correct = False;
4071 goto fail;
4074 printf("sixth delete on close test succeeded.\n");
4076 /* Test 7 ... */
4077 cli_setatr(cli1, fname, 0, 0);
4078 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4080 status = cli_ntcreate(cli1, fname, 0,
4081 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4082 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
4083 0, 0, &fnum1);
4084 if (!NT_STATUS_IS_OK(status)) {
4085 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4086 correct = False;
4087 goto fail;
4090 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4091 printf("[7] setting delete_on_close on file failed !\n");
4092 correct = False;
4093 goto fail;
4096 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, false))) {
4097 printf("[7] unsetting delete_on_close on file failed !\n");
4098 correct = False;
4099 goto fail;
4102 status = cli_close(cli1, fnum1);
4103 if (!NT_STATUS_IS_OK(status)) {
4104 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4105 correct = False;
4106 goto fail;
4109 /* This next open should succeed - we reset the flag. */
4110 status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4111 if (!NT_STATUS_IS_OK(status)) {
4112 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4113 correct = False;
4114 goto fail;
4117 status = cli_close(cli1, fnum1);
4118 if (!NT_STATUS_IS_OK(status)) {
4119 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4120 correct = False;
4121 goto fail;
4124 printf("seventh delete on close test succeeded.\n");
4126 /* Test 7 ... */
4127 cli_setatr(cli1, fname, 0, 0);
4128 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4130 if (!torture_open_connection(&cli2, 1)) {
4131 printf("[8] failed to open second connection.\n");
4132 correct = False;
4133 goto fail;
4136 cli_sockopt(cli1, sockops);
4138 status = cli_ntcreate(cli1, fname, 0,
4139 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4140 FILE_ATTRIBUTE_NORMAL,
4141 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4142 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4143 if (!NT_STATUS_IS_OK(status)) {
4144 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4145 correct = False;
4146 goto fail;
4149 status = cli_ntcreate(cli2, fname, 0,
4150 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4151 FILE_ATTRIBUTE_NORMAL,
4152 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4153 FILE_OPEN, 0, 0, &fnum2);
4154 if (!NT_STATUS_IS_OK(status)) {
4155 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4156 correct = False;
4157 goto fail;
4160 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4161 printf("[8] setting delete_on_close on file failed !\n");
4162 correct = False;
4163 goto fail;
4166 status = cli_close(cli1, fnum1);
4167 if (!NT_STATUS_IS_OK(status)) {
4168 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
4169 correct = False;
4170 goto fail;
4173 status = cli_close(cli2, fnum2);
4174 if (!NT_STATUS_IS_OK(status)) {
4175 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
4176 correct = False;
4177 goto fail;
4180 /* This should fail.. */
4181 status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4182 if (NT_STATUS_IS_OK(status)) {
4183 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
4184 goto fail;
4185 correct = False;
4186 } else
4187 printf("eighth delete on close test succeeded.\n");
4189 /* This should fail - we need to set DELETE_ACCESS. */
4190 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0,FILE_READ_DATA|FILE_WRITE_DATA,
4191 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE, 0, &fnum1))) {
4192 printf("[9] open of %s succeeded should have failed!\n", fname);
4193 correct = False;
4194 goto fail;
4197 printf("ninth delete on close test succeeded.\n");
4199 status = cli_ntcreate(cli1, fname, 0,
4200 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4201 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4202 FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
4203 0, &fnum1);
4204 if (!NT_STATUS_IS_OK(status)) {
4205 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
4206 correct = False;
4207 goto fail;
4210 /* This should delete the file. */
4211 status = cli_close(cli1, fnum1);
4212 if (!NT_STATUS_IS_OK(status)) {
4213 printf("[10] close failed (%s)\n", nt_errstr(status));
4214 correct = False;
4215 goto fail;
4218 /* This should fail.. */
4219 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
4220 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
4221 goto fail;
4222 correct = False;
4223 } else
4224 printf("tenth delete on close test succeeded.\n");
4226 cli_setatr(cli1, fname, 0, 0);
4227 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4229 /* What error do we get when attempting to open a read-only file with
4230 delete access ? */
4232 /* Create a readonly file. */
4233 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4234 FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
4235 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4236 if (!NT_STATUS_IS_OK(status)) {
4237 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
4238 correct = False;
4239 goto fail;
4242 status = cli_close(cli1, fnum1);
4243 if (!NT_STATUS_IS_OK(status)) {
4244 printf("[11] close failed (%s)\n", nt_errstr(status));
4245 correct = False;
4246 goto fail;
4249 /* Now try open for delete access. */
4250 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES|DELETE_ACCESS,
4251 0, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4252 FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4253 printf("[11] open of %s succeeded should have been denied with ACCESS_DENIED!\n", fname);
4254 cli_close(cli1, fnum1);
4255 goto fail;
4256 correct = False;
4257 } else {
4258 NTSTATUS nterr = cli_nt_error(cli1);
4259 if (!NT_STATUS_EQUAL(nterr,NT_STATUS_ACCESS_DENIED)) {
4260 printf("[11] open of %s should have been denied with ACCESS_DENIED! Got error %s\n", fname, nt_errstr(nterr));
4261 goto fail;
4262 correct = False;
4263 } else {
4264 printf("eleventh delete on close test succeeded.\n");
4268 printf("finished delete test\n");
4270 fail:
4271 /* FIXME: This will crash if we aborted before cli2 got
4272 * intialized, because these functions don't handle
4273 * uninitialized connections. */
4275 if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
4276 if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
4277 cli_setatr(cli1, fname, 0, 0);
4278 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4280 if (cli1 && !torture_close_connection(cli1)) {
4281 correct = False;
4283 if (cli2 && !torture_close_connection(cli2)) {
4284 correct = False;
4286 return correct;
4289 static bool run_deletetest_ln(int dummy)
4291 struct cli_state *cli;
4292 const char *fname = "\\delete1";
4293 const char *fname_ln = "\\delete1_ln";
4294 uint16_t fnum;
4295 uint16_t fnum1;
4296 NTSTATUS status;
4297 bool correct = true;
4298 time_t t;
4300 printf("starting deletetest-ln\n");
4302 if (!torture_open_connection(&cli, 0)) {
4303 return false;
4306 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4307 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4309 cli_sockopt(cli, sockops);
4311 /* Create the file. */
4312 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
4313 if (!NT_STATUS_IS_OK(status)) {
4314 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4315 return false;
4318 status = cli_close(cli, fnum);
4319 if (!NT_STATUS_IS_OK(status)) {
4320 printf("close1 failed (%s)\n", nt_errstr(status));
4321 return false;
4324 /* Now create a hardlink. */
4325 status = cli_nt_hardlink(cli, fname, fname_ln);
4326 if (!NT_STATUS_IS_OK(status)) {
4327 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4328 return false;
4331 /* Open the original file. */
4332 status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
4333 FILE_ATTRIBUTE_NORMAL,
4334 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4335 FILE_OPEN_IF, 0, 0, &fnum);
4336 if (!NT_STATUS_IS_OK(status)) {
4337 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
4338 return false;
4341 /* Unlink the hard link path. */
4342 status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
4343 FILE_ATTRIBUTE_NORMAL,
4344 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4345 FILE_OPEN_IF, 0, 0, &fnum1);
4346 if (!NT_STATUS_IS_OK(status)) {
4347 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
4348 return false;
4350 status = cli_nt_delete_on_close(cli, fnum1, true);
4351 if (!NT_STATUS_IS_OK(status)) {
4352 d_printf("(%s) failed to set delete_on_close %s: %s\n",
4353 __location__, fname_ln, nt_errstr(status));
4354 return false;
4357 status = cli_close(cli, fnum1);
4358 if (!NT_STATUS_IS_OK(status)) {
4359 printf("close %s failed (%s)\n",
4360 fname_ln, nt_errstr(status));
4361 return false;
4364 status = cli_close(cli, fnum);
4365 if (!NT_STATUS_IS_OK(status)) {
4366 printf("close %s failed (%s)\n",
4367 fname, nt_errstr(status));
4368 return false;
4371 /* Ensure the original file is still there. */
4372 status = cli_getatr(cli, fname, NULL, NULL, &t);
4373 if (!NT_STATUS_IS_OK(status)) {
4374 printf("%s getatr on file %s failed (%s)\n",
4375 __location__,
4376 fname,
4377 nt_errstr(status));
4378 correct = False;
4381 /* Ensure the link path is gone. */
4382 status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
4383 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4384 printf("%s, getatr for file %s returned wrong error code %s "
4385 "- should have been deleted\n",
4386 __location__,
4387 fname_ln, nt_errstr(status));
4388 correct = False;
4391 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4392 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4394 if (!torture_close_connection(cli)) {
4395 correct = false;
4398 printf("finished deletetest-ln\n");
4400 return correct;
4404 print out server properties
4406 static bool run_properties(int dummy)
4408 struct cli_state *cli;
4409 bool correct = True;
4411 printf("starting properties test\n");
4413 ZERO_STRUCT(cli);
4415 if (!torture_open_connection(&cli, 0)) {
4416 return False;
4419 cli_sockopt(cli, sockops);
4421 d_printf("Capabilities 0x%08x\n", cli->capabilities);
4423 if (!torture_close_connection(cli)) {
4424 correct = False;
4427 return correct;
4432 /* FIRST_DESIRED_ACCESS 0xf019f */
4433 #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
4434 FILE_READ_EA| /* 0xf */ \
4435 FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
4436 FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
4437 DELETE_ACCESS|READ_CONTROL_ACCESS|\
4438 WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
4439 /* SECOND_DESIRED_ACCESS 0xe0080 */
4440 #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
4441 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4442 WRITE_OWNER_ACCESS /* 0xe0000 */
4444 #if 0
4445 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
4446 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4447 FILE_READ_DATA|\
4448 WRITE_OWNER_ACCESS /* */
4449 #endif
4452 Test ntcreate calls made by xcopy
4454 static bool run_xcopy(int dummy)
4456 static struct cli_state *cli1;
4457 const char *fname = "\\test.txt";
4458 bool correct = True;
4459 uint16_t fnum1, fnum2;
4460 NTSTATUS status;
4462 printf("starting xcopy test\n");
4464 if (!torture_open_connection(&cli1, 0)) {
4465 return False;
4468 status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
4469 FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
4470 FILE_OVERWRITE_IF, 0x4044, 0, &fnum1);
4471 if (!NT_STATUS_IS_OK(status)) {
4472 printf("First open failed - %s\n", nt_errstr(status));
4473 return False;
4476 status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
4477 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4478 FILE_OPEN, 0x200000, 0, &fnum2);
4479 if (!NT_STATUS_IS_OK(status)) {
4480 printf("second open failed - %s\n", nt_errstr(status));
4481 return False;
4484 if (!torture_close_connection(cli1)) {
4485 correct = False;
4488 return correct;
4492 Test rename on files open with share delete and no share delete.
4494 static bool run_rename(int dummy)
4496 static struct cli_state *cli1;
4497 const char *fname = "\\test.txt";
4498 const char *fname1 = "\\test1.txt";
4499 bool correct = True;
4500 uint16_t fnum1;
4501 uint16_t attr;
4502 NTSTATUS status;
4504 printf("starting rename test\n");
4506 if (!torture_open_connection(&cli1, 0)) {
4507 return False;
4510 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4511 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4513 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4514 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
4515 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4516 if (!NT_STATUS_IS_OK(status)) {
4517 printf("First open failed - %s\n", nt_errstr(status));
4518 return False;
4521 status = cli_rename(cli1, fname, fname1);
4522 if (!NT_STATUS_IS_OK(status)) {
4523 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
4524 } else {
4525 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
4526 correct = False;
4529 status = cli_close(cli1, fnum1);
4530 if (!NT_STATUS_IS_OK(status)) {
4531 printf("close - 1 failed (%s)\n", nt_errstr(status));
4532 return False;
4535 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4536 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4537 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4538 #if 0
4539 FILE_SHARE_DELETE|FILE_SHARE_NONE,
4540 #else
4541 FILE_SHARE_DELETE|FILE_SHARE_READ,
4542 #endif
4543 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4544 if (!NT_STATUS_IS_OK(status)) {
4545 printf("Second open failed - %s\n", nt_errstr(status));
4546 return False;
4549 status = cli_rename(cli1, fname, fname1);
4550 if (!NT_STATUS_IS_OK(status)) {
4551 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
4552 correct = False;
4553 } else {
4554 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
4557 status = cli_close(cli1, fnum1);
4558 if (!NT_STATUS_IS_OK(status)) {
4559 printf("close - 2 failed (%s)\n", nt_errstr(status));
4560 return False;
4563 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4564 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4566 status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
4567 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4568 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4569 if (!NT_STATUS_IS_OK(status)) {
4570 printf("Third open failed - %s\n", nt_errstr(status));
4571 return False;
4575 #if 0
4577 uint16_t fnum2;
4579 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
4580 FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4581 printf("Fourth open failed - %s\n", cli_errstr(cli1));
4582 return False;
4584 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum2, true))) {
4585 printf("[8] setting delete_on_close on file failed !\n");
4586 return False;
4589 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
4590 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
4591 return False;
4594 #endif
4596 status = cli_rename(cli1, fname, fname1);
4597 if (!NT_STATUS_IS_OK(status)) {
4598 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
4599 correct = False;
4600 } else {
4601 printf("Third rename succeeded (SHARE_NONE)\n");
4604 status = cli_close(cli1, fnum1);
4605 if (!NT_STATUS_IS_OK(status)) {
4606 printf("close - 3 failed (%s)\n", nt_errstr(status));
4607 return False;
4610 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4611 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4613 /*----*/
4615 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4616 FILE_ATTRIBUTE_NORMAL,
4617 FILE_SHARE_READ | FILE_SHARE_WRITE,
4618 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4619 if (!NT_STATUS_IS_OK(status)) {
4620 printf("Fourth open failed - %s\n", nt_errstr(status));
4621 return False;
4624 status = cli_rename(cli1, fname, fname1);
4625 if (!NT_STATUS_IS_OK(status)) {
4626 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
4627 } else {
4628 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
4629 correct = False;
4632 status = cli_close(cli1, fnum1);
4633 if (!NT_STATUS_IS_OK(status)) {
4634 printf("close - 4 failed (%s)\n", nt_errstr(status));
4635 return False;
4638 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4639 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4641 /*--*/
4643 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4644 FILE_ATTRIBUTE_NORMAL,
4645 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4646 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4647 if (!NT_STATUS_IS_OK(status)) {
4648 printf("Fifth open failed - %s\n", nt_errstr(status));
4649 return False;
4652 status = cli_rename(cli1, fname, fname1);
4653 if (!NT_STATUS_IS_OK(status)) {
4654 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
4655 correct = False;
4656 } else {
4657 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
4661 * Now check if the first name still exists ...
4664 /* if (!NT_STATUS_OP(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4665 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4666 printf("Opening original file after rename of open file fails: %s\n",
4667 cli_errstr(cli1));
4669 else {
4670 printf("Opening original file after rename of open file works ...\n");
4671 (void)cli_close(cli1, fnum2);
4672 } */
4674 /*--*/
4675 status = cli_close(cli1, fnum1);
4676 if (!NT_STATUS_IS_OK(status)) {
4677 printf("close - 5 failed (%s)\n", nt_errstr(status));
4678 return False;
4681 /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
4682 status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
4683 if (!NT_STATUS_IS_OK(status)) {
4684 printf("getatr on file %s failed - %s ! \n",
4685 fname1, nt_errstr(status));
4686 correct = False;
4687 } else {
4688 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
4689 printf("Renamed file %s has wrong attr 0x%x "
4690 "(should be 0x%x)\n",
4691 fname1,
4692 attr,
4693 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
4694 correct = False;
4695 } else {
4696 printf("Renamed file %s has archive bit set\n", fname1);
4700 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4701 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4703 if (!torture_close_connection(cli1)) {
4704 correct = False;
4707 return correct;
4710 static bool run_pipe_number(int dummy)
4712 struct cli_state *cli1;
4713 const char *pipe_name = "\\SPOOLSS";
4714 uint16_t fnum;
4715 int num_pipes = 0;
4716 NTSTATUS status;
4718 printf("starting pipenumber test\n");
4719 if (!torture_open_connection(&cli1, 0)) {
4720 return False;
4723 cli_sockopt(cli1, sockops);
4724 while(1) {
4725 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
4726 FILE_ATTRIBUTE_NORMAL,
4727 FILE_SHARE_READ|FILE_SHARE_WRITE,
4728 FILE_OPEN_IF, 0, 0, &fnum);
4729 if (!NT_STATUS_IS_OK(status)) {
4730 printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
4731 break;
4733 num_pipes++;
4734 printf("\r%6d", num_pipes);
4737 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
4738 torture_close_connection(cli1);
4739 return True;
4743 Test open mode returns on read-only files.
4745 static bool run_opentest(int dummy)
4747 static struct cli_state *cli1;
4748 static struct cli_state *cli2;
4749 const char *fname = "\\readonly.file";
4750 uint16_t fnum1, fnum2;
4751 char buf[20];
4752 SMB_OFF_T fsize;
4753 bool correct = True;
4754 char *tmp_path;
4755 NTSTATUS status;
4757 printf("starting open test\n");
4759 if (!torture_open_connection(&cli1, 0)) {
4760 return False;
4763 cli_setatr(cli1, fname, 0, 0);
4764 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4766 cli_sockopt(cli1, sockops);
4768 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4769 if (!NT_STATUS_IS_OK(status)) {
4770 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4771 return False;
4774 status = cli_close(cli1, fnum1);
4775 if (!NT_STATUS_IS_OK(status)) {
4776 printf("close2 failed (%s)\n", nt_errstr(status));
4777 return False;
4780 status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
4781 if (!NT_STATUS_IS_OK(status)) {
4782 printf("cli_setatr failed (%s)\n", nt_errstr(status));
4783 return False;
4786 status = cli_open(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4787 if (!NT_STATUS_IS_OK(status)) {
4788 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4789 return False;
4792 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
4793 cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4795 if (check_error(__LINE__, cli1, ERRDOS, ERRnoaccess,
4796 NT_STATUS_ACCESS_DENIED)) {
4797 printf("correct error code ERRDOS/ERRnoaccess returned\n");
4800 printf("finished open test 1\n");
4802 cli_close(cli1, fnum1);
4804 /* Now try not readonly and ensure ERRbadshare is returned. */
4806 cli_setatr(cli1, fname, 0, 0);
4808 status = cli_open(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4809 if (!NT_STATUS_IS_OK(status)) {
4810 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4811 return False;
4814 /* This will fail - but the error should be ERRshare. */
4815 cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4817 if (check_error(__LINE__, cli1, ERRDOS, ERRbadshare,
4818 NT_STATUS_SHARING_VIOLATION)) {
4819 printf("correct error code ERRDOS/ERRbadshare returned\n");
4822 status = cli_close(cli1, fnum1);
4823 if (!NT_STATUS_IS_OK(status)) {
4824 printf("close2 failed (%s)\n", nt_errstr(status));
4825 return False;
4828 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4830 printf("finished open test 2\n");
4832 /* Test truncate open disposition on file opened for read. */
4833 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4834 if (!NT_STATUS_IS_OK(status)) {
4835 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
4836 return False;
4839 /* write 20 bytes. */
4841 memset(buf, '\0', 20);
4843 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
4844 if (!NT_STATUS_IS_OK(status)) {
4845 printf("write failed (%s)\n", nt_errstr(status));
4846 correct = False;
4849 status = cli_close(cli1, fnum1);
4850 if (!NT_STATUS_IS_OK(status)) {
4851 printf("(3) close1 failed (%s)\n", nt_errstr(status));
4852 return False;
4855 /* Ensure size == 20. */
4856 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
4857 if (!NT_STATUS_IS_OK(status)) {
4858 printf("(3) getatr failed (%s)\n", nt_errstr(status));
4859 return False;
4862 if (fsize != 20) {
4863 printf("(3) file size != 20\n");
4864 return False;
4867 /* Now test if we can truncate a file opened for readonly. */
4868 status = cli_open(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
4869 if (!NT_STATUS_IS_OK(status)) {
4870 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
4871 return False;
4874 status = cli_close(cli1, fnum1);
4875 if (!NT_STATUS_IS_OK(status)) {
4876 printf("close2 failed (%s)\n", nt_errstr(status));
4877 return False;
4880 /* Ensure size == 0. */
4881 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
4882 if (!NT_STATUS_IS_OK(status)) {
4883 printf("(3) getatr failed (%s)\n", nt_errstr(status));
4884 return False;
4887 if (fsize != 0) {
4888 printf("(3) file size != 0\n");
4889 return False;
4891 printf("finished open test 3\n");
4893 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4895 printf("Do ctemp tests\n");
4896 status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
4897 if (!NT_STATUS_IS_OK(status)) {
4898 printf("ctemp failed (%s)\n", nt_errstr(status));
4899 return False;
4902 printf("ctemp gave path %s\n", tmp_path);
4903 status = cli_close(cli1, fnum1);
4904 if (!NT_STATUS_IS_OK(status)) {
4905 printf("close of temp failed (%s)\n", nt_errstr(status));
4908 status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4909 if (!NT_STATUS_IS_OK(status)) {
4910 printf("unlink of temp failed (%s)\n", nt_errstr(status));
4913 /* Test the non-io opens... */
4915 if (!torture_open_connection(&cli2, 1)) {
4916 return False;
4919 cli_setatr(cli2, fname, 0, 0);
4920 cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4922 cli_sockopt(cli2, sockops);
4924 printf("TEST #1 testing 2 non-io opens (no delete)\n");
4925 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
4926 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4927 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4928 if (!NT_STATUS_IS_OK(status)) {
4929 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4930 return False;
4933 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
4934 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4935 FILE_OPEN_IF, 0, 0, &fnum2);
4936 if (!NT_STATUS_IS_OK(status)) {
4937 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4938 return False;
4941 status = cli_close(cli1, fnum1);
4942 if (!NT_STATUS_IS_OK(status)) {
4943 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
4944 return False;
4947 status = cli_close(cli2, fnum2);
4948 if (!NT_STATUS_IS_OK(status)) {
4949 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
4950 return False;
4953 printf("non-io open test #1 passed.\n");
4955 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4957 printf("TEST #2 testing 2 non-io opens (first with delete)\n");
4959 status = cli_ntcreate(cli1, fname, 0,
4960 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
4961 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4962 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4963 if (!NT_STATUS_IS_OK(status)) {
4964 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4965 return False;
4968 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
4969 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4970 FILE_OPEN_IF, 0, 0, &fnum2);
4971 if (!NT_STATUS_IS_OK(status)) {
4972 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4973 return False;
4976 status = cli_close(cli1, fnum1);
4977 if (!NT_STATUS_IS_OK(status)) {
4978 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
4979 return False;
4982 status = cli_close(cli2, fnum2);
4983 if (!NT_STATUS_IS_OK(status)) {
4984 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
4985 return False;
4988 printf("non-io open test #2 passed.\n");
4990 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4992 printf("TEST #3 testing 2 non-io opens (second with delete)\n");
4994 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
4995 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4996 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4997 if (!NT_STATUS_IS_OK(status)) {
4998 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4999 return False;
5002 status = cli_ntcreate(cli2, fname, 0,
5003 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5004 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5005 FILE_OPEN_IF, 0, 0, &fnum2);
5006 if (!NT_STATUS_IS_OK(status)) {
5007 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5008 return False;
5011 status = cli_close(cli1, fnum1);
5012 if (!NT_STATUS_IS_OK(status)) {
5013 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5014 return False;
5017 status = cli_close(cli2, fnum2);
5018 if (!NT_STATUS_IS_OK(status)) {
5019 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5020 return False;
5023 printf("non-io open test #3 passed.\n");
5025 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5027 printf("TEST #4 testing 2 non-io opens (both with delete)\n");
5029 status = cli_ntcreate(cli1, fname, 0,
5030 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5031 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5032 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5033 if (!NT_STATUS_IS_OK(status)) {
5034 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5035 return False;
5038 status = cli_ntcreate(cli2, fname, 0,
5039 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5040 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5041 FILE_OPEN_IF, 0, 0, &fnum2);
5042 if (NT_STATUS_IS_OK(status)) {
5043 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5044 return False;
5047 printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5049 status = cli_close(cli1, fnum1);
5050 if (!NT_STATUS_IS_OK(status)) {
5051 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5052 return False;
5055 printf("non-io open test #4 passed.\n");
5057 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5059 printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
5061 status = cli_ntcreate(cli1, fname, 0,
5062 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5063 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5064 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5065 if (!NT_STATUS_IS_OK(status)) {
5066 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5067 return False;
5070 status = cli_ntcreate(cli2, fname, 0,
5071 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5072 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5073 FILE_OPEN_IF, 0, 0, &fnum2);
5074 if (!NT_STATUS_IS_OK(status)) {
5075 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5076 return False;
5079 status = cli_close(cli1, fnum1);
5080 if (!NT_STATUS_IS_OK(status)) {
5081 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5082 return False;
5085 status = cli_close(cli2, fnum2);
5086 if (!NT_STATUS_IS_OK(status)) {
5087 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5088 return False;
5091 printf("non-io open test #5 passed.\n");
5093 printf("TEST #6 testing 1 non-io open, one io open\n");
5095 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5097 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5098 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5099 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5100 if (!NT_STATUS_IS_OK(status)) {
5101 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5102 return False;
5105 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5106 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
5107 FILE_OPEN_IF, 0, 0, &fnum2);
5108 if (!NT_STATUS_IS_OK(status)) {
5109 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5110 return False;
5113 status = cli_close(cli1, fnum1);
5114 if (!NT_STATUS_IS_OK(status)) {
5115 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5116 return False;
5119 status = cli_close(cli2, fnum2);
5120 if (!NT_STATUS_IS_OK(status)) {
5121 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5122 return False;
5125 printf("non-io open test #6 passed.\n");
5127 printf("TEST #7 testing 1 non-io open, one io open with delete\n");
5129 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5131 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5132 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5133 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5134 if (!NT_STATUS_IS_OK(status)) {
5135 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5136 return False;
5139 status = cli_ntcreate(cli2, fname, 0,
5140 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5141 FILE_ATTRIBUTE_NORMAL,
5142 FILE_SHARE_READ|FILE_SHARE_DELETE,
5143 FILE_OPEN_IF, 0, 0, &fnum2);
5144 if (NT_STATUS_IS_OK(status)) {
5145 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5146 return False;
5149 printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5151 status = cli_close(cli1, fnum1);
5152 if (!NT_STATUS_IS_OK(status)) {
5153 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5154 return False;
5157 printf("non-io open test #7 passed.\n");
5159 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5161 printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
5162 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
5163 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5164 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5165 if (!NT_STATUS_IS_OK(status)) {
5166 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
5167 correct = false;
5168 goto out;
5171 /* Write to ensure we have to update the file time. */
5172 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5173 NULL);
5174 if (!NT_STATUS_IS_OK(status)) {
5175 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
5176 correct = false;
5177 goto out;
5180 status = cli_close(cli1, fnum1);
5181 if (!NT_STATUS_IS_OK(status)) {
5182 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
5183 correct = false;
5186 out:
5188 if (!torture_close_connection(cli1)) {
5189 correct = False;
5191 if (!torture_close_connection(cli2)) {
5192 correct = False;
5195 return correct;
5198 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
5200 uint16 major, minor;
5201 uint32 caplow, caphigh;
5202 NTSTATUS status;
5204 if (!SERVER_HAS_UNIX_CIFS(cli)) {
5205 printf("Server doesn't support UNIX CIFS extensions.\n");
5206 return NT_STATUS_NOT_SUPPORTED;
5209 status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
5210 &caphigh);
5211 if (!NT_STATUS_IS_OK(status)) {
5212 printf("Server didn't return UNIX CIFS extensions: %s\n",
5213 nt_errstr(status));
5214 return status;
5217 status = cli_set_unix_extensions_capabilities(cli, major, minor,
5218 caplow, caphigh);
5219 if (!NT_STATUS_IS_OK(status)) {
5220 printf("Server doesn't support setting UNIX CIFS extensions: "
5221 "%s.\n", nt_errstr(status));
5222 return status;
5225 return NT_STATUS_OK;
5229 Test POSIX open /mkdir calls.
5231 static bool run_simple_posix_open_test(int dummy)
5233 static struct cli_state *cli1;
5234 const char *fname = "posix:file";
5235 const char *hname = "posix:hlink";
5236 const char *sname = "posix:symlink";
5237 const char *dname = "posix:dir";
5238 char buf[10];
5239 char namebuf[11];
5240 uint16_t fnum1 = (uint16_t)-1;
5241 SMB_STRUCT_STAT sbuf;
5242 bool correct = false;
5243 NTSTATUS status;
5245 printf("Starting simple POSIX open test\n");
5247 if (!torture_open_connection(&cli1, 0)) {
5248 return false;
5251 cli_sockopt(cli1, sockops);
5253 status = torture_setup_unix_extensions(cli1);
5254 if (!NT_STATUS_IS_OK(status)) {
5255 return false;
5258 cli_setatr(cli1, fname, 0, 0);
5259 cli_posix_unlink(cli1, fname);
5260 cli_setatr(cli1, dname, 0, 0);
5261 cli_posix_rmdir(cli1, dname);
5262 cli_setatr(cli1, hname, 0, 0);
5263 cli_posix_unlink(cli1, hname);
5264 cli_setatr(cli1, sname, 0, 0);
5265 cli_posix_unlink(cli1, sname);
5267 /* Create a directory. */
5268 status = cli_posix_mkdir(cli1, dname, 0777);
5269 if (!NT_STATUS_IS_OK(status)) {
5270 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
5271 goto out;
5274 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5275 0600, &fnum1);
5276 if (!NT_STATUS_IS_OK(status)) {
5277 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5278 goto out;
5281 /* Test ftruncate - set file size. */
5282 status = cli_ftruncate(cli1, fnum1, 1000);
5283 if (!NT_STATUS_IS_OK(status)) {
5284 printf("ftruncate failed (%s)\n", nt_errstr(status));
5285 goto out;
5288 /* Ensure st_size == 1000 */
5289 status = cli_posix_stat(cli1, fname, &sbuf);
5290 if (!NT_STATUS_IS_OK(status)) {
5291 printf("stat failed (%s)\n", nt_errstr(status));
5292 goto out;
5295 if (sbuf.st_ex_size != 1000) {
5296 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5297 goto out;
5300 /* Test ftruncate - set file size back to zero. */
5301 status = cli_ftruncate(cli1, fnum1, 0);
5302 if (!NT_STATUS_IS_OK(status)) {
5303 printf("ftruncate failed (%s)\n", nt_errstr(status));
5304 goto out;
5307 status = cli_close(cli1, fnum1);
5308 if (!NT_STATUS_IS_OK(status)) {
5309 printf("close failed (%s)\n", nt_errstr(status));
5310 goto out;
5313 /* Now open the file again for read only. */
5314 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5315 if (!NT_STATUS_IS_OK(status)) {
5316 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
5317 goto out;
5320 /* Now unlink while open. */
5321 status = cli_posix_unlink(cli1, fname);
5322 if (!NT_STATUS_IS_OK(status)) {
5323 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5324 goto out;
5327 status = cli_close(cli1, fnum1);
5328 if (!NT_STATUS_IS_OK(status)) {
5329 printf("close(2) failed (%s)\n", nt_errstr(status));
5330 goto out;
5333 /* Ensure the file has gone. */
5334 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5335 if (NT_STATUS_IS_OK(status)) {
5336 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
5337 goto out;
5340 /* Create again to test open with O_TRUNC. */
5341 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
5342 if (!NT_STATUS_IS_OK(status)) {
5343 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5344 goto out;
5347 /* Test ftruncate - set file size. */
5348 status = cli_ftruncate(cli1, fnum1, 1000);
5349 if (!NT_STATUS_IS_OK(status)) {
5350 printf("ftruncate failed (%s)\n", nt_errstr(status));
5351 goto out;
5354 /* Ensure st_size == 1000 */
5355 status = cli_posix_stat(cli1, fname, &sbuf);
5356 if (!NT_STATUS_IS_OK(status)) {
5357 printf("stat failed (%s)\n", nt_errstr(status));
5358 goto out;
5361 if (sbuf.st_ex_size != 1000) {
5362 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5363 goto out;
5366 status = cli_close(cli1, fnum1);
5367 if (!NT_STATUS_IS_OK(status)) {
5368 printf("close(2) failed (%s)\n", nt_errstr(status));
5369 goto out;
5372 /* Re-open with O_TRUNC. */
5373 status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
5374 if (!NT_STATUS_IS_OK(status)) {
5375 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5376 goto out;
5379 /* Ensure st_size == 0 */
5380 status = cli_posix_stat(cli1, fname, &sbuf);
5381 if (!NT_STATUS_IS_OK(status)) {
5382 printf("stat failed (%s)\n", nt_errstr(status));
5383 goto out;
5386 if (sbuf.st_ex_size != 0) {
5387 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
5388 goto out;
5391 status = cli_close(cli1, fnum1);
5392 if (!NT_STATUS_IS_OK(status)) {
5393 printf("close failed (%s)\n", nt_errstr(status));
5394 goto out;
5397 status = cli_posix_unlink(cli1, fname);
5398 if (!NT_STATUS_IS_OK(status)) {
5399 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5400 goto out;
5403 status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
5404 if (!NT_STATUS_IS_OK(status)) {
5405 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
5406 dname, nt_errstr(status));
5407 goto out;
5410 cli_close(cli1, fnum1);
5412 /* What happens when we try and POSIX open a directory for write ? */
5413 status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
5414 if (NT_STATUS_IS_OK(status)) {
5415 printf("POSIX open of directory %s succeeded, should have failed.\n", fname);
5416 goto out;
5417 } else {
5418 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
5419 NT_STATUS_FILE_IS_A_DIRECTORY)) {
5420 goto out;
5424 /* Create the file. */
5425 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5426 0600, &fnum1);
5427 if (!NT_STATUS_IS_OK(status)) {
5428 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5429 goto out;
5432 /* Write some data into it. */
5433 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5434 NULL);
5435 if (!NT_STATUS_IS_OK(status)) {
5436 printf("cli_write failed: %s\n", nt_errstr(status));
5437 goto out;
5440 cli_close(cli1, fnum1);
5442 /* Now create a hardlink. */
5443 status = cli_posix_hardlink(cli1, fname, hname);
5444 if (!NT_STATUS_IS_OK(status)) {
5445 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
5446 goto out;
5449 /* Now create a symlink. */
5450 status = cli_posix_symlink(cli1, fname, sname);
5451 if (!NT_STATUS_IS_OK(status)) {
5452 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
5453 goto out;
5456 /* Open the hardlink for read. */
5457 status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
5458 if (!NT_STATUS_IS_OK(status)) {
5459 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
5460 goto out;
5463 if (cli_read(cli1, fnum1, buf, 0, 10) != 10) {
5464 printf("POSIX read of %s failed (%s)\n", hname, cli_errstr(cli1));
5465 goto out;
5468 if (memcmp(buf, "TEST DATA\n", 10)) {
5469 printf("invalid data read from hardlink\n");
5470 goto out;
5473 /* Do a POSIX lock/unlock. */
5474 status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
5475 if (!NT_STATUS_IS_OK(status)) {
5476 printf("POSIX lock failed %s\n", nt_errstr(status));
5477 goto out;
5480 /* Punch a hole in the locked area. */
5481 status = cli_posix_unlock(cli1, fnum1, 10, 80);
5482 if (!NT_STATUS_IS_OK(status)) {
5483 printf("POSIX unlock failed %s\n", nt_errstr(status));
5484 goto out;
5487 cli_close(cli1, fnum1);
5489 /* Open the symlink for read - this should fail. A POSIX
5490 client should not be doing opens on a symlink. */
5491 status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
5492 if (NT_STATUS_IS_OK(status)) {
5493 printf("POSIX open of %s succeeded (should have failed)\n", sname);
5494 goto out;
5495 } else {
5496 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
5497 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
5498 printf("POSIX open of %s should have failed "
5499 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
5500 "failed with %s instead.\n",
5501 sname, nt_errstr(status));
5502 goto out;
5506 status = cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf));
5507 if (!NT_STATUS_IS_OK(status)) {
5508 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
5509 goto out;
5512 if (strcmp(namebuf, fname) != 0) {
5513 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
5514 sname, fname, namebuf);
5515 goto out;
5518 status = cli_posix_rmdir(cli1, dname);
5519 if (!NT_STATUS_IS_OK(status)) {
5520 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
5521 goto out;
5524 printf("Simple POSIX open test passed\n");
5525 correct = true;
5527 out:
5529 if (fnum1 != (uint16_t)-1) {
5530 cli_close(cli1, fnum1);
5531 fnum1 = (uint16_t)-1;
5534 cli_setatr(cli1, sname, 0, 0);
5535 cli_posix_unlink(cli1, sname);
5536 cli_setatr(cli1, hname, 0, 0);
5537 cli_posix_unlink(cli1, hname);
5538 cli_setatr(cli1, fname, 0, 0);
5539 cli_posix_unlink(cli1, fname);
5540 cli_setatr(cli1, dname, 0, 0);
5541 cli_posix_rmdir(cli1, dname);
5543 if (!torture_close_connection(cli1)) {
5544 correct = false;
5547 return correct;
5551 static uint32 open_attrs_table[] = {
5552 FILE_ATTRIBUTE_NORMAL,
5553 FILE_ATTRIBUTE_ARCHIVE,
5554 FILE_ATTRIBUTE_READONLY,
5555 FILE_ATTRIBUTE_HIDDEN,
5556 FILE_ATTRIBUTE_SYSTEM,
5558 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
5559 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
5560 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
5561 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5562 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5563 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5565 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5566 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5567 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5568 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
5571 struct trunc_open_results {
5572 unsigned int num;
5573 uint32 init_attr;
5574 uint32 trunc_attr;
5575 uint32 result_attr;
5578 static struct trunc_open_results attr_results[] = {
5579 { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5580 { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5581 { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5582 { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5583 { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5584 { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5585 { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5586 { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5587 { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5588 { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5589 { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5590 { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
5591 { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5592 { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5593 { 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 },
5594 { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5595 { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5596 { 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 },
5597 { 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 },
5598 { 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 },
5599 { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5600 { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5601 { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5602 { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5603 { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5604 { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
5607 static bool run_openattrtest(int dummy)
5609 static struct cli_state *cli1;
5610 const char *fname = "\\openattr.file";
5611 uint16_t fnum1;
5612 bool correct = True;
5613 uint16 attr;
5614 unsigned int i, j, k, l;
5615 NTSTATUS status;
5617 printf("starting open attr test\n");
5619 if (!torture_open_connection(&cli1, 0)) {
5620 return False;
5623 cli_sockopt(cli1, sockops);
5625 for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32); i++) {
5626 cli_setatr(cli1, fname, 0, 0);
5627 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5629 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
5630 open_attrs_table[i], FILE_SHARE_NONE,
5631 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5632 if (!NT_STATUS_IS_OK(status)) {
5633 printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5634 return False;
5637 status = cli_close(cli1, fnum1);
5638 if (!NT_STATUS_IS_OK(status)) {
5639 printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5640 return False;
5643 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32); j++) {
5644 status = cli_ntcreate(cli1, fname, 0,
5645 FILE_READ_DATA|FILE_WRITE_DATA,
5646 open_attrs_table[j],
5647 FILE_SHARE_NONE, FILE_OVERWRITE,
5648 0, 0, &fnum1);
5649 if (!NT_STATUS_IS_OK(status)) {
5650 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5651 if (attr_results[l].num == k) {
5652 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
5653 k, open_attrs_table[i],
5654 open_attrs_table[j],
5655 fname, NT_STATUS_V(status), nt_errstr(status));
5656 correct = False;
5660 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5661 printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
5662 k, open_attrs_table[i], open_attrs_table[j],
5663 nt_errstr(status));
5664 correct = False;
5666 #if 0
5667 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
5668 #endif
5669 k++;
5670 continue;
5673 status = cli_close(cli1, fnum1);
5674 if (!NT_STATUS_IS_OK(status)) {
5675 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
5676 return False;
5679 status = cli_getatr(cli1, fname, &attr, NULL, NULL);
5680 if (!NT_STATUS_IS_OK(status)) {
5681 printf("getatr(2) failed (%s)\n", nt_errstr(status));
5682 return False;
5685 #if 0
5686 printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
5687 k, open_attrs_table[i], open_attrs_table[j], attr );
5688 #endif
5690 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5691 if (attr_results[l].num == k) {
5692 if (attr != attr_results[l].result_attr ||
5693 open_attrs_table[i] != attr_results[l].init_attr ||
5694 open_attrs_table[j] != attr_results[l].trunc_attr) {
5695 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
5696 open_attrs_table[i],
5697 open_attrs_table[j],
5698 (unsigned int)attr,
5699 attr_results[l].result_attr);
5700 correct = False;
5702 break;
5705 k++;
5709 cli_setatr(cli1, fname, 0, 0);
5710 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5712 printf("open attr test %s.\n", correct ? "passed" : "failed");
5714 if (!torture_close_connection(cli1)) {
5715 correct = False;
5717 return correct;
5720 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
5721 const char *name, void *state)
5723 int *matched = (int *)state;
5724 if (matched != NULL) {
5725 *matched += 1;
5727 return NT_STATUS_OK;
5731 test directory listing speed
5733 static bool run_dirtest(int dummy)
5735 int i;
5736 static struct cli_state *cli;
5737 uint16_t fnum;
5738 struct timeval core_start;
5739 bool correct = True;
5740 int matched;
5742 printf("starting directory test\n");
5744 if (!torture_open_connection(&cli, 0)) {
5745 return False;
5748 cli_sockopt(cli, sockops);
5750 srandom(0);
5751 for (i=0;i<torture_numops;i++) {
5752 fstring fname;
5753 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5754 if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
5755 fprintf(stderr,"Failed to open %s\n", fname);
5756 return False;
5758 cli_close(cli, fnum);
5761 core_start = timeval_current();
5763 matched = 0;
5764 cli_list(cli, "a*.*", 0, list_fn, &matched);
5765 printf("Matched %d\n", matched);
5767 matched = 0;
5768 cli_list(cli, "b*.*", 0, list_fn, &matched);
5769 printf("Matched %d\n", matched);
5771 matched = 0;
5772 cli_list(cli, "xyzabc", 0, list_fn, &matched);
5773 printf("Matched %d\n", matched);
5775 printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
5777 srandom(0);
5778 for (i=0;i<torture_numops;i++) {
5779 fstring fname;
5780 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5781 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5784 if (!torture_close_connection(cli)) {
5785 correct = False;
5788 printf("finished dirtest\n");
5790 return correct;
5793 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
5794 void *state)
5796 struct cli_state *pcli = (struct cli_state *)state;
5797 fstring fname;
5798 slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
5800 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
5801 return NT_STATUS_OK;
5803 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
5804 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
5805 printf("del_fn: failed to rmdir %s\n,", fname );
5806 } else {
5807 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
5808 printf("del_fn: failed to unlink %s\n,", fname );
5810 return NT_STATUS_OK;
5815 sees what IOCTLs are supported
5817 bool torture_ioctl_test(int dummy)
5819 static struct cli_state *cli;
5820 uint16_t device, function;
5821 uint16_t fnum;
5822 const char *fname = "\\ioctl.dat";
5823 DATA_BLOB blob;
5824 NTSTATUS status;
5826 if (!torture_open_connection(&cli, 0)) {
5827 return False;
5830 printf("starting ioctl test\n");
5832 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5834 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5835 if (!NT_STATUS_IS_OK(status)) {
5836 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5837 return False;
5840 status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
5841 printf("ioctl device info: %s\n", nt_errstr(status));
5843 status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
5844 printf("ioctl job info: %s\n", nt_errstr(status));
5846 for (device=0;device<0x100;device++) {
5847 printf("ioctl test with device = 0x%x\n", device);
5848 for (function=0;function<0x100;function++) {
5849 uint32 code = (device<<16) | function;
5851 status = cli_raw_ioctl(cli, fnum, code, &blob);
5853 if (NT_STATUS_IS_OK(status)) {
5854 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
5855 (int)blob.length);
5856 data_blob_free(&blob);
5861 if (!torture_close_connection(cli)) {
5862 return False;
5865 return True;
5870 tries varients of chkpath
5872 bool torture_chkpath_test(int dummy)
5874 static struct cli_state *cli;
5875 uint16_t fnum;
5876 bool ret;
5877 NTSTATUS status;
5879 if (!torture_open_connection(&cli, 0)) {
5880 return False;
5883 printf("starting chkpath test\n");
5885 /* cleanup from an old run */
5886 cli_rmdir(cli, "\\chkpath.dir\\dir2");
5887 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5888 cli_rmdir(cli, "\\chkpath.dir");
5890 status = cli_mkdir(cli, "\\chkpath.dir");
5891 if (!NT_STATUS_IS_OK(status)) {
5892 printf("mkdir1 failed : %s\n", nt_errstr(status));
5893 return False;
5896 status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
5897 if (!NT_STATUS_IS_OK(status)) {
5898 printf("mkdir2 failed : %s\n", nt_errstr(status));
5899 return False;
5902 status = cli_open(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
5903 DENY_NONE, &fnum);
5904 if (!NT_STATUS_IS_OK(status)) {
5905 printf("open1 failed (%s)\n", nt_errstr(status));
5906 return False;
5908 cli_close(cli, fnum);
5910 status = cli_chkpath(cli, "\\chkpath.dir");
5911 if (!NT_STATUS_IS_OK(status)) {
5912 printf("chkpath1 failed: %s\n", nt_errstr(status));
5913 ret = False;
5916 status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
5917 if (!NT_STATUS_IS_OK(status)) {
5918 printf("chkpath2 failed: %s\n", nt_errstr(status));
5919 ret = False;
5922 status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
5923 if (!NT_STATUS_IS_OK(status)) {
5924 ret = check_error(__LINE__, cli, ERRDOS, ERRbadpath,
5925 NT_STATUS_NOT_A_DIRECTORY);
5926 } else {
5927 printf("* chkpath on a file should fail\n");
5928 ret = False;
5931 if (!NT_STATUS_IS_OK(cli_chkpath(cli, "\\chkpath.dir\\bar.txt"))) {
5932 ret = check_error(__LINE__, cli, ERRDOS, ERRbadfile,
5933 NT_STATUS_OBJECT_NAME_NOT_FOUND);
5934 } else {
5935 printf("* chkpath on a non existant file should fail\n");
5936 ret = False;
5939 if (!NT_STATUS_IS_OK(cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt"))) {
5940 ret = check_error(__LINE__, cli, ERRDOS, ERRbadpath,
5941 NT_STATUS_OBJECT_PATH_NOT_FOUND);
5942 } else {
5943 printf("* chkpath on a non existent component should fail\n");
5944 ret = False;
5947 cli_rmdir(cli, "\\chkpath.dir\\dir2");
5948 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5949 cli_rmdir(cli, "\\chkpath.dir");
5951 if (!torture_close_connection(cli)) {
5952 return False;
5955 return ret;
5958 static bool run_eatest(int dummy)
5960 static struct cli_state *cli;
5961 const char *fname = "\\eatest.txt";
5962 bool correct = True;
5963 uint16_t fnum;
5964 int i;
5965 size_t num_eas;
5966 struct ea_struct *ea_list = NULL;
5967 TALLOC_CTX *mem_ctx = talloc_init("eatest");
5968 NTSTATUS status;
5970 printf("starting eatest\n");
5972 if (!torture_open_connection(&cli, 0)) {
5973 talloc_destroy(mem_ctx);
5974 return False;
5977 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5979 status = cli_ntcreate(cli, fname, 0,
5980 FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
5981 FILE_SHARE_NONE, FILE_OVERWRITE_IF,
5982 0x4044, 0, &fnum);
5983 if (!NT_STATUS_IS_OK(status)) {
5984 printf("open failed - %s\n", nt_errstr(status));
5985 talloc_destroy(mem_ctx);
5986 return False;
5989 for (i = 0; i < 10; i++) {
5990 fstring ea_name, ea_val;
5992 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
5993 memset(ea_val, (char)i+1, i+1);
5994 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
5995 if (!NT_STATUS_IS_OK(status)) {
5996 printf("ea_set of name %s failed - %s\n", ea_name,
5997 nt_errstr(status));
5998 talloc_destroy(mem_ctx);
5999 return False;
6003 cli_close(cli, fnum);
6004 for (i = 0; i < 10; i++) {
6005 fstring ea_name, ea_val;
6007 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
6008 memset(ea_val, (char)i+1, i+1);
6009 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
6010 if (!NT_STATUS_IS_OK(status)) {
6011 printf("ea_set of name %s failed - %s\n", ea_name,
6012 nt_errstr(status));
6013 talloc_destroy(mem_ctx);
6014 return False;
6018 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6019 if (!NT_STATUS_IS_OK(status)) {
6020 printf("ea_get list failed - %s\n", nt_errstr(status));
6021 correct = False;
6024 printf("num_eas = %d\n", (int)num_eas);
6026 if (num_eas != 20) {
6027 printf("Should be 20 EA's stored... failing.\n");
6028 correct = False;
6031 for (i = 0; i < num_eas; i++) {
6032 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6033 dump_data(0, ea_list[i].value.data,
6034 ea_list[i].value.length);
6037 /* Setting EA's to zero length deletes them. Test this */
6038 printf("Now deleting all EA's - case indepenent....\n");
6040 #if 1
6041 cli_set_ea_path(cli, fname, "", "", 0);
6042 #else
6043 for (i = 0; i < 20; i++) {
6044 fstring ea_name;
6045 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
6046 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
6047 if (!NT_STATUS_IS_OK(status)) {
6048 printf("ea_set of name %s failed - %s\n", ea_name,
6049 nt_errstr(status));
6050 talloc_destroy(mem_ctx);
6051 return False;
6054 #endif
6056 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6057 if (!NT_STATUS_IS_OK(status)) {
6058 printf("ea_get list failed - %s\n", nt_errstr(status));
6059 correct = False;
6062 printf("num_eas = %d\n", (int)num_eas);
6063 for (i = 0; i < num_eas; i++) {
6064 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6065 dump_data(0, ea_list[i].value.data,
6066 ea_list[i].value.length);
6069 if (num_eas != 0) {
6070 printf("deleting EA's failed.\n");
6071 correct = False;
6074 /* Try and delete a non existant EA. */
6075 status = cli_set_ea_path(cli, fname, "foo", "", 0);
6076 if (!NT_STATUS_IS_OK(status)) {
6077 printf("deleting non-existant EA 'foo' should succeed. %s\n",
6078 nt_errstr(status));
6079 correct = False;
6082 talloc_destroy(mem_ctx);
6083 if (!torture_close_connection(cli)) {
6084 correct = False;
6087 return correct;
6090 static bool run_dirtest1(int dummy)
6092 int i;
6093 static struct cli_state *cli;
6094 uint16_t fnum;
6095 int num_seen;
6096 bool correct = True;
6098 printf("starting directory test\n");
6100 if (!torture_open_connection(&cli, 0)) {
6101 return False;
6104 cli_sockopt(cli, sockops);
6106 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6107 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6108 cli_rmdir(cli, "\\LISTDIR");
6109 cli_mkdir(cli, "\\LISTDIR");
6111 /* Create 1000 files and 1000 directories. */
6112 for (i=0;i<1000;i++) {
6113 fstring fname;
6114 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
6115 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6116 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum))) {
6117 fprintf(stderr,"Failed to open %s\n", fname);
6118 return False;
6120 cli_close(cli, fnum);
6122 for (i=0;i<1000;i++) {
6123 fstring fname;
6124 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
6125 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
6126 fprintf(stderr,"Failed to open %s\n", fname);
6127 return False;
6131 /* Now ensure that doing an old list sees both files and directories. */
6132 num_seen = 0;
6133 cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6134 printf("num_seen = %d\n", num_seen );
6135 /* We should see 100 files + 1000 directories + . and .. */
6136 if (num_seen != 2002)
6137 correct = False;
6139 /* Ensure if we have the "must have" bits we only see the
6140 * relevent entries.
6142 num_seen = 0;
6143 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6144 printf("num_seen = %d\n", num_seen );
6145 if (num_seen != 1002)
6146 correct = False;
6148 num_seen = 0;
6149 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6150 printf("num_seen = %d\n", num_seen );
6151 if (num_seen != 1000)
6152 correct = False;
6154 /* Delete everything. */
6155 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6156 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6157 cli_rmdir(cli, "\\LISTDIR");
6159 #if 0
6160 printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
6161 printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
6162 printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
6163 #endif
6165 if (!torture_close_connection(cli)) {
6166 correct = False;
6169 printf("finished dirtest1\n");
6171 return correct;
6174 static bool run_error_map_extract(int dummy) {
6176 static struct cli_state *c_dos;
6177 static struct cli_state *c_nt;
6178 NTSTATUS status;
6180 uint32 error;
6182 uint32 errnum;
6183 uint8 errclass;
6185 NTSTATUS nt_status;
6187 fstring user;
6189 /* NT-Error connection */
6191 if (!(c_nt = open_nbt_connection())) {
6192 return False;
6195 c_nt->use_spnego = False;
6197 status = cli_negprot(c_nt);
6199 if (!NT_STATUS_IS_OK(status)) {
6200 printf("%s rejected the NT-error negprot (%s)\n", host,
6201 nt_errstr(status));
6202 cli_shutdown(c_nt);
6203 return False;
6206 status = cli_session_setup(c_nt, "", "", 0, "", 0, workgroup);
6207 if (!NT_STATUS_IS_OK(status)) {
6208 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
6209 return False;
6212 /* DOS-Error connection */
6214 if (!(c_dos = open_nbt_connection())) {
6215 return False;
6218 c_dos->use_spnego = False;
6219 c_dos->force_dos_errors = True;
6221 status = cli_negprot(c_dos);
6222 if (!NT_STATUS_IS_OK(status)) {
6223 printf("%s rejected the DOS-error negprot (%s)\n", host,
6224 nt_errstr(status));
6225 cli_shutdown(c_dos);
6226 return False;
6229 status = cli_session_setup(c_dos, "", "", 0, "", 0, workgroup);
6230 if (!NT_STATUS_IS_OK(status)) {
6231 printf("%s rejected the DOS-error initial session setup (%s)\n",
6232 host, nt_errstr(status));
6233 return False;
6236 for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
6237 fstr_sprintf(user, "%X", error);
6239 status = cli_session_setup(c_nt, user,
6240 password, strlen(password),
6241 password, strlen(password),
6242 workgroup);
6243 if (NT_STATUS_IS_OK(status)) {
6244 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
6247 /* Case #1: 32-bit NT errors */
6248 if (cli_is_nt_error(c_nt)) {
6249 nt_status = cli_nt_error(c_nt);
6250 } else {
6251 printf("/** Dos error on NT connection! (%s) */\n",
6252 cli_errstr(c_nt));
6253 nt_status = NT_STATUS(0xc0000000);
6256 status = cli_session_setup(c_dos, user,
6257 password, strlen(password),
6258 password, strlen(password),
6259 workgroup);
6260 if (NT_STATUS_IS_OK(status)) {
6261 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
6264 /* Case #1: 32-bit NT errors */
6265 if (!cli_is_dos_error(c_dos)) {
6266 printf("/** NT error on DOS connection! (%s) */\n",
6267 cli_errstr(c_dos));
6268 errnum = errclass = 0;
6269 } else {
6270 cli_dos_error(c_dos, &errclass, &errnum);
6273 if (NT_STATUS_V(nt_status) != error) {
6274 printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
6275 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
6276 get_nt_error_c_code(talloc_tos(), nt_status));
6279 printf("\t{%s,\t%s,\t%s},\n",
6280 smb_dos_err_class(errclass),
6281 smb_dos_err_name(errclass, errnum),
6282 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
6284 return True;
6287 static bool run_sesssetup_bench(int dummy)
6289 static struct cli_state *c;
6290 const char *fname = "\\file.dat";
6291 uint16_t fnum;
6292 NTSTATUS status;
6293 int i;
6295 if (!torture_open_connection(&c, 0)) {
6296 return false;
6299 status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6300 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6301 FILE_DELETE_ON_CLOSE, 0, &fnum);
6302 if (!NT_STATUS_IS_OK(status)) {
6303 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
6304 return false;
6307 for (i=0; i<torture_numops; i++) {
6308 status = cli_session_setup(
6309 c, username,
6310 password, strlen(password),
6311 password, strlen(password),
6312 workgroup);
6313 if (!NT_STATUS_IS_OK(status)) {
6314 d_printf("(%s) cli_session_setup failed: %s\n",
6315 __location__, nt_errstr(status));
6316 return false;
6319 d_printf("\r%d ", (int)c->vuid);
6321 status = cli_ulogoff(c);
6322 if (!NT_STATUS_IS_OK(status)) {
6323 d_printf("(%s) cli_ulogoff failed: %s\n",
6324 __location__, nt_errstr(status));
6325 return false;
6327 c->vuid = 0;
6330 return true;
6333 static bool subst_test(const char *str, const char *user, const char *domain,
6334 uid_t uid, gid_t gid, const char *expected)
6336 char *subst;
6337 bool result = true;
6339 subst = talloc_sub_specified(talloc_tos(), str, user, domain, uid, gid);
6341 if (strcmp(subst, expected) != 0) {
6342 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
6343 "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
6344 expected);
6345 result = false;
6348 TALLOC_FREE(subst);
6349 return result;
6352 static void chain1_open_completion(struct tevent_req *req)
6354 uint16_t fnum;
6355 NTSTATUS status;
6356 status = cli_open_recv(req, &fnum);
6357 TALLOC_FREE(req);
6359 d_printf("cli_open_recv returned %s: %d\n",
6360 nt_errstr(status),
6361 NT_STATUS_IS_OK(status) ? fnum : -1);
6364 static void chain1_write_completion(struct tevent_req *req)
6366 size_t written;
6367 NTSTATUS status;
6368 status = cli_write_andx_recv(req, &written);
6369 TALLOC_FREE(req);
6371 d_printf("cli_write_andx_recv returned %s: %d\n",
6372 nt_errstr(status),
6373 NT_STATUS_IS_OK(status) ? (int)written : -1);
6376 static void chain1_close_completion(struct tevent_req *req)
6378 NTSTATUS status;
6379 bool *done = (bool *)tevent_req_callback_data_void(req);
6381 status = cli_close_recv(req);
6382 *done = true;
6384 TALLOC_FREE(req);
6386 d_printf("cli_close returned %s\n", nt_errstr(status));
6389 static bool run_chain1(int dummy)
6391 struct cli_state *cli1;
6392 struct event_context *evt = event_context_init(NULL);
6393 struct tevent_req *reqs[3], *smbreqs[3];
6394 bool done = false;
6395 const char *str = "foobar";
6396 NTSTATUS status;
6398 printf("starting chain1 test\n");
6399 if (!torture_open_connection(&cli1, 0)) {
6400 return False;
6403 cli_sockopt(cli1, sockops);
6405 reqs[0] = cli_open_create(talloc_tos(), evt, cli1, "\\test",
6406 O_CREAT|O_RDWR, 0, &smbreqs[0]);
6407 if (reqs[0] == NULL) return false;
6408 tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
6411 reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
6412 (const uint8_t *)str, 0, strlen(str)+1,
6413 smbreqs, 1, &smbreqs[1]);
6414 if (reqs[1] == NULL) return false;
6415 tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
6417 reqs[2] = cli_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
6418 if (reqs[2] == NULL) return false;
6419 tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
6421 status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
6422 if (!NT_STATUS_IS_OK(status)) {
6423 return false;
6426 while (!done) {
6427 event_loop_once(evt);
6430 torture_close_connection(cli1);
6431 return True;
6434 static void chain2_sesssetup_completion(struct tevent_req *req)
6436 NTSTATUS status;
6437 status = cli_session_setup_guest_recv(req);
6438 d_printf("sesssetup returned %s\n", nt_errstr(status));
6441 static void chain2_tcon_completion(struct tevent_req *req)
6443 bool *done = (bool *)tevent_req_callback_data_void(req);
6444 NTSTATUS status;
6445 status = cli_tcon_andx_recv(req);
6446 d_printf("tcon_and_x returned %s\n", nt_errstr(status));
6447 *done = true;
6450 static bool run_chain2(int dummy)
6452 struct cli_state *cli1;
6453 struct event_context *evt = event_context_init(NULL);
6454 struct tevent_req *reqs[2], *smbreqs[2];
6455 bool done = false;
6456 NTSTATUS status;
6458 printf("starting chain2 test\n");
6459 status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
6460 port_to_use, Undefined, 0);
6461 if (!NT_STATUS_IS_OK(status)) {
6462 return False;
6465 cli_sockopt(cli1, sockops);
6467 reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
6468 &smbreqs[0]);
6469 if (reqs[0] == NULL) return false;
6470 tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
6472 reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
6473 "?????", NULL, 0, &smbreqs[1]);
6474 if (reqs[1] == NULL) return false;
6475 tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
6477 status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
6478 if (!NT_STATUS_IS_OK(status)) {
6479 return false;
6482 while (!done) {
6483 event_loop_once(evt);
6486 torture_close_connection(cli1);
6487 return True;
6491 struct torture_createdel_state {
6492 struct tevent_context *ev;
6493 struct cli_state *cli;
6496 static void torture_createdel_created(struct tevent_req *subreq);
6497 static void torture_createdel_closed(struct tevent_req *subreq);
6499 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
6500 struct tevent_context *ev,
6501 struct cli_state *cli,
6502 const char *name)
6504 struct tevent_req *req, *subreq;
6505 struct torture_createdel_state *state;
6507 req = tevent_req_create(mem_ctx, &state,
6508 struct torture_createdel_state);
6509 if (req == NULL) {
6510 return NULL;
6512 state->ev = ev;
6513 state->cli = cli;
6515 subreq = cli_ntcreate_send(
6516 state, ev, cli, name, 0,
6517 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
6518 FILE_ATTRIBUTE_NORMAL,
6519 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6520 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
6522 if (tevent_req_nomem(subreq, req)) {
6523 return tevent_req_post(req, ev);
6525 tevent_req_set_callback(subreq, torture_createdel_created, req);
6526 return req;
6529 static void torture_createdel_created(struct tevent_req *subreq)
6531 struct tevent_req *req = tevent_req_callback_data(
6532 subreq, struct tevent_req);
6533 struct torture_createdel_state *state = tevent_req_data(
6534 req, struct torture_createdel_state);
6535 NTSTATUS status;
6536 uint16_t fnum;
6538 status = cli_ntcreate_recv(subreq, &fnum);
6539 TALLOC_FREE(subreq);
6540 if (!NT_STATUS_IS_OK(status)) {
6541 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
6542 nt_errstr(status)));
6543 tevent_req_nterror(req, status);
6544 return;
6547 subreq = cli_close_send(state, state->ev, state->cli, fnum);
6548 if (tevent_req_nomem(subreq, req)) {
6549 return;
6551 tevent_req_set_callback(subreq, torture_createdel_closed, req);
6554 static void torture_createdel_closed(struct tevent_req *subreq)
6556 struct tevent_req *req = tevent_req_callback_data(
6557 subreq, struct tevent_req);
6558 NTSTATUS status;
6560 status = cli_close_recv(subreq);
6561 if (!NT_STATUS_IS_OK(status)) {
6562 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
6563 tevent_req_nterror(req, status);
6564 return;
6566 tevent_req_done(req);
6569 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
6571 return tevent_req_simple_recv_ntstatus(req);
6574 struct torture_createdels_state {
6575 struct tevent_context *ev;
6576 struct cli_state *cli;
6577 const char *base_name;
6578 int sent;
6579 int received;
6580 int num_files;
6581 struct tevent_req **reqs;
6584 static void torture_createdels_done(struct tevent_req *subreq);
6586 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
6587 struct tevent_context *ev,
6588 struct cli_state *cli,
6589 const char *base_name,
6590 int num_parallel,
6591 int num_files)
6593 struct tevent_req *req;
6594 struct torture_createdels_state *state;
6595 int i;
6597 req = tevent_req_create(mem_ctx, &state,
6598 struct torture_createdels_state);
6599 if (req == NULL) {
6600 return NULL;
6602 state->ev = ev;
6603 state->cli = cli;
6604 state->base_name = talloc_strdup(state, base_name);
6605 if (tevent_req_nomem(state->base_name, req)) {
6606 return tevent_req_post(req, ev);
6608 state->num_files = MAX(num_parallel, num_files);
6609 state->sent = 0;
6610 state->received = 0;
6612 state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
6613 if (tevent_req_nomem(state->reqs, req)) {
6614 return tevent_req_post(req, ev);
6617 for (i=0; i<num_parallel; i++) {
6618 char *name;
6620 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6621 state->sent);
6622 if (tevent_req_nomem(name, req)) {
6623 return tevent_req_post(req, ev);
6625 state->reqs[i] = torture_createdel_send(
6626 state->reqs, state->ev, state->cli, name);
6627 if (tevent_req_nomem(state->reqs[i], req)) {
6628 return tevent_req_post(req, ev);
6630 name = talloc_move(state->reqs[i], &name);
6631 tevent_req_set_callback(state->reqs[i],
6632 torture_createdels_done, req);
6633 state->sent += 1;
6635 return req;
6638 static void torture_createdels_done(struct tevent_req *subreq)
6640 struct tevent_req *req = tevent_req_callback_data(
6641 subreq, struct tevent_req);
6642 struct torture_createdels_state *state = tevent_req_data(
6643 req, struct torture_createdels_state);
6644 size_t num_parallel = talloc_array_length(state->reqs);
6645 NTSTATUS status;
6646 char *name;
6647 int i;
6649 status = torture_createdel_recv(subreq);
6650 if (!NT_STATUS_IS_OK(status)){
6651 DEBUG(10, ("torture_createdel_recv returned %s\n",
6652 nt_errstr(status)));
6653 TALLOC_FREE(subreq);
6654 tevent_req_nterror(req, status);
6655 return;
6658 for (i=0; i<num_parallel; i++) {
6659 if (subreq == state->reqs[i]) {
6660 break;
6663 if (i == num_parallel) {
6664 DEBUG(10, ("received something we did not send\n"));
6665 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
6666 return;
6668 TALLOC_FREE(state->reqs[i]);
6670 if (state->sent >= state->num_files) {
6671 tevent_req_done(req);
6672 return;
6675 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6676 state->sent);
6677 if (tevent_req_nomem(name, req)) {
6678 return;
6680 state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
6681 state->cli, name);
6682 if (tevent_req_nomem(state->reqs[i], req)) {
6683 return;
6685 name = talloc_move(state->reqs[i], &name);
6686 tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
6687 state->sent += 1;
6690 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
6692 return tevent_req_simple_recv_ntstatus(req);
6695 struct swallow_notify_state {
6696 struct tevent_context *ev;
6697 struct cli_state *cli;
6698 uint16_t fnum;
6699 uint32_t completion_filter;
6700 bool recursive;
6701 bool (*fn)(uint32_t action, const char *name, void *priv);
6702 void *priv;
6705 static void swallow_notify_done(struct tevent_req *subreq);
6707 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
6708 struct tevent_context *ev,
6709 struct cli_state *cli,
6710 uint16_t fnum,
6711 uint32_t completion_filter,
6712 bool recursive,
6713 bool (*fn)(uint32_t action,
6714 const char *name,
6715 void *priv),
6716 void *priv)
6718 struct tevent_req *req, *subreq;
6719 struct swallow_notify_state *state;
6721 req = tevent_req_create(mem_ctx, &state,
6722 struct swallow_notify_state);
6723 if (req == NULL) {
6724 return NULL;
6726 state->ev = ev;
6727 state->cli = cli;
6728 state->fnum = fnum;
6729 state->completion_filter = completion_filter;
6730 state->recursive = recursive;
6731 state->fn = fn;
6732 state->priv = priv;
6734 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6735 0xffff, state->completion_filter,
6736 state->recursive);
6737 if (tevent_req_nomem(subreq, req)) {
6738 return tevent_req_post(req, ev);
6740 tevent_req_set_callback(subreq, swallow_notify_done, req);
6741 return req;
6744 static void swallow_notify_done(struct tevent_req *subreq)
6746 struct tevent_req *req = tevent_req_callback_data(
6747 subreq, struct tevent_req);
6748 struct swallow_notify_state *state = tevent_req_data(
6749 req, struct swallow_notify_state);
6750 NTSTATUS status;
6751 uint32_t i, num_changes;
6752 struct notify_change *changes;
6754 status = cli_notify_recv(subreq, state, &num_changes, &changes);
6755 TALLOC_FREE(subreq);
6756 if (!NT_STATUS_IS_OK(status)) {
6757 DEBUG(10, ("cli_notify_recv returned %s\n",
6758 nt_errstr(status)));
6759 tevent_req_nterror(req, status);
6760 return;
6763 for (i=0; i<num_changes; i++) {
6764 state->fn(changes[i].action, changes[i].name, state->priv);
6766 TALLOC_FREE(changes);
6768 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6769 0xffff, state->completion_filter,
6770 state->recursive);
6771 if (tevent_req_nomem(subreq, req)) {
6772 return;
6774 tevent_req_set_callback(subreq, swallow_notify_done, req);
6777 static bool print_notifies(uint32_t action, const char *name, void *priv)
6779 if (DEBUGLEVEL > 5) {
6780 d_printf("%d %s\n", (int)action, name);
6782 return true;
6785 static void notify_bench_done(struct tevent_req *req)
6787 int *num_finished = (int *)tevent_req_callback_data_void(req);
6788 *num_finished += 1;
6791 static bool run_notify_bench(int dummy)
6793 const char *dname = "\\notify-bench";
6794 struct tevent_context *ev;
6795 NTSTATUS status;
6796 uint16_t dnum;
6797 struct tevent_req *req1;
6798 struct tevent_req *req2 = NULL;
6799 int i, num_unc_names;
6800 int num_finished = 0;
6802 printf("starting notify-bench test\n");
6804 if (use_multishare_conn) {
6805 char **unc_list;
6806 unc_list = file_lines_load(multishare_conn_fname,
6807 &num_unc_names, 0, NULL);
6808 if (!unc_list || num_unc_names <= 0) {
6809 d_printf("Failed to load unc names list from '%s'\n",
6810 multishare_conn_fname);
6811 return false;
6813 TALLOC_FREE(unc_list);
6814 } else {
6815 num_unc_names = 1;
6818 ev = tevent_context_init(talloc_tos());
6819 if (ev == NULL) {
6820 d_printf("tevent_context_init failed\n");
6821 return false;
6824 for (i=0; i<num_unc_names; i++) {
6825 struct cli_state *cli;
6826 char *base_fname;
6828 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
6829 dname, i);
6830 if (base_fname == NULL) {
6831 return false;
6834 if (!torture_open_connection(&cli, i)) {
6835 return false;
6838 status = cli_ntcreate(cli, dname, 0,
6839 MAXIMUM_ALLOWED_ACCESS,
6840 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
6841 FILE_SHARE_DELETE,
6842 FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
6843 &dnum);
6845 if (!NT_STATUS_IS_OK(status)) {
6846 d_printf("Could not create %s: %s\n", dname,
6847 nt_errstr(status));
6848 return false;
6851 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
6852 FILE_NOTIFY_CHANGE_FILE_NAME |
6853 FILE_NOTIFY_CHANGE_DIR_NAME |
6854 FILE_NOTIFY_CHANGE_ATTRIBUTES |
6855 FILE_NOTIFY_CHANGE_LAST_WRITE,
6856 false, print_notifies, NULL);
6857 if (req1 == NULL) {
6858 d_printf("Could not create notify request\n");
6859 return false;
6862 req2 = torture_createdels_send(talloc_tos(), ev, cli,
6863 base_fname, 10, torture_numops);
6864 if (req2 == NULL) {
6865 d_printf("Could not create createdels request\n");
6866 return false;
6868 TALLOC_FREE(base_fname);
6870 tevent_req_set_callback(req2, notify_bench_done,
6871 &num_finished);
6874 while (num_finished < num_unc_names) {
6875 int ret;
6876 ret = tevent_loop_once(ev);
6877 if (ret != 0) {
6878 d_printf("tevent_loop_once failed\n");
6879 return false;
6883 if (!tevent_req_poll(req2, ev)) {
6884 d_printf("tevent_req_poll failed\n");
6887 status = torture_createdels_recv(req2);
6888 d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
6890 return true;
6893 static bool run_mangle1(int dummy)
6895 struct cli_state *cli;
6896 const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
6897 uint16_t fnum;
6898 fstring alt_name;
6899 NTSTATUS status;
6900 time_t change_time, access_time, write_time;
6901 SMB_OFF_T size;
6902 uint16_t mode;
6904 printf("starting mangle1 test\n");
6905 if (!torture_open_connection(&cli, 0)) {
6906 return False;
6909 cli_sockopt(cli, sockops);
6911 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6912 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6913 0, 0, &fnum);
6914 if (!NT_STATUS_IS_OK(status)) {
6915 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
6916 return false;
6918 cli_close(cli, fnum);
6920 status = cli_qpathinfo_alt_name(cli, fname, alt_name);
6921 if (!NT_STATUS_IS_OK(status)) {
6922 d_printf("cli_qpathinfo_alt_name failed: %s\n",
6923 nt_errstr(status));
6924 return false;
6926 d_printf("alt_name: %s\n", alt_name);
6928 status = cli_open(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
6929 if (!NT_STATUS_IS_OK(status)) {
6930 d_printf("cli_open(%s) failed: %s\n", alt_name,
6931 nt_errstr(status));
6932 return false;
6934 cli_close(cli, fnum);
6936 status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
6937 &write_time, &size, &mode);
6938 if (!NT_STATUS_IS_OK(status)) {
6939 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
6940 nt_errstr(status));
6941 return false;
6944 return true;
6947 static size_t null_source(uint8_t *buf, size_t n, void *priv)
6949 size_t *to_pull = (size_t *)priv;
6950 size_t thistime = *to_pull;
6952 thistime = MIN(thistime, n);
6953 if (thistime == 0) {
6954 return 0;
6957 memset(buf, 0, thistime);
6958 *to_pull -= thistime;
6959 return thistime;
6962 static bool run_windows_write(int dummy)
6964 struct cli_state *cli1;
6965 uint16_t fnum;
6966 int i;
6967 bool ret = false;
6968 const char *fname = "\\writetest.txt";
6969 struct timeval start_time;
6970 double seconds;
6971 double kbytes;
6972 NTSTATUS status;
6974 printf("starting windows_write test\n");
6975 if (!torture_open_connection(&cli1, 0)) {
6976 return False;
6979 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6980 if (!NT_STATUS_IS_OK(status)) {
6981 printf("open failed (%s)\n", nt_errstr(status));
6982 return False;
6985 cli_sockopt(cli1, sockops);
6987 start_time = timeval_current();
6989 for (i=0; i<torture_numops; i++) {
6990 uint8_t c = 0;
6991 off_t start = i * torture_blocksize;
6992 size_t to_pull = torture_blocksize - 1;
6994 status = cli_writeall(cli1, fnum, 0, &c,
6995 start + torture_blocksize - 1, 1, NULL);
6996 if (!NT_STATUS_IS_OK(status)) {
6997 printf("cli_write failed: %s\n", nt_errstr(status));
6998 goto fail;
7001 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
7002 null_source, &to_pull);
7003 if (!NT_STATUS_IS_OK(status)) {
7004 printf("cli_push returned: %s\n", nt_errstr(status));
7005 goto fail;
7009 seconds = timeval_elapsed(&start_time);
7010 kbytes = (double)torture_blocksize * torture_numops;
7011 kbytes /= 1024;
7013 printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
7014 (double)seconds, (int)(kbytes/seconds));
7016 ret = true;
7017 fail:
7018 cli_close(cli1, fnum);
7019 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7020 torture_close_connection(cli1);
7021 return ret;
7024 static bool run_cli_echo(int dummy)
7026 struct cli_state *cli;
7027 NTSTATUS status;
7029 printf("starting cli_echo test\n");
7030 if (!torture_open_connection(&cli, 0)) {
7031 return false;
7033 cli_sockopt(cli, sockops);
7035 status = cli_echo(cli, 5, data_blob_const("hello", 5));
7037 d_printf("cli_echo returned %s\n", nt_errstr(status));
7039 torture_close_connection(cli);
7040 return NT_STATUS_IS_OK(status);
7043 static bool run_uid_regression_test(int dummy)
7045 static struct cli_state *cli;
7046 int16_t old_vuid;
7047 int16_t old_cnum;
7048 bool correct = True;
7049 NTSTATUS status;
7051 printf("starting uid regression test\n");
7053 if (!torture_open_connection(&cli, 0)) {
7054 return False;
7057 cli_sockopt(cli, sockops);
7059 /* Ok - now save then logoff our current user. */
7060 old_vuid = cli->vuid;
7062 status = cli_ulogoff(cli);
7063 if (!NT_STATUS_IS_OK(status)) {
7064 d_printf("(%s) cli_ulogoff failed: %s\n",
7065 __location__, nt_errstr(status));
7066 correct = false;
7067 goto out;
7070 cli->vuid = old_vuid;
7072 /* Try an operation. */
7073 status = cli_mkdir(cli, "\\uid_reg_test");
7074 if (NT_STATUS_IS_OK(status)) {
7075 d_printf("(%s) cli_mkdir succeeded\n",
7076 __location__);
7077 correct = false;
7078 goto out;
7079 } else {
7080 /* Should be bad uid. */
7081 if (!check_error(__LINE__, cli, ERRSRV, ERRbaduid,
7082 NT_STATUS_USER_SESSION_DELETED)) {
7083 correct = false;
7084 goto out;
7088 old_cnum = cli->cnum;
7090 /* Now try a SMBtdis with the invald vuid set to zero. */
7091 cli->vuid = 0;
7093 /* This should succeed. */
7094 status = cli_tdis(cli);
7096 if (NT_STATUS_IS_OK(status)) {
7097 d_printf("First tdis with invalid vuid should succeed.\n");
7098 } else {
7099 d_printf("First tdis failed (%s)\n", nt_errstr(status));
7100 correct = false;
7101 goto out;
7104 cli->vuid = old_vuid;
7105 cli->cnum = old_cnum;
7107 /* This should fail. */
7108 status = cli_tdis(cli);
7109 if (NT_STATUS_IS_OK(status)) {
7110 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
7111 correct = false;
7112 goto out;
7113 } else {
7114 /* Should be bad tid. */
7115 if (!check_error(__LINE__, cli, ERRSRV, ERRinvnid,
7116 NT_STATUS_NETWORK_NAME_DELETED)) {
7117 correct = false;
7118 goto out;
7122 cli_rmdir(cli, "\\uid_reg_test");
7124 out:
7126 cli_shutdown(cli);
7127 return correct;
7131 static const char *illegal_chars = "*\\/?<>|\":";
7132 static char force_shortname_chars[] = " +,.[];=\177";
7134 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
7135 const char *mask, void *state)
7137 struct cli_state *pcli = (struct cli_state *)state;
7138 fstring fname;
7139 NTSTATUS status = NT_STATUS_OK;
7141 slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
7143 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
7144 return NT_STATUS_OK;
7146 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
7147 status = cli_rmdir(pcli, fname);
7148 if (!NT_STATUS_IS_OK(status)) {
7149 printf("del_fn: failed to rmdir %s\n,", fname );
7151 } else {
7152 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7153 if (!NT_STATUS_IS_OK(status)) {
7154 printf("del_fn: failed to unlink %s\n,", fname );
7157 return status;
7160 struct sn_state {
7161 int matched;
7162 int i;
7163 bool val;
7166 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
7167 const char *name, void *state)
7169 struct sn_state *s = (struct sn_state *)state;
7170 int i = s->i;
7172 #if 0
7173 printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
7174 i, finfo->name, finfo->short_name);
7175 #endif
7177 if (strchr(force_shortname_chars, i)) {
7178 if (!finfo->short_name) {
7179 /* Shortname not created when it should be. */
7180 d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
7181 __location__, finfo->name, i);
7182 s->val = true;
7184 } else if (finfo->short_name){
7185 /* Shortname created when it should not be. */
7186 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
7187 __location__, finfo->short_name, finfo->name);
7188 s->val = true;
7190 s->matched += 1;
7191 return NT_STATUS_OK;
7194 static bool run_shortname_test(int dummy)
7196 static struct cli_state *cli;
7197 bool correct = True;
7198 int i;
7199 struct sn_state s;
7200 char fname[20];
7201 NTSTATUS status;
7203 printf("starting shortname test\n");
7205 if (!torture_open_connection(&cli, 0)) {
7206 return False;
7209 cli_sockopt(cli, sockops);
7211 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7212 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7213 cli_rmdir(cli, "\\shortname");
7215 status = cli_mkdir(cli, "\\shortname");
7216 if (!NT_STATUS_IS_OK(status)) {
7217 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
7218 __location__, nt_errstr(status));
7219 correct = false;
7220 goto out;
7223 strlcpy(fname, "\\shortname\\", sizeof(fname));
7224 strlcat(fname, "test .txt", sizeof(fname));
7226 s.val = false;
7228 for (i = 32; i < 128; i++) {
7229 uint16_t fnum = (uint16_t)-1;
7231 s.i = i;
7233 if (strchr(illegal_chars, i)) {
7234 continue;
7236 fname[15] = i;
7238 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
7239 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum);
7240 if (!NT_STATUS_IS_OK(status)) {
7241 d_printf("(%s) cli_nt_create of %s failed: %s\n",
7242 __location__, fname, nt_errstr(status));
7243 correct = false;
7244 goto out;
7246 cli_close(cli, fnum);
7248 s.matched = 0;
7249 status = cli_list(cli, "\\shortname\\test*.*", 0,
7250 shortname_list_fn, &s);
7251 if (s.matched != 1) {
7252 d_printf("(%s) failed to list %s: %s\n",
7253 __location__, fname, nt_errstr(status));
7254 correct = false;
7255 goto out;
7258 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7259 if (!NT_STATUS_IS_OK(status)) {
7260 d_printf("(%s) failed to delete %s: %s\n",
7261 __location__, fname, nt_errstr(status));
7262 correct = false;
7263 goto out;
7266 if (s.val) {
7267 correct = false;
7268 goto out;
7272 out:
7274 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7275 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7276 cli_rmdir(cli, "\\shortname");
7277 torture_close_connection(cli);
7278 return correct;
7281 static void pagedsearch_cb(struct tevent_req *req)
7283 int rc;
7284 struct tldap_message *msg;
7285 char *dn;
7287 rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
7288 if (rc != TLDAP_SUCCESS) {
7289 d_printf("tldap_search_paged_recv failed: %s\n",
7290 tldap_err2string(rc));
7291 return;
7293 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
7294 TALLOC_FREE(msg);
7295 return;
7297 if (!tldap_entry_dn(msg, &dn)) {
7298 d_printf("tldap_entry_dn failed\n");
7299 return;
7301 d_printf("%s\n", dn);
7302 TALLOC_FREE(msg);
7305 static bool run_tldap(int dummy)
7307 struct tldap_context *ld;
7308 int fd, rc;
7309 NTSTATUS status;
7310 struct sockaddr_storage addr;
7311 struct tevent_context *ev;
7312 struct tevent_req *req;
7313 char *basedn;
7314 const char *filter;
7316 if (!resolve_name(host, &addr, 0, false)) {
7317 d_printf("could not find host %s\n", host);
7318 return false;
7320 status = open_socket_out(&addr, 389, 9999, &fd);
7321 if (!NT_STATUS_IS_OK(status)) {
7322 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
7323 return false;
7326 ld = tldap_context_create(talloc_tos(), fd);
7327 if (ld == NULL) {
7328 close(fd);
7329 d_printf("tldap_context_create failed\n");
7330 return false;
7333 rc = tldap_fetch_rootdse(ld);
7334 if (rc != TLDAP_SUCCESS) {
7335 d_printf("tldap_fetch_rootdse failed: %s\n",
7336 tldap_errstr(talloc_tos(), ld, rc));
7337 return false;
7340 basedn = tldap_talloc_single_attribute(
7341 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
7342 if (basedn == NULL) {
7343 d_printf("no defaultNamingContext\n");
7344 return false;
7346 d_printf("defaultNamingContext: %s\n", basedn);
7348 ev = tevent_context_init(talloc_tos());
7349 if (ev == NULL) {
7350 d_printf("tevent_context_init failed\n");
7351 return false;
7354 req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
7355 TLDAP_SCOPE_SUB, "(objectclass=*)",
7356 NULL, 0, 0,
7357 NULL, 0, NULL, 0, 0, 0, 0, 5);
7358 if (req == NULL) {
7359 d_printf("tldap_search_paged_send failed\n");
7360 return false;
7362 tevent_req_set_callback(req, pagedsearch_cb, NULL);
7364 tevent_req_poll(req, ev);
7366 TALLOC_FREE(req);
7368 /* test search filters against rootDSE */
7369 filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
7370 "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
7372 rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
7373 NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
7374 talloc_tos(), NULL, NULL);
7375 if (rc != TLDAP_SUCCESS) {
7376 d_printf("tldap_search with complex filter failed: %s\n",
7377 tldap_errstr(talloc_tos(), ld, rc));
7378 return false;
7381 TALLOC_FREE(ld);
7382 return true;
7385 /* Torture test to ensure no regression of :
7386 https://bugzilla.samba.org/show_bug.cgi?id=7084
7389 static bool run_dir_createtime(int dummy)
7391 struct cli_state *cli;
7392 const char *dname = "\\testdir";
7393 const char *fname = "\\testdir\\testfile";
7394 NTSTATUS status;
7395 struct timespec create_time;
7396 struct timespec create_time1;
7397 uint16_t fnum;
7398 bool ret = false;
7400 if (!torture_open_connection(&cli, 0)) {
7401 return false;
7404 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7405 cli_rmdir(cli, dname);
7407 status = cli_mkdir(cli, dname);
7408 if (!NT_STATUS_IS_OK(status)) {
7409 printf("mkdir failed: %s\n", nt_errstr(status));
7410 goto out;
7413 status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
7414 NULL, NULL, NULL);
7415 if (!NT_STATUS_IS_OK(status)) {
7416 printf("cli_qpathinfo2 returned %s\n",
7417 nt_errstr(status));
7418 goto out;
7421 /* Sleep 3 seconds, then create a file. */
7422 sleep(3);
7424 status = cli_open(cli, fname, O_RDWR | O_CREAT | O_EXCL,
7425 DENY_NONE, &fnum);
7426 if (!NT_STATUS_IS_OK(status)) {
7427 printf("cli_open failed: %s\n", nt_errstr(status));
7428 goto out;
7431 status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
7432 NULL, NULL, NULL);
7433 if (!NT_STATUS_IS_OK(status)) {
7434 printf("cli_qpathinfo2 (2) returned %s\n",
7435 nt_errstr(status));
7436 goto out;
7439 if (timespec_compare(&create_time1, &create_time)) {
7440 printf("run_dir_createtime: create time was updated (error)\n");
7441 } else {
7442 printf("run_dir_createtime: create time was not updated (correct)\n");
7443 ret = true;
7446 out:
7448 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7449 cli_rmdir(cli, dname);
7450 if (!torture_close_connection(cli)) {
7451 ret = false;
7453 return ret;
7457 static bool run_streamerror(int dummy)
7459 struct cli_state *cli;
7460 const char *dname = "\\testdir";
7461 const char *streamname =
7462 "testdir:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
7463 NTSTATUS status;
7464 time_t change_time, access_time, write_time;
7465 SMB_OFF_T size;
7466 uint16_t mode, fnum;
7467 bool ret = true;
7469 if (!torture_open_connection(&cli, 0)) {
7470 return false;
7473 cli_unlink(cli, "\\testdir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7474 cli_rmdir(cli, dname);
7476 status = cli_mkdir(cli, dname);
7477 if (!NT_STATUS_IS_OK(status)) {
7478 printf("mkdir failed: %s\n", nt_errstr(status));
7479 return false;
7482 cli_qpathinfo1(cli, streamname, &change_time, &access_time, &write_time,
7483 &size, &mode);
7484 status = cli_nt_error(cli);
7486 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7487 printf("pathinfo returned %s, expected "
7488 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
7489 nt_errstr(status));
7490 ret = false;
7493 status = cli_ntcreate(cli, streamname, 0x16,
7494 FILE_READ_DATA|FILE_READ_EA|
7495 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
7496 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7497 FILE_OPEN, 0, 0, &fnum);
7499 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7500 printf("ntcreate returned %s, expected "
7501 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
7502 nt_errstr(status));
7503 ret = false;
7507 cli_rmdir(cli, dname);
7508 return ret;
7511 static bool run_local_substitute(int dummy)
7513 bool ok = true;
7515 ok &= subst_test("%U", "bla", "", -1, -1, "bla");
7516 ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
7517 ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
7518 ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
7519 ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
7520 ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
7521 ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
7522 ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
7524 /* Different captialization rules in sub_basic... */
7526 ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
7527 "blaDOM") == 0);
7529 return ok;
7532 static bool run_local_base64(int dummy)
7534 int i;
7535 bool ret = true;
7537 for (i=1; i<2000; i++) {
7538 DATA_BLOB blob1, blob2;
7539 char *b64;
7541 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
7542 blob1.length = i;
7543 generate_random_buffer(blob1.data, blob1.length);
7545 b64 = base64_encode_data_blob(talloc_tos(), blob1);
7546 if (b64 == NULL) {
7547 d_fprintf(stderr, "base64_encode_data_blob failed "
7548 "for %d bytes\n", i);
7549 ret = false;
7551 blob2 = base64_decode_data_blob(b64);
7552 TALLOC_FREE(b64);
7554 if (data_blob_cmp(&blob1, &blob2)) {
7555 d_fprintf(stderr, "data_blob_cmp failed for %d "
7556 "bytes\n", i);
7557 ret = false;
7559 TALLOC_FREE(blob1.data);
7560 data_blob_free(&blob2);
7562 return ret;
7565 static bool run_local_gencache(int dummy)
7567 char *val;
7568 time_t tm;
7569 DATA_BLOB blob;
7571 if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
7572 d_printf("%s: gencache_set() failed\n", __location__);
7573 return False;
7576 if (!gencache_get("foo", NULL, NULL)) {
7577 d_printf("%s: gencache_get() failed\n", __location__);
7578 return False;
7581 if (!gencache_get("foo", &val, &tm)) {
7582 d_printf("%s: gencache_get() failed\n", __location__);
7583 return False;
7586 if (strcmp(val, "bar") != 0) {
7587 d_printf("%s: gencache_get() returned %s, expected %s\n",
7588 __location__, val, "bar");
7589 SAFE_FREE(val);
7590 return False;
7593 SAFE_FREE(val);
7595 if (!gencache_del("foo")) {
7596 d_printf("%s: gencache_del() failed\n", __location__);
7597 return False;
7599 if (gencache_del("foo")) {
7600 d_printf("%s: second gencache_del() succeeded\n",
7601 __location__);
7602 return False;
7605 if (gencache_get("foo", &val, &tm)) {
7606 d_printf("%s: gencache_get() on deleted entry "
7607 "succeeded\n", __location__);
7608 return False;
7611 blob = data_blob_string_const_null("bar");
7612 tm = time(NULL) + 60;
7614 if (!gencache_set_data_blob("foo", &blob, tm)) {
7615 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
7616 return False;
7619 if (!gencache_get_data_blob("foo", &blob, NULL, NULL)) {
7620 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
7621 return False;
7624 if (strcmp((const char *)blob.data, "bar") != 0) {
7625 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
7626 __location__, (const char *)blob.data, "bar");
7627 data_blob_free(&blob);
7628 return False;
7631 data_blob_free(&blob);
7633 if (!gencache_del("foo")) {
7634 d_printf("%s: gencache_del() failed\n", __location__);
7635 return False;
7637 if (gencache_del("foo")) {
7638 d_printf("%s: second gencache_del() succeeded\n",
7639 __location__);
7640 return False;
7643 if (gencache_get_data_blob("foo", &blob, NULL, NULL)) {
7644 d_printf("%s: gencache_get_data_blob() on deleted entry "
7645 "succeeded\n", __location__);
7646 return False;
7649 return True;
7652 static bool rbt_testval(struct db_context *db, const char *key,
7653 const char *value)
7655 struct db_record *rec;
7656 TDB_DATA data = string_tdb_data(value);
7657 bool ret = false;
7658 NTSTATUS status;
7660 rec = db->fetch_locked(db, db, string_tdb_data(key));
7661 if (rec == NULL) {
7662 d_fprintf(stderr, "fetch_locked failed\n");
7663 goto done;
7665 status = rec->store(rec, data, 0);
7666 if (!NT_STATUS_IS_OK(status)) {
7667 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
7668 goto done;
7670 TALLOC_FREE(rec);
7672 rec = db->fetch_locked(db, db, string_tdb_data(key));
7673 if (rec == NULL) {
7674 d_fprintf(stderr, "second fetch_locked failed\n");
7675 goto done;
7677 if ((rec->value.dsize != data.dsize)
7678 || (memcmp(rec->value.dptr, data.dptr, data.dsize) != 0)) {
7679 d_fprintf(stderr, "Got wrong data back\n");
7680 goto done;
7683 ret = true;
7684 done:
7685 TALLOC_FREE(rec);
7686 return ret;
7689 static bool run_local_rbtree(int dummy)
7691 struct db_context *db;
7692 bool ret = false;
7693 int i;
7695 db = db_open_rbt(NULL);
7697 if (db == NULL) {
7698 d_fprintf(stderr, "db_open_rbt failed\n");
7699 return false;
7702 for (i=0; i<1000; i++) {
7703 char *key, *value;
7705 if (asprintf(&key, "key%ld", random()) == -1) {
7706 goto done;
7708 if (asprintf(&value, "value%ld", random()) == -1) {
7709 SAFE_FREE(key);
7710 goto done;
7713 if (!rbt_testval(db, key, value)) {
7714 SAFE_FREE(key);
7715 SAFE_FREE(value);
7716 goto done;
7719 SAFE_FREE(value);
7720 if (asprintf(&value, "value%ld", random()) == -1) {
7721 SAFE_FREE(key);
7722 goto done;
7725 if (!rbt_testval(db, key, value)) {
7726 SAFE_FREE(key);
7727 SAFE_FREE(value);
7728 goto done;
7731 SAFE_FREE(key);
7732 SAFE_FREE(value);
7735 ret = true;
7737 done:
7738 TALLOC_FREE(db);
7739 return ret;
7744 local test for character set functions
7746 This is a very simple test for the functionality in convert_string_error()
7748 static bool run_local_convert_string(int dummy)
7750 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
7751 const char *test_strings[2] = { "March", "M\303\244rz" };
7752 char dst[7];
7753 int i;
7755 for (i=0; i<2; i++) {
7756 const char *str = test_strings[i];
7757 int len = strlen(str);
7758 size_t converted_size;
7759 bool ret;
7761 memset(dst, 'X', sizeof(dst));
7763 /* first try with real source length */
7764 ret = convert_string_error(CH_UNIX, CH_UTF8,
7765 str, len,
7766 dst, sizeof(dst),
7767 &converted_size);
7768 if (ret != true) {
7769 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
7770 goto failed;
7773 if (converted_size != len) {
7774 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
7775 str, len, (int)converted_size);
7776 goto failed;
7779 if (strncmp(str, dst, converted_size) != 0) {
7780 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
7781 goto failed;
7784 if (strlen(str) != converted_size) {
7785 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
7786 (int)strlen(str), (int)converted_size);
7787 goto failed;
7790 if (dst[converted_size] != 'X') {
7791 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
7792 goto failed;
7795 /* now with srclen==-1, this causes the nul to be
7796 * converted too */
7797 ret = convert_string_error(CH_UNIX, CH_UTF8,
7798 str, -1,
7799 dst, sizeof(dst),
7800 &converted_size);
7801 if (ret != true) {
7802 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
7803 goto failed;
7806 if (converted_size != len+1) {
7807 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
7808 str, len, (int)converted_size);
7809 goto failed;
7812 if (strncmp(str, dst, converted_size) != 0) {
7813 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
7814 goto failed;
7817 if (len+1 != converted_size) {
7818 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
7819 len+1, (int)converted_size);
7820 goto failed;
7823 if (dst[converted_size] != 'X') {
7824 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
7825 goto failed;
7831 TALLOC_FREE(tmp_ctx);
7832 return true;
7833 failed:
7834 TALLOC_FREE(tmp_ctx);
7835 return false;
7839 struct talloc_dict_test {
7840 int content;
7843 static int talloc_dict_traverse_fn(DATA_BLOB key, void *data, void *priv)
7845 int *count = (int *)priv;
7846 *count += 1;
7847 return 0;
7850 static bool run_local_talloc_dict(int dummy)
7852 struct talloc_dict *dict;
7853 struct talloc_dict_test *t;
7854 int key, count;
7856 dict = talloc_dict_init(talloc_tos());
7857 if (dict == NULL) {
7858 return false;
7861 t = talloc(talloc_tos(), struct talloc_dict_test);
7862 if (t == NULL) {
7863 return false;
7866 key = 1;
7867 t->content = 1;
7868 if (!talloc_dict_set(dict, data_blob_const(&key, sizeof(key)), t)) {
7869 return false;
7872 count = 0;
7873 if (talloc_dict_traverse(dict, talloc_dict_traverse_fn, &count) != 0) {
7874 return false;
7877 if (count != 1) {
7878 return false;
7881 TALLOC_FREE(dict);
7883 return true;
7886 static bool run_local_string_to_sid(int dummy) {
7887 struct dom_sid sid;
7889 if (string_to_sid(&sid, "S--1-5-32-545")) {
7890 printf("allowing S--1-5-32-545\n");
7891 return false;
7893 if (string_to_sid(&sid, "S-1-5-32-+545")) {
7894 printf("allowing S-1-5-32-+545\n");
7895 return false;
7897 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")) {
7898 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
7899 return false;
7901 if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
7902 printf("allowing S-1-5-32-545-abc\n");
7903 return false;
7905 if (!string_to_sid(&sid, "S-1-5-32-545")) {
7906 printf("could not parse S-1-5-32-545\n");
7907 return false;
7909 if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
7910 printf("mis-parsed S-1-5-32-545 as %s\n",
7911 sid_string_tos(&sid));
7912 return false;
7914 return true;
7917 static bool run_local_binary_to_sid(int dummy) {
7918 struct dom_sid *sid = talloc(NULL, struct dom_sid);
7919 static const char good_binary_sid[] = {
7920 0x1, /* revision number */
7921 15, /* num auths */
7922 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
7923 0x1, 0x1, 0x1, 0x1, /* auth[0] */
7924 0x1, 0x1, 0x1, 0x1, /* auth[1] */
7925 0x1, 0x1, 0x1, 0x1, /* auth[2] */
7926 0x1, 0x1, 0x1, 0x1, /* auth[3] */
7927 0x1, 0x1, 0x1, 0x1, /* auth[4] */
7928 0x1, 0x1, 0x1, 0x1, /* auth[5] */
7929 0x1, 0x1, 0x1, 0x1, /* auth[6] */
7930 0x1, 0x1, 0x1, 0x1, /* auth[7] */
7931 0x1, 0x1, 0x1, 0x1, /* auth[8] */
7932 0x1, 0x1, 0x1, 0x1, /* auth[9] */
7933 0x1, 0x1, 0x1, 0x1, /* auth[10] */
7934 0x1, 0x1, 0x1, 0x1, /* auth[11] */
7935 0x1, 0x1, 0x1, 0x1, /* auth[12] */
7936 0x1, 0x1, 0x1, 0x1, /* auth[13] */
7937 0x1, 0x1, 0x1, 0x1, /* auth[14] */
7940 static const char long_binary_sid[] = {
7941 0x1, /* revision number */
7942 15, /* num auths */
7943 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
7944 0x1, 0x1, 0x1, 0x1, /* auth[0] */
7945 0x1, 0x1, 0x1, 0x1, /* auth[1] */
7946 0x1, 0x1, 0x1, 0x1, /* auth[2] */
7947 0x1, 0x1, 0x1, 0x1, /* auth[3] */
7948 0x1, 0x1, 0x1, 0x1, /* auth[4] */
7949 0x1, 0x1, 0x1, 0x1, /* auth[5] */
7950 0x1, 0x1, 0x1, 0x1, /* auth[6] */
7951 0x1, 0x1, 0x1, 0x1, /* auth[7] */
7952 0x1, 0x1, 0x1, 0x1, /* auth[8] */
7953 0x1, 0x1, 0x1, 0x1, /* auth[9] */
7954 0x1, 0x1, 0x1, 0x1, /* auth[10] */
7955 0x1, 0x1, 0x1, 0x1, /* auth[11] */
7956 0x1, 0x1, 0x1, 0x1, /* auth[12] */
7957 0x1, 0x1, 0x1, 0x1, /* auth[13] */
7958 0x1, 0x1, 0x1, 0x1, /* auth[14] */
7959 0x1, 0x1, 0x1, 0x1, /* auth[15] */
7960 0x1, 0x1, 0x1, 0x1, /* auth[16] */
7961 0x1, 0x1, 0x1, 0x1, /* auth[17] */
7964 static const char long_binary_sid2[] = {
7965 0x1, /* revision number */
7966 32, /* 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] */
7986 0x1, 0x1, 0x1, 0x1, /* auth[18] */
7987 0x1, 0x1, 0x1, 0x1, /* auth[19] */
7988 0x1, 0x1, 0x1, 0x1, /* auth[20] */
7989 0x1, 0x1, 0x1, 0x1, /* auth[21] */
7990 0x1, 0x1, 0x1, 0x1, /* auth[22] */
7991 0x1, 0x1, 0x1, 0x1, /* auth[23] */
7992 0x1, 0x1, 0x1, 0x1, /* auth[24] */
7993 0x1, 0x1, 0x1, 0x1, /* auth[25] */
7994 0x1, 0x1, 0x1, 0x1, /* auth[26] */
7995 0x1, 0x1, 0x1, 0x1, /* auth[27] */
7996 0x1, 0x1, 0x1, 0x1, /* auth[28] */
7997 0x1, 0x1, 0x1, 0x1, /* auth[29] */
7998 0x1, 0x1, 0x1, 0x1, /* auth[30] */
7999 0x1, 0x1, 0x1, 0x1, /* auth[31] */
8002 if (!sid_parse(good_binary_sid, sizeof(good_binary_sid), sid)) {
8003 return false;
8005 if (sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid)) {
8006 return false;
8008 if (sid_parse(long_binary_sid, sizeof(long_binary_sid), sid)) {
8009 return false;
8011 return true;
8014 /* Split a path name into filename and stream name components. Canonicalise
8015 * such that an implicit $DATA token is always explicit.
8017 * The "specification" of this function can be found in the
8018 * run_local_stream_name() function in torture.c, I've tried those
8019 * combinations against a W2k3 server.
8022 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
8023 char **pbase, char **pstream)
8025 char *base = NULL;
8026 char *stream = NULL;
8027 char *sname; /* stream name */
8028 const char *stype; /* stream type */
8030 DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
8032 sname = strchr_m(fname, ':');
8034 if (lp_posix_pathnames() || (sname == NULL)) {
8035 if (pbase != NULL) {
8036 base = talloc_strdup(mem_ctx, fname);
8037 NT_STATUS_HAVE_NO_MEMORY(base);
8039 goto done;
8042 if (pbase != NULL) {
8043 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
8044 NT_STATUS_HAVE_NO_MEMORY(base);
8047 sname += 1;
8049 stype = strchr_m(sname, ':');
8051 if (stype == NULL) {
8052 sname = talloc_strdup(mem_ctx, sname);
8053 stype = "$DATA";
8055 else {
8056 if (strcasecmp_m(stype, ":$DATA") != 0) {
8058 * If there is an explicit stream type, so far we only
8059 * allow $DATA. Is there anything else allowed? -- vl
8061 DEBUG(10, ("[%s] is an invalid stream type\n", stype));
8062 TALLOC_FREE(base);
8063 return NT_STATUS_OBJECT_NAME_INVALID;
8065 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
8066 stype += 1;
8069 if (sname == NULL) {
8070 TALLOC_FREE(base);
8071 return NT_STATUS_NO_MEMORY;
8074 if (sname[0] == '\0') {
8076 * no stream name, so no stream
8078 goto done;
8081 if (pstream != NULL) {
8082 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
8083 if (stream == NULL) {
8084 TALLOC_FREE(sname);
8085 TALLOC_FREE(base);
8086 return NT_STATUS_NO_MEMORY;
8089 * upper-case the type field
8091 strupper_m(strchr_m(stream, ':')+1);
8094 done:
8095 if (pbase != NULL) {
8096 *pbase = base;
8098 if (pstream != NULL) {
8099 *pstream = stream;
8101 return NT_STATUS_OK;
8104 static bool test_stream_name(const char *fname, const char *expected_base,
8105 const char *expected_stream,
8106 NTSTATUS expected_status)
8108 NTSTATUS status;
8109 char *base = NULL;
8110 char *stream = NULL;
8112 status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
8113 if (!NT_STATUS_EQUAL(status, expected_status)) {
8114 goto error;
8117 if (!NT_STATUS_IS_OK(status)) {
8118 return true;
8121 if (base == NULL) goto error;
8123 if (strcmp(expected_base, base) != 0) goto error;
8125 if ((expected_stream != NULL) && (stream == NULL)) goto error;
8126 if ((expected_stream == NULL) && (stream != NULL)) goto error;
8128 if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
8129 goto error;
8131 TALLOC_FREE(base);
8132 TALLOC_FREE(stream);
8133 return true;
8135 error:
8136 d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
8137 fname, expected_base ? expected_base : "<NULL>",
8138 expected_stream ? expected_stream : "<NULL>",
8139 nt_errstr(expected_status));
8140 d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
8141 base ? base : "<NULL>", stream ? stream : "<NULL>",
8142 nt_errstr(status));
8143 TALLOC_FREE(base);
8144 TALLOC_FREE(stream);
8145 return false;
8148 static bool run_local_stream_name(int dummy)
8150 bool ret = true;
8152 ret &= test_stream_name(
8153 "bla", "bla", NULL, NT_STATUS_OK);
8154 ret &= test_stream_name(
8155 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
8156 ret &= test_stream_name(
8157 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8158 ret &= test_stream_name(
8159 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
8160 ret &= test_stream_name(
8161 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8162 ret &= test_stream_name(
8163 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
8164 ret &= test_stream_name(
8165 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
8166 ret &= test_stream_name(
8167 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
8169 return ret;
8172 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
8174 if (a.length != b.length) {
8175 printf("a.length=%d != b.length=%d\n",
8176 (int)a.length, (int)b.length);
8177 return false;
8179 if (memcmp(a.data, b.data, a.length) != 0) {
8180 printf("a.data and b.data differ\n");
8181 return false;
8183 return true;
8186 static bool run_local_memcache(int dummy)
8188 struct memcache *cache;
8189 DATA_BLOB k1, k2;
8190 DATA_BLOB d1, d2, d3;
8191 DATA_BLOB v1, v2, v3;
8193 TALLOC_CTX *mem_ctx;
8194 char *str1, *str2;
8195 size_t size1, size2;
8196 bool ret = false;
8198 cache = memcache_init(NULL, 100);
8200 if (cache == NULL) {
8201 printf("memcache_init failed\n");
8202 return false;
8205 d1 = data_blob_const("d1", 2);
8206 d2 = data_blob_const("d2", 2);
8207 d3 = data_blob_const("d3", 2);
8209 k1 = data_blob_const("d1", 2);
8210 k2 = data_blob_const("d2", 2);
8212 memcache_add(cache, STAT_CACHE, k1, d1);
8213 memcache_add(cache, GETWD_CACHE, k2, d2);
8215 if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
8216 printf("could not find k1\n");
8217 return false;
8219 if (!data_blob_equal(d1, v1)) {
8220 return false;
8223 if (!memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8224 printf("could not find k2\n");
8225 return false;
8227 if (!data_blob_equal(d2, v2)) {
8228 return false;
8231 memcache_add(cache, STAT_CACHE, k1, d3);
8233 if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
8234 printf("could not find replaced k1\n");
8235 return false;
8237 if (!data_blob_equal(d3, v3)) {
8238 return false;
8241 memcache_add(cache, GETWD_CACHE, k1, d1);
8243 if (memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8244 printf("Did find k2, should have been purged\n");
8245 return false;
8248 TALLOC_FREE(cache);
8250 cache = memcache_init(NULL, 0);
8252 mem_ctx = talloc_init("foo");
8254 str1 = talloc_strdup(mem_ctx, "string1");
8255 str2 = talloc_strdup(mem_ctx, "string2");
8257 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8258 data_blob_string_const("torture"), &str1);
8259 size1 = talloc_total_size(cache);
8261 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8262 data_blob_string_const("torture"), &str2);
8263 size2 = talloc_total_size(cache);
8265 printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
8267 if (size2 > size1) {
8268 printf("memcache leaks memory!\n");
8269 goto fail;
8272 ret = true;
8273 fail:
8274 TALLOC_FREE(cache);
8275 return ret;
8278 static void wbclient_done(struct tevent_req *req)
8280 wbcErr wbc_err;
8281 struct winbindd_response *wb_resp;
8282 int *i = (int *)tevent_req_callback_data_void(req);
8284 wbc_err = wb_trans_recv(req, req, &wb_resp);
8285 TALLOC_FREE(req);
8286 *i += 1;
8287 d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
8290 static bool run_local_wbclient(int dummy)
8292 struct event_context *ev;
8293 struct wb_context **wb_ctx;
8294 struct winbindd_request wb_req;
8295 bool result = false;
8296 int i, j;
8298 BlockSignals(True, SIGPIPE);
8300 ev = tevent_context_init_byname(talloc_tos(), "epoll");
8301 if (ev == NULL) {
8302 goto fail;
8305 wb_ctx = talloc_array(ev, struct wb_context *, nprocs);
8306 if (wb_ctx == NULL) {
8307 goto fail;
8310 ZERO_STRUCT(wb_req);
8311 wb_req.cmd = WINBINDD_PING;
8313 d_printf("nprocs=%d, numops=%d\n", (int)nprocs, (int)torture_numops);
8315 for (i=0; i<nprocs; i++) {
8316 wb_ctx[i] = wb_context_init(ev, NULL);
8317 if (wb_ctx[i] == NULL) {
8318 goto fail;
8320 for (j=0; j<torture_numops; j++) {
8321 struct tevent_req *req;
8322 req = wb_trans_send(ev, ev, wb_ctx[i],
8323 (j % 2) == 0, &wb_req);
8324 if (req == NULL) {
8325 goto fail;
8327 tevent_req_set_callback(req, wbclient_done, &i);
8331 i = 0;
8333 while (i < nprocs * torture_numops) {
8334 event_loop_once(ev);
8337 result = true;
8338 fail:
8339 TALLOC_FREE(ev);
8340 return result;
8343 static void getaddrinfo_finished(struct tevent_req *req)
8345 char *name = (char *)tevent_req_callback_data_void(req);
8346 struct addrinfo *ainfo;
8347 int res;
8349 res = getaddrinfo_recv(req, &ainfo);
8350 if (res != 0) {
8351 d_printf("gai(%s) returned %s\n", name, gai_strerror(res));
8352 return;
8354 d_printf("gai(%s) succeeded\n", name);
8355 freeaddrinfo(ainfo);
8358 static bool run_getaddrinfo_send(int dummy)
8360 TALLOC_CTX *frame = talloc_stackframe();
8361 struct fncall_context *ctx;
8362 struct tevent_context *ev;
8363 bool result = false;
8364 const char *names[4] = { "www.samba.org", "notfound.samba.org",
8365 "www.slashdot.org", "heise.de" };
8366 struct tevent_req *reqs[4];
8367 int i;
8369 ev = event_context_init(frame);
8370 if (ev == NULL) {
8371 goto fail;
8374 ctx = fncall_context_init(frame, 4);
8376 for (i=0; i<ARRAY_SIZE(names); i++) {
8377 reqs[i] = getaddrinfo_send(frame, ev, ctx, names[i], NULL,
8378 NULL);
8379 if (reqs[i] == NULL) {
8380 goto fail;
8382 tevent_req_set_callback(reqs[i], getaddrinfo_finished,
8383 discard_const_p(void, names[i]));
8386 for (i=0; i<ARRAY_SIZE(reqs); i++) {
8387 tevent_loop_once(ev);
8390 result = true;
8391 fail:
8392 TALLOC_FREE(frame);
8393 return result;
8396 static bool dbtrans_inc(struct db_context *db)
8398 struct db_record *rec;
8399 uint32_t *val;
8400 bool ret = false;
8401 NTSTATUS status;
8403 rec = db->fetch_locked(db, db, string_term_tdb_data("transtest"));
8404 if (rec == NULL) {
8405 printf(__location__ "fetch_lock failed\n");
8406 return false;
8409 if (rec->value.dsize != sizeof(uint32_t)) {
8410 printf(__location__ "value.dsize = %d\n",
8411 (int)rec->value.dsize);
8412 goto fail;
8415 val = (uint32_t *)rec->value.dptr;
8416 *val += 1;
8418 status = rec->store(rec, make_tdb_data((uint8_t *)val,
8419 sizeof(uint32_t)),
8421 if (!NT_STATUS_IS_OK(status)) {
8422 printf(__location__ "store failed: %s\n",
8423 nt_errstr(status));
8424 goto fail;
8427 ret = true;
8428 fail:
8429 TALLOC_FREE(rec);
8430 return ret;
8433 static bool run_local_dbtrans(int dummy)
8435 struct db_context *db;
8436 struct db_record *rec;
8437 NTSTATUS status;
8438 uint32_t initial;
8439 int res;
8441 db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
8442 O_RDWR|O_CREAT, 0600);
8443 if (db == NULL) {
8444 printf("Could not open transtest.db\n");
8445 return false;
8448 res = db->transaction_start(db);
8449 if (res != 0) {
8450 printf(__location__ "transaction_start failed\n");
8451 return false;
8454 rec = db->fetch_locked(db, db, string_term_tdb_data("transtest"));
8455 if (rec == NULL) {
8456 printf(__location__ "fetch_lock failed\n");
8457 return false;
8460 if (rec->value.dptr == NULL) {
8461 initial = 0;
8462 status = rec->store(
8463 rec, make_tdb_data((uint8_t *)&initial,
8464 sizeof(initial)),
8466 if (!NT_STATUS_IS_OK(status)) {
8467 printf(__location__ "store returned %s\n",
8468 nt_errstr(status));
8469 return false;
8473 TALLOC_FREE(rec);
8475 res = db->transaction_commit(db);
8476 if (res != 0) {
8477 printf(__location__ "transaction_commit failed\n");
8478 return false;
8481 while (true) {
8482 uint32_t val, val2;
8483 int i;
8485 res = db->transaction_start(db);
8486 if (res != 0) {
8487 printf(__location__ "transaction_start failed\n");
8488 break;
8491 if (!dbwrap_fetch_uint32(db, "transtest", &val)) {
8492 printf(__location__ "dbwrap_fetch_uint32 failed\n");
8493 break;
8496 for (i=0; i<10; i++) {
8497 if (!dbtrans_inc(db)) {
8498 return false;
8502 if (!dbwrap_fetch_uint32(db, "transtest", &val2)) {
8503 printf(__location__ "dbwrap_fetch_uint32 failed\n");
8504 break;
8507 if (val2 != val + 10) {
8508 printf(__location__ "val=%d, val2=%d\n",
8509 (int)val, (int)val2);
8510 break;
8513 printf("val2=%d\r", val2);
8515 res = db->transaction_commit(db);
8516 if (res != 0) {
8517 printf(__location__ "transaction_commit failed\n");
8518 break;
8522 TALLOC_FREE(db);
8523 return true;
8527 * Just a dummy test to be run under a debugger. There's no real way
8528 * to inspect the tevent_select specific function from outside of
8529 * tevent_select.c.
8532 static bool run_local_tevent_select(int dummy)
8534 struct tevent_context *ev;
8535 struct tevent_fd *fd1, *fd2;
8536 bool result = false;
8538 ev = tevent_context_init_byname(NULL, "select");
8539 if (ev == NULL) {
8540 d_fprintf(stderr, "tevent_context_init_byname failed\n");
8541 goto fail;
8544 fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
8545 if (fd1 == NULL) {
8546 d_fprintf(stderr, "tevent_add_fd failed\n");
8547 goto fail;
8549 fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
8550 if (fd2 == NULL) {
8551 d_fprintf(stderr, "tevent_add_fd failed\n");
8552 goto fail;
8554 TALLOC_FREE(fd2);
8556 fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
8557 if (fd2 == NULL) {
8558 d_fprintf(stderr, "tevent_add_fd failed\n");
8559 goto fail;
8562 result = true;
8563 fail:
8564 TALLOC_FREE(ev);
8565 return result;
8568 static double create_procs(bool (*fn)(int), bool *result)
8570 int i, status;
8571 volatile pid_t *child_status;
8572 volatile bool *child_status_out;
8573 int synccount;
8574 int tries = 8;
8575 struct timeval start;
8577 synccount = 0;
8579 child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*nprocs);
8580 if (!child_status) {
8581 printf("Failed to setup shared memory\n");
8582 return -1;
8585 child_status_out = (volatile bool *)shm_setup(sizeof(bool)*nprocs);
8586 if (!child_status_out) {
8587 printf("Failed to setup result status shared memory\n");
8588 return -1;
8591 for (i = 0; i < nprocs; i++) {
8592 child_status[i] = 0;
8593 child_status_out[i] = True;
8596 start = timeval_current();
8598 for (i=0;i<nprocs;i++) {
8599 procnum = i;
8600 if (fork() == 0) {
8601 pid_t mypid = getpid();
8602 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
8604 slprintf(myname,sizeof(myname),"CLIENT%d", i);
8606 while (1) {
8607 if (torture_open_connection(&current_cli, i)) break;
8608 if (tries-- == 0) {
8609 printf("pid %d failed to start\n", (int)getpid());
8610 _exit(1);
8612 smb_msleep(10);
8615 child_status[i] = getpid();
8617 while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
8619 child_status_out[i] = fn(i);
8620 _exit(0);
8624 do {
8625 synccount = 0;
8626 for (i=0;i<nprocs;i++) {
8627 if (child_status[i]) synccount++;
8629 if (synccount == nprocs) break;
8630 smb_msleep(10);
8631 } while (timeval_elapsed(&start) < 30);
8633 if (synccount != nprocs) {
8634 printf("FAILED TO START %d CLIENTS (started %d)\n", nprocs, synccount);
8635 *result = False;
8636 return timeval_elapsed(&start);
8639 /* start the client load */
8640 start = timeval_current();
8642 for (i=0;i<nprocs;i++) {
8643 child_status[i] = 0;
8646 printf("%d clients started\n", nprocs);
8648 for (i=0;i<nprocs;i++) {
8649 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
8652 printf("\n");
8654 for (i=0;i<nprocs;i++) {
8655 if (!child_status_out[i]) {
8656 *result = False;
8659 return timeval_elapsed(&start);
8662 #define FLAG_MULTIPROC 1
8664 static struct {
8665 const char *name;
8666 bool (*fn)(int);
8667 unsigned flags;
8668 } torture_ops[] = {
8669 {"FDPASS", run_fdpasstest, 0},
8670 {"LOCK1", run_locktest1, 0},
8671 {"LOCK2", run_locktest2, 0},
8672 {"LOCK3", run_locktest3, 0},
8673 {"LOCK4", run_locktest4, 0},
8674 {"LOCK5", run_locktest5, 0},
8675 {"LOCK6", run_locktest6, 0},
8676 {"LOCK7", run_locktest7, 0},
8677 {"LOCK8", run_locktest8, 0},
8678 {"LOCK9", run_locktest9, 0},
8679 {"UNLINK", run_unlinktest, 0},
8680 {"BROWSE", run_browsetest, 0},
8681 {"ATTR", run_attrtest, 0},
8682 {"TRANS2", run_trans2test, 0},
8683 {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
8684 {"TORTURE",run_torture, FLAG_MULTIPROC},
8685 {"RANDOMIPC", run_randomipc, 0},
8686 {"NEGNOWAIT", run_negprot_nowait, 0},
8687 {"NBENCH", run_nbench, 0},
8688 {"NBENCH2", run_nbench2, 0},
8689 {"OPLOCK1", run_oplock1, 0},
8690 {"OPLOCK2", run_oplock2, 0},
8691 {"OPLOCK4", run_oplock4, 0},
8692 {"DIR", run_dirtest, 0},
8693 {"DIR1", run_dirtest1, 0},
8694 {"DIR-CREATETIME", run_dir_createtime, 0},
8695 {"DENY1", torture_denytest1, 0},
8696 {"DENY2", torture_denytest2, 0},
8697 {"TCON", run_tcon_test, 0},
8698 {"TCONDEV", run_tcon_devtype_test, 0},
8699 {"RW1", run_readwritetest, 0},
8700 {"RW2", run_readwritemulti, FLAG_MULTIPROC},
8701 {"RW3", run_readwritelarge, 0},
8702 {"RW-SIGNING", run_readwritelarge_signtest, 0},
8703 {"OPEN", run_opentest, 0},
8704 {"POSIX", run_simple_posix_open_test, 0},
8705 {"POSIX-APPEND", run_posix_append, 0},
8706 {"CASE-INSENSITIVE-CREATE", run_case_insensitive_create, 0},
8707 {"ASYNC-ECHO", run_async_echo, 0},
8708 { "UID-REGRESSION-TEST", run_uid_regression_test, 0},
8709 { "SHORTNAME-TEST", run_shortname_test, 0},
8710 { "ADDRCHANGE", run_addrchange, 0},
8711 #if 1
8712 {"OPENATTR", run_openattrtest, 0},
8713 #endif
8714 {"XCOPY", run_xcopy, 0},
8715 {"RENAME", run_rename, 0},
8716 {"DELETE", run_deletetest, 0},
8717 {"DELETE-LN", run_deletetest_ln, 0},
8718 {"PROPERTIES", run_properties, 0},
8719 {"MANGLE", torture_mangle, 0},
8720 {"MANGLE1", run_mangle1, 0},
8721 {"W2K", run_w2ktest, 0},
8722 {"TRANS2SCAN", torture_trans2_scan, 0},
8723 {"NTTRANSSCAN", torture_nttrans_scan, 0},
8724 {"UTABLE", torture_utable, 0},
8725 {"CASETABLE", torture_casetable, 0},
8726 {"ERRMAPEXTRACT", run_error_map_extract, 0},
8727 {"PIPE_NUMBER", run_pipe_number, 0},
8728 {"TCON2", run_tcon2_test, 0},
8729 {"IOCTL", torture_ioctl_test, 0},
8730 {"CHKPATH", torture_chkpath_test, 0},
8731 {"FDSESS", run_fdsesstest, 0},
8732 { "EATEST", run_eatest, 0},
8733 { "SESSSETUP_BENCH", run_sesssetup_bench, 0},
8734 { "CHAIN1", run_chain1, 0},
8735 { "CHAIN2", run_chain2, 0},
8736 { "WINDOWS-WRITE", run_windows_write, 0},
8737 { "NTTRANS-CREATE", run_nttrans_create, 0},
8738 { "CLI_ECHO", run_cli_echo, 0},
8739 { "GETADDRINFO", run_getaddrinfo_send, 0},
8740 { "TLDAP", run_tldap },
8741 { "STREAMERROR", run_streamerror },
8742 { "NOTIFY-BENCH", run_notify_bench },
8743 { "BAD-NBT-SESSION", run_bad_nbt_session },
8744 { "SMB-ANY-CONNECT", run_smb_any_connect },
8745 { "NOTIFY-ONLINE", run_notify_online },
8746 { "SMB2-BASIC", run_smb2_basic },
8747 { "LOCAL-SUBSTITUTE", run_local_substitute, 0},
8748 { "LOCAL-GENCACHE", run_local_gencache, 0},
8749 { "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0},
8750 { "LOCAL-BASE64", run_local_base64, 0},
8751 { "LOCAL-RBTREE", run_local_rbtree, 0},
8752 { "LOCAL-MEMCACHE", run_local_memcache, 0},
8753 { "LOCAL-STREAM-NAME", run_local_stream_name, 0},
8754 { "LOCAL-WBCLIENT", run_local_wbclient, 0},
8755 { "LOCAL-string_to_sid", run_local_string_to_sid, 0},
8756 { "LOCAL-binary_to_sid", run_local_binary_to_sid, 0},
8757 { "LOCAL-DBTRANS", run_local_dbtrans, 0},
8758 { "LOCAL-TEVENT-SELECT", run_local_tevent_select, 0},
8759 { "LOCAL-CONVERT-STRING", run_local_convert_string, 0},
8760 {NULL, NULL, 0}};
8764 /****************************************************************************
8765 run a specified test or "ALL"
8766 ****************************************************************************/
8767 static bool run_test(const char *name)
8769 bool ret = True;
8770 bool result = True;
8771 bool found = False;
8772 int i;
8773 double t;
8774 if (strequal(name,"ALL")) {
8775 for (i=0;torture_ops[i].name;i++) {
8776 run_test(torture_ops[i].name);
8778 found = True;
8781 for (i=0;torture_ops[i].name;i++) {
8782 fstr_sprintf(randomfname, "\\XX%x",
8783 (unsigned)random());
8785 if (strequal(name, torture_ops[i].name)) {
8786 found = True;
8787 printf("Running %s\n", name);
8788 if (torture_ops[i].flags & FLAG_MULTIPROC) {
8789 t = create_procs(torture_ops[i].fn, &result);
8790 if (!result) {
8791 ret = False;
8792 printf("TEST %s FAILED!\n", name);
8794 } else {
8795 struct timeval start;
8796 start = timeval_current();
8797 if (!torture_ops[i].fn(0)) {
8798 ret = False;
8799 printf("TEST %s FAILED!\n", name);
8801 t = timeval_elapsed(&start);
8803 printf("%s took %g secs\n\n", name, t);
8807 if (!found) {
8808 printf("Did not find a test named %s\n", name);
8809 ret = False;
8812 return ret;
8816 static void usage(void)
8818 int i;
8820 printf("WARNING samba4 test suite is much more complete nowadays.\n");
8821 printf("Please use samba4 torture.\n\n");
8823 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
8825 printf("\t-d debuglevel\n");
8826 printf("\t-U user%%pass\n");
8827 printf("\t-k use kerberos\n");
8828 printf("\t-N numprocs\n");
8829 printf("\t-n my_netbios_name\n");
8830 printf("\t-W workgroup\n");
8831 printf("\t-o num_operations\n");
8832 printf("\t-O socket_options\n");
8833 printf("\t-m maximum protocol\n");
8834 printf("\t-L use oplocks\n");
8835 printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
8836 printf("\t-A showall\n");
8837 printf("\t-p port\n");
8838 printf("\t-s seed\n");
8839 printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
8840 printf("\t-f filename filename to test\n");
8841 printf("\n\n");
8843 printf("tests are:");
8844 for (i=0;torture_ops[i].name;i++) {
8845 printf(" %s", torture_ops[i].name);
8847 printf("\n");
8849 printf("default test is ALL\n");
8851 exit(1);
8854 /****************************************************************************
8855 main program
8856 ****************************************************************************/
8857 int main(int argc,char *argv[])
8859 int opt, i;
8860 char *p;
8861 int gotuser = 0;
8862 int gotpass = 0;
8863 bool correct = True;
8864 TALLOC_CTX *frame = talloc_stackframe();
8865 int seed = time(NULL);
8867 #ifdef HAVE_SETBUFFER
8868 setbuffer(stdout, NULL, 0);
8869 #endif
8871 setup_logging("smbtorture", DEBUG_STDOUT);
8873 load_case_tables();
8875 if (is_default_dyn_CONFIGFILE()) {
8876 if(getenv("SMB_CONF_PATH")) {
8877 set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
8880 lp_load(get_dyn_CONFIGFILE(),True,False,False,True);
8881 load_interfaces();
8883 if (argc < 2) {
8884 usage();
8887 for(p = argv[1]; *p; p++)
8888 if(*p == '\\')
8889 *p = '/';
8891 if (strncmp(argv[1], "//", 2)) {
8892 usage();
8895 fstrcpy(host, &argv[1][2]);
8896 p = strchr_m(&host[2],'/');
8897 if (!p) {
8898 usage();
8900 *p = 0;
8901 fstrcpy(share, p+1);
8903 fstrcpy(myname, get_myname(talloc_tos()));
8904 if (!*myname) {
8905 fprintf(stderr, "Failed to get my hostname.\n");
8906 return 1;
8909 if (*username == 0 && getenv("LOGNAME")) {
8910 fstrcpy(username,getenv("LOGNAME"));
8913 argc--;
8914 argv++;
8916 fstrcpy(workgroup, lp_workgroup());
8918 while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
8919 != EOF) {
8920 switch (opt) {
8921 case 'p':
8922 port_to_use = atoi(optarg);
8923 break;
8924 case 's':
8925 seed = atoi(optarg);
8926 break;
8927 case 'W':
8928 fstrcpy(workgroup,optarg);
8929 break;
8930 case 'm':
8931 max_protocol = interpret_protocol(optarg, max_protocol);
8932 break;
8933 case 'N':
8934 nprocs = atoi(optarg);
8935 break;
8936 case 'o':
8937 torture_numops = atoi(optarg);
8938 break;
8939 case 'd':
8940 lp_set_cmdline("log level", optarg);
8941 break;
8942 case 'O':
8943 sockops = optarg;
8944 break;
8945 case 'L':
8946 use_oplocks = True;
8947 break;
8948 case 'l':
8949 local_path = optarg;
8950 break;
8951 case 'A':
8952 torture_showall = True;
8953 break;
8954 case 'n':
8955 fstrcpy(myname, optarg);
8956 break;
8957 case 'c':
8958 client_txt = optarg;
8959 break;
8960 case 'e':
8961 do_encrypt = true;
8962 break;
8963 case 'k':
8964 #ifdef HAVE_KRB5
8965 use_kerberos = True;
8966 #else
8967 d_printf("No kerberos support compiled in\n");
8968 exit(1);
8969 #endif
8970 break;
8971 case 'U':
8972 gotuser = 1;
8973 fstrcpy(username,optarg);
8974 p = strchr_m(username,'%');
8975 if (p) {
8976 *p = 0;
8977 fstrcpy(password, p+1);
8978 gotpass = 1;
8980 break;
8981 case 'b':
8982 fstrcpy(multishare_conn_fname, optarg);
8983 use_multishare_conn = True;
8984 break;
8985 case 'B':
8986 torture_blocksize = atoi(optarg);
8987 break;
8988 case 'f':
8989 test_filename = SMB_STRDUP(optarg);
8990 break;
8991 default:
8992 printf("Unknown option %c (%d)\n", (char)opt, opt);
8993 usage();
8997 d_printf("using seed %d\n", seed);
8999 srandom(seed);
9001 if(use_kerberos && !gotuser) gotpass = True;
9003 while (!gotpass) {
9004 p = getpass("Password:");
9005 if (p) {
9006 fstrcpy(password, p);
9007 gotpass = 1;
9011 printf("host=%s share=%s user=%s myname=%s\n",
9012 host, share, username, myname);
9014 if (argc == optind) {
9015 correct = run_test("ALL");
9016 } else {
9017 for (i=optind;i<argc;i++) {
9018 if (!run_test(argv[i])) {
9019 correct = False;
9024 TALLOC_FREE(frame);
9026 if (correct) {
9027 return(0);
9028 } else {
9029 return(1);