s3:torture: s/Undefined/SMB_SIGNING_DEFAULT/ s/Required/SMB_SIGNING_REQUIRED/
[Samba/gebeck_regimport.git] / source3 / torture / torture.c
blob4a5f7908a314a40c859e34a3bf38634fdf10ad7a
1 /*
2 Unix SMB/CIFS implementation.
3 SMB torture tester
4 Copyright (C) Andrew Tridgell 1997-1998
5 Copyright (C) Jeremy Allison 2009
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
22 #include "system/shmem.h"
23 #include "wbc_async.h"
24 #include "torture/proto.h"
25 #include "libcli/security/security.h"
26 #include "tldap.h"
27 #include "tldap_util.h"
28 #include "../librpc/gen_ndr/svcctl.h"
29 #include "memcache.h"
30 #include "nsswitch/winbind_client.h"
31 #include "dbwrap/dbwrap.h"
32 #include "dbwrap/dbwrap_open.h"
33 #include "dbwrap/dbwrap_rbt.h"
34 #include "talloc_dict.h"
35 #include "async_smb.h"
36 #include "libsmb/libsmb.h"
37 #include "libsmb/clirap.h"
38 #include "trans2.h"
39 #include "libsmb/nmblib.h"
40 #include "../lib/util/tevent_ntstatus.h"
41 #include "util_tdb.h"
42 #include "../libcli/smb/read_smb.h"
44 extern char *optarg;
45 extern int optind;
47 fstring host, workgroup, share, password, username, myname;
48 static int max_protocol = PROTOCOL_NT1;
49 static const char *sockops="TCP_NODELAY";
50 static int nprocs=1;
51 static int port_to_use=0;
52 int torture_numops=100;
53 int torture_blocksize=1024*1024;
54 static int procnum; /* records process count number when forking */
55 static struct cli_state *current_cli;
56 static fstring randomfname;
57 static bool use_oplocks;
58 static bool use_level_II_oplocks;
59 static const char *client_txt = "client_oplocks.txt";
60 static bool disable_spnego;
61 static bool use_kerberos;
62 static bool force_dos_errors;
63 static fstring multishare_conn_fname;
64 static bool use_multishare_conn = False;
65 static bool do_encrypt;
66 static const char *local_path = NULL;
67 static int signing_state = SMB_SIGNING_DEFAULT;
68 char *test_filename;
70 bool torture_showall = False;
72 static double create_procs(bool (*fn)(int), bool *result);
75 /* return a pointer to a anonymous shared memory segment of size "size"
76 which will persist across fork() but will disappear when all processes
77 exit
79 The memory is not zeroed
81 This function uses system5 shared memory. It takes advantage of a property
82 that the memory is not destroyed if it is attached when the id is removed
84 void *shm_setup(int size)
86 int shmid;
87 void *ret;
89 #ifdef __QNXNTO__
90 shmid = shm_open("private", O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
91 if (shmid == -1) {
92 printf("can't get shared memory\n");
93 exit(1);
95 shm_unlink("private");
96 if (ftruncate(shmid, size) == -1) {
97 printf("can't set shared memory size\n");
98 exit(1);
100 ret = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, shmid, 0);
101 if (ret == MAP_FAILED) {
102 printf("can't map shared memory\n");
103 exit(1);
105 #else
106 shmid = shmget(IPC_PRIVATE, size, S_IRUSR | S_IWUSR);
107 if (shmid == -1) {
108 printf("can't get shared memory\n");
109 exit(1);
111 ret = (void *)shmat(shmid, 0, 0);
112 if (!ret || ret == (void *)-1) {
113 printf("can't attach to shared memory\n");
114 return NULL;
116 /* the following releases the ipc, but note that this process
117 and all its children will still have access to the memory, its
118 just that the shmid is no longer valid for other shm calls. This
119 means we don't leave behind lots of shm segments after we exit
121 See Stevens "advanced programming in unix env" for details
123 shmctl(shmid, IPC_RMID, 0);
124 #endif
126 return ret;
129 /********************************************************************
130 Ensure a connection is encrypted.
131 ********************************************************************/
133 static bool force_cli_encryption(struct cli_state *c,
134 const char *sharename)
136 uint16 major, minor;
137 uint32 caplow, caphigh;
138 NTSTATUS status;
140 if (!SERVER_HAS_UNIX_CIFS(c)) {
141 d_printf("Encryption required and "
142 "server that doesn't support "
143 "UNIX extensions - failing connect\n");
144 return false;
147 status = cli_unix_extensions_version(c, &major, &minor, &caplow,
148 &caphigh);
149 if (!NT_STATUS_IS_OK(status)) {
150 d_printf("Encryption required and "
151 "can't get UNIX CIFS extensions "
152 "version from server: %s\n", nt_errstr(status));
153 return false;
156 if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
157 d_printf("Encryption required and "
158 "share %s doesn't support "
159 "encryption.\n", sharename);
160 return false;
163 if (c->use_kerberos) {
164 status = cli_gss_smb_encryption_start(c);
165 } else {
166 status = cli_raw_ntlm_smb_encryption_start(c,
167 username,
168 password,
169 workgroup);
172 if (!NT_STATUS_IS_OK(status)) {
173 d_printf("Encryption required and "
174 "setup failed with error %s.\n",
175 nt_errstr(status));
176 return false;
179 return true;
183 static struct cli_state *open_nbt_connection(void)
185 struct cli_state *c;
186 NTSTATUS status;
187 int flags = 0;
189 if (disable_spnego) {
190 flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
193 if (use_oplocks) {
194 flags |= CLI_FULL_CONNECTION_OPLOCKS;
197 if (use_level_II_oplocks) {
198 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
201 if (use_kerberos) {
202 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
205 if (force_dos_errors) {
206 flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
209 status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
210 signing_state, flags, &c);
211 if (!NT_STATUS_IS_OK(status)) {
212 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
213 return NULL;
216 cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
218 return c;
221 /****************************************************************************
222 Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
223 ****************************************************************************/
225 static bool cli_bad_session_request(int fd,
226 struct nmb_name *calling, struct nmb_name *called)
228 TALLOC_CTX *frame;
229 uint8_t len_buf[4];
230 struct iovec iov[3];
231 ssize_t len;
232 uint8_t *inbuf;
233 int err;
234 bool ret = false;
235 uint8_t message_type;
236 uint8_t error;
237 struct event_context *ev;
238 struct tevent_req *req;
240 frame = talloc_stackframe();
242 iov[0].iov_base = len_buf;
243 iov[0].iov_len = sizeof(len_buf);
245 /* put in the destination name */
247 iov[1].iov_base = name_mangle(talloc_tos(), called->name,
248 called->name_type);
249 if (iov[1].iov_base == NULL) {
250 goto fail;
252 iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
253 talloc_get_size(iov[1].iov_base));
255 /* and my name */
257 iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
258 calling->name_type);
259 if (iov[2].iov_base == NULL) {
260 goto fail;
262 iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
263 talloc_get_size(iov[2].iov_base));
265 /* Deliberately corrupt the name len (first byte) */
266 *((uint8_t *)iov[2].iov_base) = 100;
268 /* send a session request (RFC 1002) */
269 /* setup the packet length
270 * Remove four bytes from the length count, since the length
271 * field in the NBT Session Service header counts the number
272 * of bytes which follow. The cli_send_smb() function knows
273 * about this and accounts for those four bytes.
274 * CRH.
277 _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
278 SCVAL(len_buf,0,0x81);
280 len = write_data_iov(fd, iov, 3);
281 if (len == -1) {
282 goto fail;
285 ev = event_context_init(frame);
286 if (ev == NULL) {
287 goto fail;
289 req = read_smb_send(frame, ev, fd);
290 if (req == NULL) {
291 goto fail;
293 if (!tevent_req_poll(req, ev)) {
294 goto fail;
296 len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
297 if (len == -1) {
298 errno = err;
299 goto fail;
301 TALLOC_FREE(ev);
303 message_type = CVAL(inbuf, 0);
304 if (message_type != 0x83) {
305 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
306 message_type);
307 goto fail;
310 if (smb_len(inbuf) != 1) {
311 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
312 (int)smb_len(inbuf));
313 goto fail;
316 error = CVAL(inbuf, 4);
317 if (error != 0x82) {
318 d_fprintf(stderr, "Expected error 0x82, got %d\n",
319 (int)error);
320 goto fail;
323 ret = true;
324 fail:
325 TALLOC_FREE(frame);
326 return ret;
329 /* Insert a NULL at the first separator of the given path and return a pointer
330 * to the remainder of the string.
332 static char *
333 terminate_path_at_separator(char * path)
335 char * p;
337 if (!path) {
338 return NULL;
341 if ((p = strchr_m(path, '/'))) {
342 *p = '\0';
343 return p + 1;
346 if ((p = strchr_m(path, '\\'))) {
347 *p = '\0';
348 return p + 1;
351 /* No separator. */
352 return NULL;
356 parse a //server/share type UNC name
358 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
359 char **hostname, char **sharename)
361 char *p;
363 *hostname = *sharename = NULL;
365 if (strncmp(unc_name, "\\\\", 2) &&
366 strncmp(unc_name, "//", 2)) {
367 return False;
370 *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
371 p = terminate_path_at_separator(*hostname);
373 if (p && *p) {
374 *sharename = talloc_strdup(mem_ctx, p);
375 terminate_path_at_separator(*sharename);
378 if (*hostname && *sharename) {
379 return True;
382 TALLOC_FREE(*hostname);
383 TALLOC_FREE(*sharename);
384 return False;
387 static bool torture_open_connection_share(struct cli_state **c,
388 const char *hostname,
389 const char *sharename)
391 int flags = 0;
392 NTSTATUS status;
394 if (use_kerberos)
395 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
396 if (use_oplocks)
397 flags |= CLI_FULL_CONNECTION_OPLOCKS;
398 if (use_level_II_oplocks)
399 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
401 status = cli_full_connection(c, myname,
402 hostname, NULL, port_to_use,
403 sharename, "?????",
404 username, workgroup,
405 password, flags, signing_state);
406 if (!NT_STATUS_IS_OK(status)) {
407 printf("failed to open share connection: //%s/%s port:%d - %s\n",
408 hostname, sharename, port_to_use, nt_errstr(status));
409 return False;
412 cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
414 if (do_encrypt) {
415 return force_cli_encryption(*c,
416 sharename);
418 return True;
421 bool torture_open_connection(struct cli_state **c, int conn_index)
423 char **unc_list = NULL;
424 int num_unc_names = 0;
425 bool result;
427 if (use_multishare_conn==True) {
428 char *h, *s;
429 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
430 if (!unc_list || num_unc_names <= 0) {
431 printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
432 exit(1);
435 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
436 NULL, &h, &s)) {
437 printf("Failed to parse UNC name %s\n",
438 unc_list[conn_index % num_unc_names]);
439 TALLOC_FREE(unc_list);
440 exit(1);
443 result = torture_open_connection_share(c, h, s);
445 /* h, s were copied earlier */
446 TALLOC_FREE(unc_list);
447 return result;
450 return torture_open_connection_share(c, host, share);
453 bool torture_init_connection(struct cli_state **pcli)
455 struct cli_state *cli;
457 cli = open_nbt_connection();
458 if (cli == NULL) {
459 return false;
462 *pcli = cli;
463 return true;
466 bool torture_cli_session_setup2(struct cli_state *cli, uint16 *new_vuid)
468 uint16_t old_vuid = cli_state_get_uid(cli);
469 fstring old_user_name;
470 size_t passlen = strlen(password);
471 NTSTATUS status;
472 bool ret;
474 fstrcpy(old_user_name, cli->user_name);
475 cli_state_set_uid(cli, 0);
476 ret = NT_STATUS_IS_OK(cli_session_setup(cli, username,
477 password, passlen,
478 password, passlen,
479 workgroup));
480 *new_vuid = cli_state_get_uid(cli);
481 cli_state_set_uid(cli, old_vuid);
482 status = cli_set_username(cli, old_user_name);
483 if (!NT_STATUS_IS_OK(status)) {
484 return false;
486 return ret;
490 bool torture_close_connection(struct cli_state *c)
492 bool ret = True;
493 NTSTATUS status;
495 status = cli_tdis(c);
496 if (!NT_STATUS_IS_OK(status)) {
497 printf("tdis failed (%s)\n", nt_errstr(status));
498 ret = False;
501 cli_shutdown(c);
503 return ret;
507 /* check if the server produced the expected dos or nt error code */
508 static bool check_both_error(int line, NTSTATUS status,
509 uint8 eclass, uint32 ecode, NTSTATUS nterr)
511 if (NT_STATUS_IS_DOS(status)) {
512 uint8 cclass;
513 uint32 num;
515 /* Check DOS error */
516 cclass = NT_STATUS_DOS_CLASS(status);
517 num = NT_STATUS_DOS_CODE(status);
519 if (eclass != cclass || ecode != num) {
520 printf("unexpected error code class=%d code=%d\n",
521 (int)cclass, (int)num);
522 printf(" expected %d/%d %s (line=%d)\n",
523 (int)eclass, (int)ecode, nt_errstr(nterr), line);
524 return false;
526 } else {
527 /* Check NT error */
528 if (!NT_STATUS_EQUAL(nterr, status)) {
529 printf("unexpected error code %s\n",
530 nt_errstr(status));
531 printf(" expected %s (line=%d)\n",
532 nt_errstr(nterr), line);
533 return false;
537 return true;
541 /* check if the server produced the expected error code */
542 static bool check_error(int line, NTSTATUS status,
543 uint8 eclass, uint32 ecode, NTSTATUS nterr)
545 if (NT_STATUS_IS_DOS(status)) {
546 uint8 cclass;
547 uint32 num;
549 /* Check DOS error */
551 cclass = NT_STATUS_DOS_CLASS(status);
552 num = NT_STATUS_DOS_CODE(status);
554 if (eclass != cclass || ecode != num) {
555 printf("unexpected error code class=%d code=%d\n",
556 (int)cclass, (int)num);
557 printf(" expected %d/%d %s (line=%d)\n",
558 (int)eclass, (int)ecode, nt_errstr(nterr),
559 line);
560 return False;
563 } else {
564 /* Check NT error */
566 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
567 printf("unexpected error code %s\n",
568 nt_errstr(status));
569 printf(" expected %s (line=%d)\n", nt_errstr(nterr),
570 line);
571 return False;
575 return True;
579 static bool wait_lock(struct cli_state *c, int fnum, uint32 offset, uint32 len)
581 NTSTATUS status;
583 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
585 while (!NT_STATUS_IS_OK(status)) {
586 if (!check_both_error(__LINE__, status, ERRDOS,
587 ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
588 return false;
591 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
594 return true;
598 static bool rw_torture(struct cli_state *c)
600 const char *lockfname = "\\torture.lck";
601 fstring fname;
602 uint16_t fnum;
603 uint16_t fnum2;
604 pid_t pid2, pid = getpid();
605 int i, j;
606 char buf[1024];
607 bool correct = True;
608 size_t nread = 0;
609 NTSTATUS status;
611 memset(buf, '\0', sizeof(buf));
613 status = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
614 DENY_NONE, &fnum2);
615 if (!NT_STATUS_IS_OK(status)) {
616 status = cli_open(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
618 if (!NT_STATUS_IS_OK(status)) {
619 printf("open of %s failed (%s)\n",
620 lockfname, nt_errstr(status));
621 return False;
624 for (i=0;i<torture_numops;i++) {
625 unsigned n = (unsigned)sys_random()%10;
627 if (i % 10 == 0) {
628 printf("%d\r", i); fflush(stdout);
630 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
632 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
633 return False;
636 status = cli_open(c, fname, O_RDWR | O_CREAT | O_TRUNC,
637 DENY_ALL, &fnum);
638 if (!NT_STATUS_IS_OK(status)) {
639 printf("open failed (%s)\n", nt_errstr(status));
640 correct = False;
641 break;
644 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
645 sizeof(pid), NULL);
646 if (!NT_STATUS_IS_OK(status)) {
647 printf("write failed (%s)\n", nt_errstr(status));
648 correct = False;
651 for (j=0;j<50;j++) {
652 status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
653 sizeof(pid)+(j*sizeof(buf)),
654 sizeof(buf), NULL);
655 if (!NT_STATUS_IS_OK(status)) {
656 printf("write failed (%s)\n",
657 nt_errstr(status));
658 correct = False;
662 pid2 = 0;
664 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
665 &nread);
666 if (!NT_STATUS_IS_OK(status)) {
667 printf("read failed (%s)\n", nt_errstr(status));
668 correct = false;
669 } else if (nread != sizeof(pid)) {
670 printf("read/write compare failed: "
671 "recv %ld req %ld\n", (unsigned long)nread,
672 (unsigned long)sizeof(pid));
673 correct = false;
676 if (pid2 != pid) {
677 printf("data corruption!\n");
678 correct = False;
681 status = cli_close(c, fnum);
682 if (!NT_STATUS_IS_OK(status)) {
683 printf("close failed (%s)\n", nt_errstr(status));
684 correct = False;
687 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
688 if (!NT_STATUS_IS_OK(status)) {
689 printf("unlink failed (%s)\n", nt_errstr(status));
690 correct = False;
693 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
694 if (!NT_STATUS_IS_OK(status)) {
695 printf("unlock failed (%s)\n", nt_errstr(status));
696 correct = False;
700 cli_close(c, fnum2);
701 cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
703 printf("%d\n", i);
705 return correct;
708 static bool run_torture(int dummy)
710 struct cli_state *cli;
711 bool ret;
713 cli = current_cli;
715 cli_sockopt(cli, sockops);
717 ret = rw_torture(cli);
719 if (!torture_close_connection(cli)) {
720 ret = False;
723 return ret;
726 static bool rw_torture3(struct cli_state *c, char *lockfname)
728 uint16_t fnum = (uint16_t)-1;
729 unsigned int i = 0;
730 char buf[131072];
731 char buf_rd[131072];
732 unsigned count;
733 unsigned countprev = 0;
734 size_t sent = 0;
735 bool correct = True;
736 NTSTATUS status = NT_STATUS_OK;
738 srandom(1);
739 for (i = 0; i < sizeof(buf); i += sizeof(uint32))
741 SIVAL(buf, i, sys_random());
744 if (procnum == 0)
746 status = cli_unlink(
747 c, lockfname,
748 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
749 if (!NT_STATUS_IS_OK(status)) {
750 printf("unlink failed (%s) (normal, this file should "
751 "not exist)\n", nt_errstr(status));
754 status = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
755 DENY_NONE, &fnum);
756 if (!NT_STATUS_IS_OK(status)) {
757 printf("first open read/write of %s failed (%s)\n",
758 lockfname, nt_errstr(status));
759 return False;
762 else
764 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
766 status = cli_open(c, lockfname, O_RDONLY,
767 DENY_NONE, &fnum);
768 if (!NT_STATUS_IS_OK(status)) {
769 break;
771 smb_msleep(10);
773 if (!NT_STATUS_IS_OK(status)) {
774 printf("second open read-only of %s failed (%s)\n",
775 lockfname, nt_errstr(status));
776 return False;
780 i = 0;
781 for (count = 0; count < sizeof(buf); count += sent)
783 if (count >= countprev) {
784 printf("%d %8d\r", i, count);
785 fflush(stdout);
786 i++;
787 countprev += (sizeof(buf) / 20);
790 if (procnum == 0)
792 sent = ((unsigned)sys_random()%(20))+ 1;
793 if (sent > sizeof(buf) - count)
795 sent = sizeof(buf) - count;
798 status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
799 count, sent, NULL);
800 if (!NT_STATUS_IS_OK(status)) {
801 printf("write failed (%s)\n",
802 nt_errstr(status));
803 correct = False;
806 else
808 status = cli_read(c, fnum, buf_rd+count, count,
809 sizeof(buf)-count, &sent);
810 if(!NT_STATUS_IS_OK(status)) {
811 printf("read failed offset:%d size:%ld (%s)\n",
812 count, (unsigned long)sizeof(buf)-count,
813 nt_errstr(status));
814 correct = False;
815 sent = 0;
816 } else if (sent > 0) {
817 if (memcmp(buf_rd+count, buf+count, sent) != 0)
819 printf("read/write compare failed\n");
820 printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
821 correct = False;
822 break;
829 status = cli_close(c, fnum);
830 if (!NT_STATUS_IS_OK(status)) {
831 printf("close failed (%s)\n", nt_errstr(status));
832 correct = False;
835 return correct;
838 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
840 const char *lockfname = "\\torture2.lck";
841 uint16_t fnum1;
842 uint16_t fnum2;
843 int i;
844 char buf[131072];
845 char buf_rd[131072];
846 bool correct = True;
847 size_t bytes_read;
848 NTSTATUS status;
850 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
851 if (!NT_STATUS_IS_OK(status)) {
852 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
855 status = cli_open(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
856 DENY_NONE, &fnum1);
857 if (!NT_STATUS_IS_OK(status)) {
858 printf("first open read/write of %s failed (%s)\n",
859 lockfname, nt_errstr(status));
860 return False;
863 status = cli_open(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
864 if (!NT_STATUS_IS_OK(status)) {
865 printf("second open read-only of %s failed (%s)\n",
866 lockfname, nt_errstr(status));
867 cli_close(c1, fnum1);
868 return False;
871 for (i = 0; i < torture_numops; i++)
873 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
874 if (i % 10 == 0) {
875 printf("%d\r", i); fflush(stdout);
878 generate_random_buffer((unsigned char *)buf, buf_size);
880 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
881 buf_size, NULL);
882 if (!NT_STATUS_IS_OK(status)) {
883 printf("write failed (%s)\n", nt_errstr(status));
884 correct = False;
885 break;
888 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
889 if(!NT_STATUS_IS_OK(status)) {
890 printf("read failed (%s)\n", nt_errstr(status));
891 correct = false;
892 break;
893 } else if (bytes_read != buf_size) {
894 printf("read failed\n");
895 printf("read %ld, expected %ld\n",
896 (unsigned long)bytes_read,
897 (unsigned long)buf_size);
898 correct = False;
899 break;
902 if (memcmp(buf_rd, buf, buf_size) != 0)
904 printf("read/write compare failed\n");
905 correct = False;
906 break;
910 status = cli_close(c2, fnum2);
911 if (!NT_STATUS_IS_OK(status)) {
912 printf("close failed (%s)\n", nt_errstr(status));
913 correct = False;
916 status = cli_close(c1, fnum1);
917 if (!NT_STATUS_IS_OK(status)) {
918 printf("close failed (%s)\n", nt_errstr(status));
919 correct = False;
922 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
923 if (!NT_STATUS_IS_OK(status)) {
924 printf("unlink failed (%s)\n", nt_errstr(status));
925 correct = False;
928 return correct;
931 static bool run_readwritetest(int dummy)
933 struct cli_state *cli1, *cli2;
934 bool test1, test2 = False;
936 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
937 return False;
939 cli_sockopt(cli1, sockops);
940 cli_sockopt(cli2, sockops);
942 printf("starting readwritetest\n");
944 test1 = rw_torture2(cli1, cli2);
945 printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
947 if (test1) {
948 test2 = rw_torture2(cli1, cli1);
949 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
952 if (!torture_close_connection(cli1)) {
953 test1 = False;
956 if (!torture_close_connection(cli2)) {
957 test2 = False;
960 return (test1 && test2);
963 static bool run_readwritemulti(int dummy)
965 struct cli_state *cli;
966 bool test;
968 cli = current_cli;
970 cli_sockopt(cli, sockops);
972 printf("run_readwritemulti: fname %s\n", randomfname);
973 test = rw_torture3(cli, randomfname);
975 if (!torture_close_connection(cli)) {
976 test = False;
979 return test;
982 static bool run_readwritelarge_internal(void)
984 static struct cli_state *cli1;
985 uint16_t fnum1;
986 const char *lockfname = "\\large.dat";
987 SMB_OFF_T fsize;
988 char buf[126*1024];
989 bool correct = True;
990 NTSTATUS status;
992 if (!torture_open_connection(&cli1, 0)) {
993 return False;
995 cli_sockopt(cli1, sockops);
996 memset(buf,'\0',sizeof(buf));
998 printf("starting readwritelarge_internal\n");
1000 cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
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 cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
1011 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1012 NULL, NULL, NULL);
1013 if (!NT_STATUS_IS_OK(status)) {
1014 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1015 correct = False;
1018 if (fsize == sizeof(buf))
1019 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
1020 (unsigned long)fsize);
1021 else {
1022 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
1023 (unsigned long)fsize);
1024 correct = False;
1027 status = cli_close(cli1, fnum1);
1028 if (!NT_STATUS_IS_OK(status)) {
1029 printf("close failed (%s)\n", nt_errstr(status));
1030 correct = False;
1033 status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1034 if (!NT_STATUS_IS_OK(status)) {
1035 printf("unlink failed (%s)\n", nt_errstr(status));
1036 correct = False;
1039 status = cli_open(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1040 DENY_NONE, &fnum1);
1041 if (!NT_STATUS_IS_OK(status)) {
1042 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1043 return False;
1046 cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1048 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1049 NULL, NULL, NULL);
1050 if (!NT_STATUS_IS_OK(status)) {
1051 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1052 correct = False;
1055 if (fsize == sizeof(buf))
1056 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1057 (unsigned long)fsize);
1058 else {
1059 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1060 (unsigned long)fsize);
1061 correct = False;
1064 #if 0
1065 /* ToDo - set allocation. JRA */
1066 if(!cli_set_allocation_size(cli1, fnum1, 0)) {
1067 printf("set allocation size to zero failed (%s)\n", cli_errstr(&cli1));
1068 return False;
1070 if (!cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL, NULL,
1071 NULL, NULL)) {
1072 printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
1073 correct = False;
1075 if (fsize != 0)
1076 printf("readwritelarge test 3 (truncate test) succeeded (size = %x)\n", fsize);
1077 #endif
1079 status = cli_close(cli1, fnum1);
1080 if (!NT_STATUS_IS_OK(status)) {
1081 printf("close failed (%s)\n", nt_errstr(status));
1082 correct = False;
1085 if (!torture_close_connection(cli1)) {
1086 correct = False;
1088 return correct;
1091 static bool run_readwritelarge(int dummy)
1093 return run_readwritelarge_internal();
1096 static bool run_readwritelarge_signtest(int dummy)
1098 bool ret;
1099 signing_state = SMB_SIGNING_REQUIRED;
1100 ret = run_readwritelarge_internal();
1101 signing_state = SMB_SIGNING_DEFAULT;
1102 return ret;
1105 int line_count = 0;
1106 int nbio_id;
1108 #define ival(s) strtol(s, NULL, 0)
1110 /* run a test that simulates an approximate netbench client load */
1111 static bool run_netbench(int client)
1113 struct cli_state *cli;
1114 int i;
1115 char line[1024];
1116 char cname[20];
1117 FILE *f;
1118 const char *params[20];
1119 bool correct = True;
1121 cli = current_cli;
1123 nbio_id = client;
1125 cli_sockopt(cli, sockops);
1127 nb_setup(cli);
1129 slprintf(cname,sizeof(cname)-1, "client%d", client);
1131 f = fopen(client_txt, "r");
1133 if (!f) {
1134 perror(client_txt);
1135 return False;
1138 while (fgets(line, sizeof(line)-1, f)) {
1139 char *saveptr;
1140 line_count++;
1142 line[strlen(line)-1] = 0;
1144 /* printf("[%d] %s\n", line_count, line); */
1146 all_string_sub(line,"client1", cname, sizeof(line));
1148 /* parse the command parameters */
1149 params[0] = strtok_r(line, " ", &saveptr);
1150 i = 0;
1151 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1153 params[i] = "";
1155 if (i < 2) continue;
1157 if (!strncmp(params[0],"SMB", 3)) {
1158 printf("ERROR: You are using a dbench 1 load file\n");
1159 exit(1);
1162 if (!strcmp(params[0],"NTCreateX")) {
1163 nb_createx(params[1], ival(params[2]), ival(params[3]),
1164 ival(params[4]));
1165 } else if (!strcmp(params[0],"Close")) {
1166 nb_close(ival(params[1]));
1167 } else if (!strcmp(params[0],"Rename")) {
1168 nb_rename(params[1], params[2]);
1169 } else if (!strcmp(params[0],"Unlink")) {
1170 nb_unlink(params[1]);
1171 } else if (!strcmp(params[0],"Deltree")) {
1172 nb_deltree(params[1]);
1173 } else if (!strcmp(params[0],"Rmdir")) {
1174 nb_rmdir(params[1]);
1175 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1176 nb_qpathinfo(params[1]);
1177 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1178 nb_qfileinfo(ival(params[1]));
1179 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1180 nb_qfsinfo(ival(params[1]));
1181 } else if (!strcmp(params[0],"FIND_FIRST")) {
1182 nb_findfirst(params[1]);
1183 } else if (!strcmp(params[0],"WriteX")) {
1184 nb_writex(ival(params[1]),
1185 ival(params[2]), ival(params[3]), ival(params[4]));
1186 } else if (!strcmp(params[0],"ReadX")) {
1187 nb_readx(ival(params[1]),
1188 ival(params[2]), ival(params[3]), ival(params[4]));
1189 } else if (!strcmp(params[0],"Flush")) {
1190 nb_flush(ival(params[1]));
1191 } else {
1192 printf("Unknown operation %s\n", params[0]);
1193 exit(1);
1196 fclose(f);
1198 nb_cleanup();
1200 if (!torture_close_connection(cli)) {
1201 correct = False;
1204 return correct;
1208 /* run a test that simulates an approximate netbench client load */
1209 static bool run_nbench(int dummy)
1211 double t;
1212 bool correct = True;
1214 nbio_shmem(nprocs);
1216 nbio_id = -1;
1218 signal(SIGALRM, nb_alarm);
1219 alarm(1);
1220 t = create_procs(run_netbench, &correct);
1221 alarm(0);
1223 printf("\nThroughput %g MB/sec\n",
1224 1.0e-6 * nbio_total() / t);
1225 return correct;
1230 This test checks for two things:
1232 1) correct support for retaining locks over a close (ie. the server
1233 must not use posix semantics)
1234 2) support for lock timeouts
1236 static bool run_locktest1(int dummy)
1238 struct cli_state *cli1, *cli2;
1239 const char *fname = "\\lockt1.lck";
1240 uint16_t fnum1, fnum2, fnum3;
1241 time_t t1, t2;
1242 unsigned lock_timeout;
1243 NTSTATUS status;
1245 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1246 return False;
1248 cli_sockopt(cli1, sockops);
1249 cli_sockopt(cli2, sockops);
1251 printf("starting locktest1\n");
1253 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1255 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1256 &fnum1);
1257 if (!NT_STATUS_IS_OK(status)) {
1258 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1259 return False;
1262 status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1263 if (!NT_STATUS_IS_OK(status)) {
1264 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1265 return False;
1268 status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1269 if (!NT_STATUS_IS_OK(status)) {
1270 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1271 return False;
1274 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1275 if (!NT_STATUS_IS_OK(status)) {
1276 printf("lock1 failed (%s)\n", nt_errstr(status));
1277 return false;
1280 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1281 if (NT_STATUS_IS_OK(status)) {
1282 printf("lock2 succeeded! This is a locking bug\n");
1283 return false;
1284 } else {
1285 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1286 NT_STATUS_LOCK_NOT_GRANTED)) {
1287 return false;
1291 lock_timeout = (1 + (random() % 20));
1292 printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1293 t1 = time(NULL);
1294 status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1295 if (NT_STATUS_IS_OK(status)) {
1296 printf("lock3 succeeded! This is a locking bug\n");
1297 return false;
1298 } else {
1299 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1300 NT_STATUS_FILE_LOCK_CONFLICT)) {
1301 return false;
1304 t2 = time(NULL);
1306 if (ABS(t2 - t1) < lock_timeout-1) {
1307 printf("error: This server appears not to support timed lock requests\n");
1310 printf("server slept for %u seconds for a %u second timeout\n",
1311 (unsigned int)(t2-t1), lock_timeout);
1313 status = cli_close(cli1, fnum2);
1314 if (!NT_STATUS_IS_OK(status)) {
1315 printf("close1 failed (%s)\n", nt_errstr(status));
1316 return False;
1319 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1320 if (NT_STATUS_IS_OK(status)) {
1321 printf("lock4 succeeded! This is a locking bug\n");
1322 return false;
1323 } else {
1324 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1325 NT_STATUS_FILE_LOCK_CONFLICT)) {
1326 return false;
1330 status = cli_close(cli1, fnum1);
1331 if (!NT_STATUS_IS_OK(status)) {
1332 printf("close2 failed (%s)\n", nt_errstr(status));
1333 return False;
1336 status = cli_close(cli2, fnum3);
1337 if (!NT_STATUS_IS_OK(status)) {
1338 printf("close3 failed (%s)\n", nt_errstr(status));
1339 return False;
1342 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1343 if (!NT_STATUS_IS_OK(status)) {
1344 printf("unlink failed (%s)\n", nt_errstr(status));
1345 return False;
1349 if (!torture_close_connection(cli1)) {
1350 return False;
1353 if (!torture_close_connection(cli2)) {
1354 return False;
1357 printf("Passed locktest1\n");
1358 return True;
1362 this checks to see if a secondary tconx can use open files from an
1363 earlier tconx
1365 static bool run_tcon_test(int dummy)
1367 static struct cli_state *cli;
1368 const char *fname = "\\tcontest.tmp";
1369 uint16 fnum1;
1370 uint16 cnum1, cnum2, cnum3;
1371 uint16 vuid1, vuid2;
1372 char buf[4];
1373 bool ret = True;
1374 NTSTATUS status;
1376 memset(buf, '\0', sizeof(buf));
1378 if (!torture_open_connection(&cli, 0)) {
1379 return False;
1381 cli_sockopt(cli, sockops);
1383 printf("starting tcontest\n");
1385 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1387 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1388 if (!NT_STATUS_IS_OK(status)) {
1389 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1390 return False;
1393 cnum1 = cli_state_get_tid(cli);
1394 vuid1 = cli_state_get_uid(cli);
1396 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1397 if (!NT_STATUS_IS_OK(status)) {
1398 printf("initial write failed (%s)", nt_errstr(status));
1399 return False;
1402 status = cli_tcon_andx(cli, share, "?????",
1403 password, strlen(password)+1);
1404 if (!NT_STATUS_IS_OK(status)) {
1405 printf("%s refused 2nd tree connect (%s)\n", host,
1406 nt_errstr(status));
1407 cli_shutdown(cli);
1408 return False;
1411 cnum2 = cli_state_get_tid(cli);
1412 cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1413 vuid2 = cli_state_get_uid(cli) + 1;
1415 /* try a write with the wrong tid */
1416 cli_state_set_tid(cli, cnum2);
1418 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1419 if (NT_STATUS_IS_OK(status)) {
1420 printf("* server allows write with wrong TID\n");
1421 ret = False;
1422 } else {
1423 printf("server fails write with wrong TID : %s\n",
1424 nt_errstr(status));
1428 /* try a write with an invalid tid */
1429 cli_state_set_tid(cli, cnum3);
1431 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1432 if (NT_STATUS_IS_OK(status)) {
1433 printf("* server allows write with invalid TID\n");
1434 ret = False;
1435 } else {
1436 printf("server fails write with invalid TID : %s\n",
1437 nt_errstr(status));
1440 /* try a write with an invalid vuid */
1441 cli_state_set_uid(cli, vuid2);
1442 cli_state_set_tid(cli, cnum1);
1444 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1445 if (NT_STATUS_IS_OK(status)) {
1446 printf("* server allows write with invalid VUID\n");
1447 ret = False;
1448 } else {
1449 printf("server fails write with invalid VUID : %s\n",
1450 nt_errstr(status));
1453 cli_state_set_tid(cli, cnum1);
1454 cli_state_set_uid(cli, vuid1);
1456 status = cli_close(cli, fnum1);
1457 if (!NT_STATUS_IS_OK(status)) {
1458 printf("close failed (%s)\n", nt_errstr(status));
1459 return False;
1462 cli_state_set_tid(cli, cnum2);
1464 status = cli_tdis(cli);
1465 if (!NT_STATUS_IS_OK(status)) {
1466 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1467 return False;
1470 cli_state_set_tid(cli, cnum1);
1472 if (!torture_close_connection(cli)) {
1473 return False;
1476 return ret;
1481 checks for old style tcon support
1483 static bool run_tcon2_test(int dummy)
1485 static struct cli_state *cli;
1486 uint16 cnum, max_xmit;
1487 char *service;
1488 NTSTATUS status;
1490 if (!torture_open_connection(&cli, 0)) {
1491 return False;
1493 cli_sockopt(cli, sockops);
1495 printf("starting tcon2 test\n");
1497 if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1498 return false;
1501 status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1503 SAFE_FREE(service);
1505 if (!NT_STATUS_IS_OK(status)) {
1506 printf("tcon2 failed : %s\n", nt_errstr(status));
1507 } else {
1508 printf("tcon OK : max_xmit=%d cnum=%d\n",
1509 (int)max_xmit, (int)cnum);
1512 if (!torture_close_connection(cli)) {
1513 return False;
1516 printf("Passed tcon2 test\n");
1517 return True;
1520 static bool tcon_devtest(struct cli_state *cli,
1521 const char *myshare, const char *devtype,
1522 const char *return_devtype,
1523 NTSTATUS expected_error)
1525 NTSTATUS status;
1526 bool ret;
1528 status = cli_tcon_andx(cli, myshare, devtype,
1529 password, strlen(password)+1);
1531 if (NT_STATUS_IS_OK(expected_error)) {
1532 if (NT_STATUS_IS_OK(status)) {
1533 if (strcmp(cli->dev, return_devtype) == 0) {
1534 ret = True;
1535 } else {
1536 printf("tconX to share %s with type %s "
1537 "succeeded but returned the wrong "
1538 "device type (got [%s] but should have got [%s])\n",
1539 myshare, devtype, cli->dev, return_devtype);
1540 ret = False;
1542 } else {
1543 printf("tconX to share %s with type %s "
1544 "should have succeeded but failed\n",
1545 myshare, devtype);
1546 ret = False;
1548 cli_tdis(cli);
1549 } else {
1550 if (NT_STATUS_IS_OK(status)) {
1551 printf("tconx to share %s with type %s "
1552 "should have failed but succeeded\n",
1553 myshare, devtype);
1554 ret = False;
1555 } else {
1556 if (NT_STATUS_EQUAL(cli_nt_error(cli),
1557 expected_error)) {
1558 ret = True;
1559 } else {
1560 printf("Returned unexpected error\n");
1561 ret = False;
1565 return ret;
1569 checks for correct tconX support
1571 static bool run_tcon_devtype_test(int dummy)
1573 static struct cli_state *cli1 = NULL;
1574 int flags = 0;
1575 NTSTATUS status;
1576 bool ret = True;
1578 status = cli_full_connection(&cli1, myname,
1579 host, NULL, port_to_use,
1580 NULL, NULL,
1581 username, workgroup,
1582 password, flags, signing_state);
1584 if (!NT_STATUS_IS_OK(status)) {
1585 printf("could not open connection\n");
1586 return False;
1589 if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1590 ret = False;
1592 if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1593 ret = False;
1595 if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1596 ret = False;
1598 if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1599 ret = False;
1601 if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1602 ret = False;
1604 if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1605 ret = False;
1607 if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1608 ret = False;
1610 if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1611 ret = False;
1613 if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1614 ret = False;
1616 if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1617 ret = False;
1619 cli_shutdown(cli1);
1621 if (ret)
1622 printf("Passed tcondevtest\n");
1624 return ret;
1629 This test checks that
1631 1) the server supports multiple locking contexts on the one SMB
1632 connection, distinguished by PID.
1634 2) the server correctly fails overlapping locks made by the same PID (this
1635 goes against POSIX behaviour, which is why it is tricky to implement)
1637 3) the server denies unlock requests by an incorrect client PID
1639 static bool run_locktest2(int dummy)
1641 static struct cli_state *cli;
1642 const char *fname = "\\lockt2.lck";
1643 uint16_t fnum1, fnum2, fnum3;
1644 bool correct = True;
1645 NTSTATUS status;
1647 if (!torture_open_connection(&cli, 0)) {
1648 return False;
1651 cli_sockopt(cli, sockops);
1653 printf("starting locktest2\n");
1655 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1657 cli_setpid(cli, 1);
1659 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1660 if (!NT_STATUS_IS_OK(status)) {
1661 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1662 return False;
1665 status = cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1666 if (!NT_STATUS_IS_OK(status)) {
1667 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1668 return False;
1671 cli_setpid(cli, 2);
1673 status = cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1674 if (!NT_STATUS_IS_OK(status)) {
1675 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1676 return False;
1679 cli_setpid(cli, 1);
1681 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1682 if (!NT_STATUS_IS_OK(status)) {
1683 printf("lock1 failed (%s)\n", nt_errstr(status));
1684 return false;
1687 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1688 if (NT_STATUS_IS_OK(status)) {
1689 printf("WRITE lock1 succeeded! This is a locking bug\n");
1690 correct = false;
1691 } else {
1692 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1693 NT_STATUS_LOCK_NOT_GRANTED)) {
1694 return false;
1698 status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1699 if (NT_STATUS_IS_OK(status)) {
1700 printf("WRITE lock2 succeeded! This is a locking bug\n");
1701 correct = false;
1702 } else {
1703 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1704 NT_STATUS_LOCK_NOT_GRANTED)) {
1705 return false;
1709 status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1710 if (NT_STATUS_IS_OK(status)) {
1711 printf("READ lock2 succeeded! This is a locking bug\n");
1712 correct = false;
1713 } else {
1714 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1715 NT_STATUS_FILE_LOCK_CONFLICT)) {
1716 return false;
1720 status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1721 if (!NT_STATUS_IS_OK(status)) {
1722 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1724 cli_setpid(cli, 2);
1725 if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1726 printf("unlock at 100 succeeded! This is a locking bug\n");
1727 correct = False;
1730 status = cli_unlock(cli, fnum1, 0, 4);
1731 if (NT_STATUS_IS_OK(status)) {
1732 printf("unlock1 succeeded! This is a locking bug\n");
1733 correct = false;
1734 } else {
1735 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1736 NT_STATUS_RANGE_NOT_LOCKED)) {
1737 return false;
1741 status = cli_unlock(cli, fnum1, 0, 8);
1742 if (NT_STATUS_IS_OK(status)) {
1743 printf("unlock2 succeeded! This is a locking bug\n");
1744 correct = false;
1745 } else {
1746 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1747 NT_STATUS_RANGE_NOT_LOCKED)) {
1748 return false;
1752 status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1753 if (NT_STATUS_IS_OK(status)) {
1754 printf("lock3 succeeded! This is a locking bug\n");
1755 correct = false;
1756 } else {
1757 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1758 NT_STATUS_LOCK_NOT_GRANTED)) {
1759 return false;
1763 cli_setpid(cli, 1);
1765 status = cli_close(cli, fnum1);
1766 if (!NT_STATUS_IS_OK(status)) {
1767 printf("close1 failed (%s)\n", nt_errstr(status));
1768 return False;
1771 status = cli_close(cli, fnum2);
1772 if (!NT_STATUS_IS_OK(status)) {
1773 printf("close2 failed (%s)\n", nt_errstr(status));
1774 return False;
1777 status = cli_close(cli, fnum3);
1778 if (!NT_STATUS_IS_OK(status)) {
1779 printf("close3 failed (%s)\n", nt_errstr(status));
1780 return False;
1783 if (!torture_close_connection(cli)) {
1784 correct = False;
1787 printf("locktest2 finished\n");
1789 return correct;
1794 This test checks that
1796 1) the server supports the full offset range in lock requests
1798 static bool run_locktest3(int dummy)
1800 static struct cli_state *cli1, *cli2;
1801 const char *fname = "\\lockt3.lck";
1802 uint16_t fnum1, fnum2;
1803 int i;
1804 uint32 offset;
1805 bool correct = True;
1806 NTSTATUS status;
1808 #define NEXT_OFFSET offset += (~(uint32)0) / torture_numops
1810 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1811 return False;
1813 cli_sockopt(cli1, sockops);
1814 cli_sockopt(cli2, sockops);
1816 printf("starting locktest3\n");
1818 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1820 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1821 &fnum1);
1822 if (!NT_STATUS_IS_OK(status)) {
1823 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1824 return False;
1827 status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1828 if (!NT_STATUS_IS_OK(status)) {
1829 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1830 return False;
1833 for (offset=i=0;i<torture_numops;i++) {
1834 NEXT_OFFSET;
1836 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1837 if (!NT_STATUS_IS_OK(status)) {
1838 printf("lock1 %d failed (%s)\n",
1840 nt_errstr(status));
1841 return False;
1844 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1845 if (!NT_STATUS_IS_OK(status)) {
1846 printf("lock2 %d failed (%s)\n",
1848 nt_errstr(status));
1849 return False;
1853 for (offset=i=0;i<torture_numops;i++) {
1854 NEXT_OFFSET;
1856 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1857 if (NT_STATUS_IS_OK(status)) {
1858 printf("error: lock1 %d succeeded!\n", i);
1859 return False;
1862 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1863 if (NT_STATUS_IS_OK(status)) {
1864 printf("error: lock2 %d succeeded!\n", i);
1865 return False;
1868 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1869 if (NT_STATUS_IS_OK(status)) {
1870 printf("error: lock3 %d succeeded!\n", i);
1871 return False;
1874 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1875 if (NT_STATUS_IS_OK(status)) {
1876 printf("error: lock4 %d succeeded!\n", i);
1877 return False;
1881 for (offset=i=0;i<torture_numops;i++) {
1882 NEXT_OFFSET;
1884 status = cli_unlock(cli1, fnum1, offset-1, 1);
1885 if (!NT_STATUS_IS_OK(status)) {
1886 printf("unlock1 %d failed (%s)\n",
1888 nt_errstr(status));
1889 return False;
1892 status = cli_unlock(cli2, fnum2, offset-2, 1);
1893 if (!NT_STATUS_IS_OK(status)) {
1894 printf("unlock2 %d failed (%s)\n",
1896 nt_errstr(status));
1897 return False;
1901 status = cli_close(cli1, fnum1);
1902 if (!NT_STATUS_IS_OK(status)) {
1903 printf("close1 failed (%s)\n", nt_errstr(status));
1904 return False;
1907 status = cli_close(cli2, fnum2);
1908 if (!NT_STATUS_IS_OK(status)) {
1909 printf("close2 failed (%s)\n", nt_errstr(status));
1910 return False;
1913 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1914 if (!NT_STATUS_IS_OK(status)) {
1915 printf("unlink failed (%s)\n", nt_errstr(status));
1916 return False;
1919 if (!torture_close_connection(cli1)) {
1920 correct = False;
1923 if (!torture_close_connection(cli2)) {
1924 correct = False;
1927 printf("finished locktest3\n");
1929 return correct;
1932 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
1933 char *buf, off_t offset, size_t size,
1934 size_t *nread, size_t expect)
1936 NTSTATUS status;
1937 size_t l_nread;
1939 status = cli_read(cli, fnum, buf, offset, size, &l_nread);
1941 if(!NT_STATUS_IS_OK(status)) {
1942 return false;
1943 } else if (l_nread != expect) {
1944 return false;
1947 if (nread) {
1948 *nread = l_nread;
1951 return true;
1954 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1955 printf("** "); correct = False; \
1959 looks at overlapping locks
1961 static bool run_locktest4(int dummy)
1963 static struct cli_state *cli1, *cli2;
1964 const char *fname = "\\lockt4.lck";
1965 uint16_t fnum1, fnum2, f;
1966 bool ret;
1967 char buf[1000];
1968 bool correct = True;
1969 NTSTATUS status;
1971 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1972 return False;
1975 cli_sockopt(cli1, sockops);
1976 cli_sockopt(cli2, sockops);
1978 printf("starting locktest4\n");
1980 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1982 cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1983 cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1985 memset(buf, 0, sizeof(buf));
1987 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
1988 NULL);
1989 if (!NT_STATUS_IS_OK(status)) {
1990 printf("Failed to create file: %s\n", nt_errstr(status));
1991 correct = False;
1992 goto fail;
1995 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1996 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
1997 EXPECTED(ret, False);
1998 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
2000 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
2001 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
2002 EXPECTED(ret, True);
2003 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
2005 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
2006 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
2007 EXPECTED(ret, False);
2008 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
2010 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
2011 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
2012 EXPECTED(ret, True);
2013 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
2015 ret = (cli_setpid(cli1, 1),
2016 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
2017 (cli_setpid(cli1, 2),
2018 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
2019 EXPECTED(ret, False);
2020 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
2022 ret = (cli_setpid(cli1, 1),
2023 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
2024 (cli_setpid(cli1, 2),
2025 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
2026 EXPECTED(ret, True);
2027 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
2029 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
2030 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
2031 EXPECTED(ret, True);
2032 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
2034 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
2035 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
2036 EXPECTED(ret, False);
2037 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
2039 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
2040 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
2041 EXPECTED(ret, False);
2042 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
2044 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
2045 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2046 EXPECTED(ret, True);
2047 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2049 ret = (cli_setpid(cli1, 1),
2050 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2051 (cli_setpid(cli1, 2),
2052 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2053 EXPECTED(ret, False);
2054 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2056 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2057 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2058 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2059 EXPECTED(ret, False);
2060 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2063 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2064 test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2065 EXPECTED(ret, False);
2066 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2068 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2069 ret = NT_STATUS_IS_OK(status);
2070 if (ret) {
2071 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2072 NULL);
2073 ret = NT_STATUS_IS_OK(status);
2075 EXPECTED(ret, False);
2076 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2079 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2080 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2081 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2082 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2083 EXPECTED(ret, True);
2084 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2087 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2088 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2089 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2090 test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2091 !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2092 150, 4, NULL))) &&
2093 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2094 EXPECTED(ret, True);
2095 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2097 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2098 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2099 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2100 160, 4, NULL)) &&
2101 test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2102 EXPECTED(ret, True);
2103 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2105 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2106 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2107 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2108 170, 4, NULL)) &&
2109 test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2110 EXPECTED(ret, True);
2111 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2113 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2114 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2115 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2116 !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2117 190, 4, NULL)) &&
2118 test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2119 EXPECTED(ret, True);
2120 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2122 cli_close(cli1, fnum1);
2123 cli_close(cli2, fnum2);
2124 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2125 cli_open(cli1, fname, O_RDWR, DENY_NONE, &f);
2126 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2127 NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2128 NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2129 NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2130 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2131 cli_close(cli1, f);
2132 cli_close(cli1, fnum1);
2133 EXPECTED(ret, True);
2134 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2136 fail:
2137 cli_close(cli1, fnum1);
2138 cli_close(cli2, fnum2);
2139 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2140 torture_close_connection(cli1);
2141 torture_close_connection(cli2);
2143 printf("finished locktest4\n");
2144 return correct;
2148 looks at lock upgrade/downgrade.
2150 static bool run_locktest5(int dummy)
2152 static struct cli_state *cli1, *cli2;
2153 const char *fname = "\\lockt5.lck";
2154 uint16_t fnum1, fnum2, fnum3;
2155 bool ret;
2156 char buf[1000];
2157 bool correct = True;
2158 NTSTATUS status;
2160 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2161 return False;
2164 cli_sockopt(cli1, sockops);
2165 cli_sockopt(cli2, sockops);
2167 printf("starting locktest5\n");
2169 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2171 cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2172 cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2173 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2175 memset(buf, 0, sizeof(buf));
2177 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2178 NULL);
2179 if (!NT_STATUS_IS_OK(status)) {
2180 printf("Failed to create file: %s\n", nt_errstr(status));
2181 correct = False;
2182 goto fail;
2185 /* Check for NT bug... */
2186 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2187 NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2188 cli_close(cli1, fnum1);
2189 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2190 status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2191 ret = NT_STATUS_IS_OK(status);
2192 EXPECTED(ret, True);
2193 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2194 cli_close(cli1, fnum1);
2195 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2196 cli_unlock(cli1, fnum3, 0, 1);
2198 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2199 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2200 EXPECTED(ret, True);
2201 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2203 status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2204 ret = NT_STATUS_IS_OK(status);
2205 EXPECTED(ret, False);
2207 printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2209 /* Unlock the process 2 lock. */
2210 cli_unlock(cli2, fnum2, 0, 4);
2212 status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2213 ret = NT_STATUS_IS_OK(status);
2214 EXPECTED(ret, False);
2216 printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
2218 /* Unlock the process 1 fnum3 lock. */
2219 cli_unlock(cli1, fnum3, 0, 4);
2221 /* Stack 2 more locks here. */
2222 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2223 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2225 EXPECTED(ret, True);
2226 printf("the same process %s stack read locks\n", ret?"can":"cannot");
2228 /* Unlock the first process lock, then check this was the WRITE lock that was
2229 removed. */
2231 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2232 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2234 EXPECTED(ret, True);
2235 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2237 /* Unlock the process 2 lock. */
2238 cli_unlock(cli2, fnum2, 0, 4);
2240 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2242 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2243 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2244 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2246 EXPECTED(ret, True);
2247 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2249 /* Ensure the next unlock fails. */
2250 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2251 EXPECTED(ret, False);
2252 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2254 /* Ensure connection 2 can get a write lock. */
2255 status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2256 ret = NT_STATUS_IS_OK(status);
2257 EXPECTED(ret, True);
2259 printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2262 fail:
2263 cli_close(cli1, fnum1);
2264 cli_close(cli2, fnum2);
2265 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2266 if (!torture_close_connection(cli1)) {
2267 correct = False;
2269 if (!torture_close_connection(cli2)) {
2270 correct = False;
2273 printf("finished locktest5\n");
2275 return correct;
2279 tries the unusual lockingX locktype bits
2281 static bool run_locktest6(int dummy)
2283 static struct cli_state *cli;
2284 const char *fname[1] = { "\\lock6.txt" };
2285 int i;
2286 uint16_t fnum;
2287 NTSTATUS status;
2289 if (!torture_open_connection(&cli, 0)) {
2290 return False;
2293 cli_sockopt(cli, sockops);
2295 printf("starting locktest6\n");
2297 for (i=0;i<1;i++) {
2298 printf("Testing %s\n", fname[i]);
2300 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2302 cli_open(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2303 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2304 cli_close(cli, fnum);
2305 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2307 cli_open(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2308 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2309 cli_close(cli, fnum);
2310 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2312 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2315 torture_close_connection(cli);
2317 printf("finished locktest6\n");
2318 return True;
2321 static bool run_locktest7(int dummy)
2323 struct cli_state *cli1;
2324 const char *fname = "\\lockt7.lck";
2325 uint16_t fnum1;
2326 char buf[200];
2327 bool correct = False;
2328 size_t nread;
2329 NTSTATUS status;
2331 if (!torture_open_connection(&cli1, 0)) {
2332 return False;
2335 cli_sockopt(cli1, sockops);
2337 printf("starting locktest7\n");
2339 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2341 cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2343 memset(buf, 0, sizeof(buf));
2345 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2346 NULL);
2347 if (!NT_STATUS_IS_OK(status)) {
2348 printf("Failed to create file: %s\n", nt_errstr(status));
2349 goto fail;
2352 cli_setpid(cli1, 1);
2354 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2355 if (!NT_STATUS_IS_OK(status)) {
2356 printf("Unable to apply read lock on range 130:4, "
2357 "error was %s\n", nt_errstr(status));
2358 goto fail;
2359 } else {
2360 printf("pid1 successfully locked range 130:4 for READ\n");
2363 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2364 if (!NT_STATUS_IS_OK(status)) {
2365 printf("pid1 unable to read the range 130:4, error was %s\n",
2366 nt_errstr(status));
2367 goto fail;
2368 } else if (nread != 4) {
2369 printf("pid1 unable to read the range 130:4, "
2370 "recv %ld req %d\n", (unsigned long)nread, 4);
2371 goto fail;
2372 } else {
2373 printf("pid1 successfully read the range 130:4\n");
2376 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2377 if (!NT_STATUS_IS_OK(status)) {
2378 printf("pid1 unable to write to the range 130:4, error was "
2379 "%s\n", nt_errstr(status));
2380 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2381 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2382 goto fail;
2384 } else {
2385 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2386 goto fail;
2389 cli_setpid(cli1, 2);
2391 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2392 if (!NT_STATUS_IS_OK(status)) {
2393 printf("pid2 unable to read the range 130:4, error was %s\n",
2394 nt_errstr(status));
2395 goto fail;
2396 } else if (nread != 4) {
2397 printf("pid2 unable to read the range 130:4, "
2398 "recv %ld req %d\n", (unsigned long)nread, 4);
2399 goto fail;
2400 } else {
2401 printf("pid2 successfully read the range 130:4\n");
2404 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2405 if (!NT_STATUS_IS_OK(status)) {
2406 printf("pid2 unable to write to the range 130:4, error was "
2407 "%s\n", nt_errstr(status));
2408 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2409 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2410 goto fail;
2412 } else {
2413 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2414 goto fail;
2417 cli_setpid(cli1, 1);
2418 cli_unlock(cli1, fnum1, 130, 4);
2420 status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2421 if (!NT_STATUS_IS_OK(status)) {
2422 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2423 goto fail;
2424 } else {
2425 printf("pid1 successfully locked range 130:4 for WRITE\n");
2428 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2429 if (!NT_STATUS_IS_OK(status)) {
2430 printf("pid1 unable to read the range 130:4, error was %s\n",
2431 nt_errstr(status));
2432 goto fail;
2433 } else if (nread != 4) {
2434 printf("pid1 unable to read the range 130:4, "
2435 "recv %ld req %d\n", (unsigned long)nread, 4);
2436 goto fail;
2437 } else {
2438 printf("pid1 successfully read the range 130:4\n");
2441 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2442 if (!NT_STATUS_IS_OK(status)) {
2443 printf("pid1 unable to write to the range 130:4, error was "
2444 "%s\n", nt_errstr(status));
2445 goto fail;
2446 } else {
2447 printf("pid1 successfully wrote to the range 130:4\n");
2450 cli_setpid(cli1, 2);
2452 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2453 if (!NT_STATUS_IS_OK(status)) {
2454 printf("pid2 unable to read the range 130:4, error was "
2455 "%s\n", nt_errstr(status));
2456 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2457 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2458 goto fail;
2460 } else {
2461 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2462 (unsigned long)nread);
2463 goto fail;
2466 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2467 if (!NT_STATUS_IS_OK(status)) {
2468 printf("pid2 unable to write to the range 130:4, error was "
2469 "%s\n", nt_errstr(status));
2470 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2471 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2472 goto fail;
2474 } else {
2475 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2476 goto fail;
2479 cli_unlock(cli1, fnum1, 130, 0);
2480 correct = True;
2482 fail:
2483 cli_close(cli1, fnum1);
2484 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2485 torture_close_connection(cli1);
2487 printf("finished locktest7\n");
2488 return correct;
2492 * This demonstrates a problem with our use of GPFS share modes: A file
2493 * descriptor sitting in the pending close queue holding a GPFS share mode
2494 * blocks opening a file another time. Happens with Word 2007 temp files.
2495 * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2496 * open is denied with NT_STATUS_SHARING_VIOLATION.
2499 static bool run_locktest8(int dummy)
2501 struct cli_state *cli1;
2502 const char *fname = "\\lockt8.lck";
2503 uint16_t fnum1, fnum2;
2504 char buf[200];
2505 bool correct = False;
2506 NTSTATUS status;
2508 if (!torture_open_connection(&cli1, 0)) {
2509 return False;
2512 cli_sockopt(cli1, sockops);
2514 printf("starting locktest8\n");
2516 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2518 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2519 &fnum1);
2520 if (!NT_STATUS_IS_OK(status)) {
2521 d_fprintf(stderr, "cli_open returned %s\n", nt_errstr(status));
2522 return false;
2525 memset(buf, 0, sizeof(buf));
2527 status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2528 if (!NT_STATUS_IS_OK(status)) {
2529 d_fprintf(stderr, "cli_open second time returned %s\n",
2530 nt_errstr(status));
2531 goto fail;
2534 status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2535 if (!NT_STATUS_IS_OK(status)) {
2536 printf("Unable to apply read lock on range 1:1, error was "
2537 "%s\n", nt_errstr(status));
2538 goto fail;
2541 status = cli_close(cli1, fnum1);
2542 if (!NT_STATUS_IS_OK(status)) {
2543 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2544 goto fail;
2547 status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2548 if (!NT_STATUS_IS_OK(status)) {
2549 d_fprintf(stderr, "cli_open third time returned %s\n",
2550 nt_errstr(status));
2551 goto fail;
2554 correct = true;
2556 fail:
2557 cli_close(cli1, fnum1);
2558 cli_close(cli1, fnum2);
2559 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2560 torture_close_connection(cli1);
2562 printf("finished locktest8\n");
2563 return correct;
2567 * This test is designed to be run in conjunction with
2568 * external NFS or POSIX locks taken in the filesystem.
2569 * It checks that the smbd server will block until the
2570 * lock is released and then acquire it. JRA.
2573 static bool got_alarm;
2574 static struct cli_state *alarm_cli;
2576 static void alarm_handler(int dummy)
2578 got_alarm = True;
2581 static void alarm_handler_parent(int dummy)
2583 cli_state_disconnect(alarm_cli);
2586 static void do_local_lock(int read_fd, int write_fd)
2588 int fd;
2589 char c = '\0';
2590 struct flock lock;
2591 const char *local_pathname = NULL;
2592 int ret;
2594 local_pathname = talloc_asprintf(talloc_tos(),
2595 "%s/lockt9.lck", local_path);
2596 if (!local_pathname) {
2597 printf("child: alloc fail\n");
2598 exit(1);
2601 unlink(local_pathname);
2602 fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2603 if (fd == -1) {
2604 printf("child: open of %s failed %s.\n",
2605 local_pathname, strerror(errno));
2606 exit(1);
2609 /* Now take a fcntl lock. */
2610 lock.l_type = F_WRLCK;
2611 lock.l_whence = SEEK_SET;
2612 lock.l_start = 0;
2613 lock.l_len = 4;
2614 lock.l_pid = getpid();
2616 ret = fcntl(fd,F_SETLK,&lock);
2617 if (ret == -1) {
2618 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2619 local_pathname, strerror(errno));
2620 exit(1);
2621 } else {
2622 printf("child: got lock 0:4 on file %s.\n",
2623 local_pathname );
2624 fflush(stdout);
2627 CatchSignal(SIGALRM, alarm_handler);
2628 alarm(5);
2629 /* Signal the parent. */
2630 if (write(write_fd, &c, 1) != 1) {
2631 printf("child: start signal fail %s.\n",
2632 strerror(errno));
2633 exit(1);
2635 alarm(0);
2637 alarm(10);
2638 /* Wait for the parent to be ready. */
2639 if (read(read_fd, &c, 1) != 1) {
2640 printf("child: reply signal fail %s.\n",
2641 strerror(errno));
2642 exit(1);
2644 alarm(0);
2646 sleep(5);
2647 close(fd);
2648 printf("child: released lock 0:4 on file %s.\n",
2649 local_pathname );
2650 fflush(stdout);
2651 exit(0);
2654 static bool run_locktest9(int dummy)
2656 struct cli_state *cli1;
2657 const char *fname = "\\lockt9.lck";
2658 uint16_t fnum;
2659 bool correct = False;
2660 int pipe_in[2], pipe_out[2];
2661 pid_t child_pid;
2662 char c = '\0';
2663 int ret;
2664 struct timeval start;
2665 double seconds;
2666 NTSTATUS status;
2668 printf("starting locktest9\n");
2670 if (local_path == NULL) {
2671 d_fprintf(stderr, "locktest9 must be given a local path via -l <localpath>\n");
2672 return false;
2675 if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2676 return false;
2679 child_pid = fork();
2680 if (child_pid == -1) {
2681 return false;
2684 if (child_pid == 0) {
2685 /* Child. */
2686 do_local_lock(pipe_out[0], pipe_in[1]);
2687 exit(0);
2690 close(pipe_out[0]);
2691 close(pipe_in[1]);
2692 pipe_out[0] = -1;
2693 pipe_in[1] = -1;
2695 /* Parent. */
2696 ret = read(pipe_in[0], &c, 1);
2697 if (ret != 1) {
2698 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2699 strerror(errno));
2700 return false;
2703 if (!torture_open_connection(&cli1, 0)) {
2704 return false;
2707 cli_sockopt(cli1, sockops);
2709 status = cli_open(cli1, fname, O_RDWR, DENY_NONE,
2710 &fnum);
2711 if (!NT_STATUS_IS_OK(status)) {
2712 d_fprintf(stderr, "cli_open returned %s\n", nt_errstr(status));
2713 return false;
2716 /* Ensure the child has the lock. */
2717 status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2718 if (NT_STATUS_IS_OK(status)) {
2719 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2720 goto fail;
2721 } else {
2722 d_printf("Child has the lock.\n");
2725 /* Tell the child to wait 5 seconds then exit. */
2726 ret = write(pipe_out[1], &c, 1);
2727 if (ret != 1) {
2728 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2729 strerror(errno));
2730 goto fail;
2733 /* Wait 20 seconds for the lock. */
2734 alarm_cli = cli1;
2735 CatchSignal(SIGALRM, alarm_handler_parent);
2736 alarm(20);
2738 start = timeval_current();
2740 status = cli_lock32(cli1, fnum, 0, 4, -1, WRITE_LOCK);
2741 if (!NT_STATUS_IS_OK(status)) {
2742 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2743 "%s\n", nt_errstr(status));
2744 goto fail_nofd;
2746 alarm(0);
2748 seconds = timeval_elapsed(&start);
2750 printf("Parent got the lock after %.2f seconds.\n",
2751 seconds);
2753 status = cli_close(cli1, fnum);
2754 if (!NT_STATUS_IS_OK(status)) {
2755 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2756 goto fail;
2759 correct = true;
2761 fail:
2762 cli_close(cli1, fnum);
2763 torture_close_connection(cli1);
2765 fail_nofd:
2767 printf("finished locktest9\n");
2768 return correct;
2772 test whether fnums and tids open on one VC are available on another (a major
2773 security hole)
2775 static bool run_fdpasstest(int dummy)
2777 struct cli_state *cli1, *cli2;
2778 const char *fname = "\\fdpass.tst";
2779 uint16_t fnum1;
2780 char buf[1024];
2781 NTSTATUS status;
2783 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2784 return False;
2786 cli_sockopt(cli1, sockops);
2787 cli_sockopt(cli2, sockops);
2789 printf("starting fdpasstest\n");
2791 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2793 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
2794 &fnum1);
2795 if (!NT_STATUS_IS_OK(status)) {
2796 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2797 return False;
2800 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
2801 13, NULL);
2802 if (!NT_STATUS_IS_OK(status)) {
2803 printf("write failed (%s)\n", nt_errstr(status));
2804 return False;
2807 cli_state_set_uid(cli2, cli_state_get_uid(cli1));
2808 cli_state_set_tid(cli2, cli_state_get_tid(cli1));
2809 cli_setpid(cli2, cli_getpid(cli1));
2811 if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
2812 printf("read succeeded! nasty security hole [%s]\n", buf);
2813 return false;
2816 cli_close(cli1, fnum1);
2817 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2819 torture_close_connection(cli1);
2820 torture_close_connection(cli2);
2822 printf("finished fdpasstest\n");
2823 return True;
2826 static bool run_fdsesstest(int dummy)
2828 struct cli_state *cli;
2829 uint16 new_vuid;
2830 uint16 saved_vuid;
2831 uint16 new_cnum;
2832 uint16 saved_cnum;
2833 const char *fname = "\\fdsess.tst";
2834 const char *fname1 = "\\fdsess1.tst";
2835 uint16_t fnum1;
2836 uint16_t fnum2;
2837 char buf[1024];
2838 bool ret = True;
2839 NTSTATUS status;
2841 if (!torture_open_connection(&cli, 0))
2842 return False;
2843 cli_sockopt(cli, sockops);
2845 if (!torture_cli_session_setup2(cli, &new_vuid))
2846 return False;
2848 saved_cnum = cli_state_get_tid(cli);
2849 if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, share, "?????", "", 1)))
2850 return False;
2851 new_cnum = cli_state_get_tid(cli);
2852 cli_state_set_tid(cli, saved_cnum);
2854 printf("starting fdsesstest\n");
2856 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2857 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2859 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2860 if (!NT_STATUS_IS_OK(status)) {
2861 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2862 return False;
2865 status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
2866 NULL);
2867 if (!NT_STATUS_IS_OK(status)) {
2868 printf("write failed (%s)\n", nt_errstr(status));
2869 return False;
2872 saved_vuid = cli_state_get_uid(cli);
2873 cli_state_set_uid(cli, new_vuid);
2875 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2876 printf("read succeeded with different vuid! "
2877 "nasty security hole [%s]\n", buf);
2878 ret = false;
2880 /* Try to open a file with different vuid, samba cnum. */
2881 if (NT_STATUS_IS_OK(cli_open(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
2882 printf("create with different vuid, same cnum succeeded.\n");
2883 cli_close(cli, fnum2);
2884 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2885 } else {
2886 printf("create with different vuid, same cnum failed.\n");
2887 printf("This will cause problems with service clients.\n");
2888 ret = False;
2891 cli_state_set_uid(cli, saved_vuid);
2893 /* Try with same vuid, different cnum. */
2894 cli_state_set_tid(cli, new_cnum);
2896 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2897 printf("read succeeded with different cnum![%s]\n", buf);
2898 ret = false;
2901 cli_state_set_tid(cli, saved_cnum);
2902 cli_close(cli, fnum1);
2903 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2905 torture_close_connection(cli);
2907 printf("finished fdsesstest\n");
2908 return ret;
2912 This test checks that
2914 1) the server does not allow an unlink on a file that is open
2916 static bool run_unlinktest(int dummy)
2918 struct cli_state *cli;
2919 const char *fname = "\\unlink.tst";
2920 uint16_t fnum;
2921 bool correct = True;
2922 NTSTATUS status;
2924 if (!torture_open_connection(&cli, 0)) {
2925 return False;
2928 cli_sockopt(cli, sockops);
2930 printf("starting unlink test\n");
2932 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2934 cli_setpid(cli, 1);
2936 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2937 if (!NT_STATUS_IS_OK(status)) {
2938 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2939 return False;
2942 status = cli_unlink(cli, fname,
2943 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2944 if (NT_STATUS_IS_OK(status)) {
2945 printf("error: server allowed unlink on an open file\n");
2946 correct = False;
2947 } else {
2948 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
2949 NT_STATUS_SHARING_VIOLATION);
2952 cli_close(cli, fnum);
2953 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2955 if (!torture_close_connection(cli)) {
2956 correct = False;
2959 printf("unlink test finished\n");
2961 return correct;
2966 test how many open files this server supports on the one socket
2968 static bool run_maxfidtest(int dummy)
2970 struct cli_state *cli;
2971 fstring fname;
2972 uint16_t fnums[0x11000];
2973 int i;
2974 int retries=4;
2975 bool correct = True;
2976 NTSTATUS status;
2978 cli = current_cli;
2980 if (retries <= 0) {
2981 printf("failed to connect\n");
2982 return False;
2985 cli_sockopt(cli, sockops);
2987 for (i=0; i<0x11000; i++) {
2988 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2989 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
2990 &fnums[i]);
2991 if (!NT_STATUS_IS_OK(status)) {
2992 printf("open of %s failed (%s)\n",
2993 fname, nt_errstr(status));
2994 printf("maximum fnum is %d\n", i);
2995 break;
2997 printf("%6d\r", i);
2999 printf("%6d\n", i);
3000 i--;
3002 printf("cleaning up\n");
3003 for (;i>=0;i--) {
3004 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3005 cli_close(cli, fnums[i]);
3007 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3008 if (!NT_STATUS_IS_OK(status)) {
3009 printf("unlink of %s failed (%s)\n",
3010 fname, nt_errstr(status));
3011 correct = False;
3013 printf("%6d\r", i);
3015 printf("%6d\n", 0);
3017 printf("maxfid test finished\n");
3018 if (!torture_close_connection(cli)) {
3019 correct = False;
3021 return correct;
3024 /* generate a random buffer */
3025 static void rand_buf(char *buf, int len)
3027 while (len--) {
3028 *buf = (char)sys_random();
3029 buf++;
3033 /* send smb negprot commands, not reading the response */
3034 static bool run_negprot_nowait(int dummy)
3036 struct tevent_context *ev;
3037 int i;
3038 struct cli_state *cli;
3039 bool correct = True;
3041 printf("starting negprot nowait test\n");
3043 ev = tevent_context_init(talloc_tos());
3044 if (ev == NULL) {
3045 return false;
3048 if (!(cli = open_nbt_connection())) {
3049 TALLOC_FREE(ev);
3050 return False;
3053 for (i=0;i<50000;i++) {
3054 struct tevent_req *req;
3056 req = cli_negprot_send(ev, ev, cli, PROTOCOL_NT1);
3057 if (req == NULL) {
3058 TALLOC_FREE(ev);
3059 return false;
3061 if (!tevent_req_poll(req, ev)) {
3062 d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3063 strerror(errno));
3064 TALLOC_FREE(ev);
3065 return false;
3067 TALLOC_FREE(req);
3070 if (torture_close_connection(cli)) {
3071 correct = False;
3074 printf("finished negprot nowait test\n");
3076 return correct;
3079 /* send smb negprot commands, not reading the response */
3080 static bool run_bad_nbt_session(int dummy)
3082 struct nmb_name called, calling;
3083 struct sockaddr_storage ss;
3084 NTSTATUS status;
3085 int fd;
3086 bool ret;
3088 printf("starting bad nbt session test\n");
3090 make_nmb_name(&calling, myname, 0x0);
3091 make_nmb_name(&called , host, 0x20);
3093 if (!resolve_name(host, &ss, 0x20, true)) {
3094 d_fprintf(stderr, "Could not resolve name %s\n", host);
3095 return false;
3098 status = open_socket_out(&ss, 139, 10000, &fd);
3099 if (!NT_STATUS_IS_OK(status)) {
3100 d_fprintf(stderr, "open_socket_out failed: %s\n",
3101 nt_errstr(status));
3102 return false;
3105 ret = cli_bad_session_request(fd, &calling, &called);
3106 close(fd);
3107 if (!ret) {
3108 d_fprintf(stderr, "open_socket_out failed: %s\n",
3109 nt_errstr(status));
3110 return false;
3113 printf("finished bad nbt session test\n");
3114 return true;
3117 /* send random IPC commands */
3118 static bool run_randomipc(int dummy)
3120 char *rparam = NULL;
3121 char *rdata = NULL;
3122 unsigned int rdrcnt,rprcnt;
3123 char param[1024];
3124 int api, param_len, i;
3125 struct cli_state *cli;
3126 bool correct = True;
3127 int count = 50000;
3129 printf("starting random ipc test\n");
3131 if (!torture_open_connection(&cli, 0)) {
3132 return False;
3135 for (i=0;i<count;i++) {
3136 api = sys_random() % 500;
3137 param_len = (sys_random() % 64);
3139 rand_buf(param, param_len);
3141 SSVAL(param,0,api);
3143 cli_api(cli,
3144 param, param_len, 8,
3145 NULL, 0, BUFFER_SIZE,
3146 &rparam, &rprcnt,
3147 &rdata, &rdrcnt);
3148 if (i % 100 == 0) {
3149 printf("%d/%d\r", i,count);
3152 printf("%d/%d\n", i, count);
3154 if (!torture_close_connection(cli)) {
3155 correct = False;
3158 printf("finished random ipc test\n");
3160 return correct;
3165 static void browse_callback(const char *sname, uint32 stype,
3166 const char *comment, void *state)
3168 printf("\t%20.20s %08x %s\n", sname, stype, comment);
3174 This test checks the browse list code
3177 static bool run_browsetest(int dummy)
3179 static struct cli_state *cli;
3180 bool correct = True;
3182 printf("starting browse test\n");
3184 if (!torture_open_connection(&cli, 0)) {
3185 return False;
3188 printf("domain list:\n");
3189 cli_NetServerEnum(cli, cli->server_domain,
3190 SV_TYPE_DOMAIN_ENUM,
3191 browse_callback, NULL);
3193 printf("machine list:\n");
3194 cli_NetServerEnum(cli, cli->server_domain,
3195 SV_TYPE_ALL,
3196 browse_callback, NULL);
3198 if (!torture_close_connection(cli)) {
3199 correct = False;
3202 printf("browse test finished\n");
3204 return correct;
3210 This checks how the getatr calls works
3212 static bool run_attrtest(int dummy)
3214 struct cli_state *cli;
3215 uint16_t fnum;
3216 time_t t, t2;
3217 const char *fname = "\\attrib123456789.tst";
3218 bool correct = True;
3219 NTSTATUS status;
3221 printf("starting attrib test\n");
3223 if (!torture_open_connection(&cli, 0)) {
3224 return False;
3227 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3228 cli_open(cli, fname,
3229 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3230 cli_close(cli, fnum);
3232 status = cli_getatr(cli, fname, NULL, NULL, &t);
3233 if (!NT_STATUS_IS_OK(status)) {
3234 printf("getatr failed (%s)\n", nt_errstr(status));
3235 correct = False;
3238 if (abs(t - time(NULL)) > 60*60*24*10) {
3239 printf("ERROR: SMBgetatr bug. time is %s",
3240 ctime(&t));
3241 t = time(NULL);
3242 correct = True;
3245 t2 = t-60*60*24; /* 1 day ago */
3247 status = cli_setatr(cli, fname, 0, t2);
3248 if (!NT_STATUS_IS_OK(status)) {
3249 printf("setatr failed (%s)\n", nt_errstr(status));
3250 correct = True;
3253 status = cli_getatr(cli, fname, NULL, NULL, &t);
3254 if (!NT_STATUS_IS_OK(status)) {
3255 printf("getatr failed (%s)\n", nt_errstr(status));
3256 correct = True;
3259 if (t != t2) {
3260 printf("ERROR: getatr/setatr bug. times are\n%s",
3261 ctime(&t));
3262 printf("%s", ctime(&t2));
3263 correct = True;
3266 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3268 if (!torture_close_connection(cli)) {
3269 correct = False;
3272 printf("attrib test finished\n");
3274 return correct;
3279 This checks a couple of trans2 calls
3281 static bool run_trans2test(int dummy)
3283 struct cli_state *cli;
3284 uint16_t fnum;
3285 SMB_OFF_T size;
3286 time_t c_time, a_time, m_time;
3287 struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
3288 const char *fname = "\\trans2.tst";
3289 const char *dname = "\\trans2";
3290 const char *fname2 = "\\trans2\\trans2.tst";
3291 char *pname;
3292 bool correct = True;
3293 NTSTATUS status;
3294 uint32_t fs_attr;
3296 printf("starting trans2 test\n");
3298 if (!torture_open_connection(&cli, 0)) {
3299 return False;
3302 status = cli_get_fs_attr_info(cli, &fs_attr);
3303 if (!NT_STATUS_IS_OK(status)) {
3304 printf("ERROR: cli_get_fs_attr_info returned %s\n",
3305 nt_errstr(status));
3306 correct = false;
3309 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3310 cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3311 status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
3312 &a_time_ts, &w_time_ts, &m_time_ts, NULL);
3313 if (!NT_STATUS_IS_OK(status)) {
3314 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
3315 correct = False;
3318 status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
3319 if (!NT_STATUS_IS_OK(status)) {
3320 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
3321 correct = False;
3324 if (strcmp(pname, fname)) {
3325 printf("qfilename gave different name? [%s] [%s]\n",
3326 fname, pname);
3327 correct = False;
3330 cli_close(cli, fnum);
3332 sleep(2);
3334 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3335 status = cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
3336 &fnum);
3337 if (!NT_STATUS_IS_OK(status)) {
3338 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3339 return False;
3341 cli_close(cli, fnum);
3343 status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
3344 NULL);
3345 if (!NT_STATUS_IS_OK(status)) {
3346 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
3347 correct = False;
3348 } else {
3349 time_t t = time(NULL);
3351 if (c_time != m_time) {
3352 printf("create time=%s", ctime(&c_time));
3353 printf("modify time=%s", ctime(&m_time));
3354 printf("This system appears to have sticky create times\n");
3356 if ((abs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
3357 printf("access time=%s", ctime(&a_time));
3358 printf("This system appears to set a midnight access time\n");
3359 correct = False;
3362 if (abs(m_time - t) > 60*60*24*7) {
3363 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
3364 correct = False;
3369 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3370 cli_open(cli, fname,
3371 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3372 cli_close(cli, fnum);
3373 status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
3374 &m_time_ts, &size, NULL, NULL);
3375 if (!NT_STATUS_IS_OK(status)) {
3376 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3377 correct = False;
3378 } else {
3379 if (w_time_ts.tv_sec < 60*60*24*2) {
3380 printf("write time=%s", ctime(&w_time_ts.tv_sec));
3381 printf("This system appears to set a initial 0 write time\n");
3382 correct = False;
3386 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3389 /* check if the server updates the directory modification time
3390 when creating a new file */
3391 status = cli_mkdir(cli, dname);
3392 if (!NT_STATUS_IS_OK(status)) {
3393 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
3394 correct = False;
3396 sleep(3);
3397 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3398 &w_time_ts, &m_time_ts, &size, NULL, NULL);
3399 if (!NT_STATUS_IS_OK(status)) {
3400 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3401 correct = False;
3404 cli_open(cli, fname2,
3405 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3406 cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
3407 cli_close(cli, fnum);
3408 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3409 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
3410 if (!NT_STATUS_IS_OK(status)) {
3411 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3412 correct = False;
3413 } else {
3414 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
3415 == 0) {
3416 printf("This system does not update directory modification times\n");
3417 correct = False;
3420 cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3421 cli_rmdir(cli, dname);
3423 if (!torture_close_connection(cli)) {
3424 correct = False;
3427 printf("trans2 test finished\n");
3429 return correct;
3433 This checks new W2K calls.
3436 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
3438 uint8_t *buf = NULL;
3439 uint32 len;
3440 NTSTATUS status;
3442 status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
3443 CLI_BUFFER_SIZE, NULL, &buf, &len);
3444 if (!NT_STATUS_IS_OK(status)) {
3445 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
3446 nt_errstr(status));
3447 } else {
3448 printf("qfileinfo: level %d, len = %u\n", level, len);
3449 dump_data(0, (uint8 *)buf, len);
3450 printf("\n");
3452 TALLOC_FREE(buf);
3453 return status;
3456 static bool run_w2ktest(int dummy)
3458 struct cli_state *cli;
3459 uint16_t fnum;
3460 const char *fname = "\\w2ktest\\w2k.tst";
3461 int level;
3462 bool correct = True;
3464 printf("starting w2k test\n");
3466 if (!torture_open_connection(&cli, 0)) {
3467 return False;
3470 cli_open(cli, fname,
3471 O_RDWR | O_CREAT , DENY_NONE, &fnum);
3473 for (level = 1004; level < 1040; level++) {
3474 new_trans(cli, fnum, level);
3477 cli_close(cli, fnum);
3479 if (!torture_close_connection(cli)) {
3480 correct = False;
3483 printf("w2k test finished\n");
3485 return correct;
3490 this is a harness for some oplock tests
3492 static bool run_oplock1(int dummy)
3494 struct cli_state *cli1;
3495 const char *fname = "\\lockt1.lck";
3496 uint16_t fnum1;
3497 bool correct = True;
3498 NTSTATUS status;
3500 printf("starting oplock test 1\n");
3502 if (!torture_open_connection(&cli1, 0)) {
3503 return False;
3506 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3508 cli_sockopt(cli1, sockops);
3510 cli1->use_oplocks = True;
3512 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3513 &fnum1);
3514 if (!NT_STATUS_IS_OK(status)) {
3515 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3516 return False;
3519 cli1->use_oplocks = False;
3521 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3522 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3524 status = cli_close(cli1, fnum1);
3525 if (!NT_STATUS_IS_OK(status)) {
3526 printf("close2 failed (%s)\n", nt_errstr(status));
3527 return False;
3530 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3531 if (!NT_STATUS_IS_OK(status)) {
3532 printf("unlink failed (%s)\n", nt_errstr(status));
3533 return False;
3536 if (!torture_close_connection(cli1)) {
3537 correct = False;
3540 printf("finished oplock test 1\n");
3542 return correct;
3545 static bool run_oplock2(int dummy)
3547 struct cli_state *cli1, *cli2;
3548 const char *fname = "\\lockt2.lck";
3549 uint16_t fnum1, fnum2;
3550 int saved_use_oplocks = use_oplocks;
3551 char buf[4];
3552 bool correct = True;
3553 volatile bool *shared_correct;
3554 size_t nread;
3555 NTSTATUS status;
3557 shared_correct = (volatile bool *)shm_setup(sizeof(bool));
3558 *shared_correct = True;
3560 use_level_II_oplocks = True;
3561 use_oplocks = True;
3563 printf("starting oplock test 2\n");
3565 if (!torture_open_connection(&cli1, 0)) {
3566 use_level_II_oplocks = False;
3567 use_oplocks = saved_use_oplocks;
3568 return False;
3571 if (!torture_open_connection(&cli2, 1)) {
3572 use_level_II_oplocks = False;
3573 use_oplocks = saved_use_oplocks;
3574 return False;
3577 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3579 cli_sockopt(cli1, sockops);
3580 cli_sockopt(cli2, sockops);
3582 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3583 &fnum1);
3584 if (!NT_STATUS_IS_OK(status)) {
3585 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3586 return False;
3589 /* Don't need the globals any more. */
3590 use_level_II_oplocks = False;
3591 use_oplocks = saved_use_oplocks;
3593 if (fork() == 0) {
3594 /* Child code */
3595 status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
3596 if (!NT_STATUS_IS_OK(status)) {
3597 printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
3598 *shared_correct = False;
3599 exit(0);
3602 sleep(2);
3604 status = cli_close(cli2, fnum2);
3605 if (!NT_STATUS_IS_OK(status)) {
3606 printf("close2 failed (%s)\n", nt_errstr(status));
3607 *shared_correct = False;
3610 exit(0);
3613 sleep(2);
3615 /* Ensure cli1 processes the break. Empty file should always return 0
3616 * bytes. */
3617 status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
3618 if (!NT_STATUS_IS_OK(status)) {
3619 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
3620 correct = false;
3621 } else if (nread != 0) {
3622 printf("read on empty fnum1 failed. recv %ld expected %d\n",
3623 (unsigned long)nread, 0);
3624 correct = false;
3627 /* Should now be at level II. */
3628 /* Test if sending a write locks causes a break to none. */
3629 status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
3630 if (!NT_STATUS_IS_OK(status)) {
3631 printf("lock failed (%s)\n", nt_errstr(status));
3632 correct = False;
3635 cli_unlock(cli1, fnum1, 0, 4);
3637 sleep(2);
3639 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
3640 if (!NT_STATUS_IS_OK(status)) {
3641 printf("lock failed (%s)\n", nt_errstr(status));
3642 correct = False;
3645 cli_unlock(cli1, fnum1, 0, 4);
3647 sleep(2);
3649 cli_read(cli1, fnum1, buf, 0, 4, NULL);
3651 status = cli_close(cli1, fnum1);
3652 if (!NT_STATUS_IS_OK(status)) {
3653 printf("close1 failed (%s)\n", nt_errstr(status));
3654 correct = False;
3657 sleep(4);
3659 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3660 if (!NT_STATUS_IS_OK(status)) {
3661 printf("unlink failed (%s)\n", nt_errstr(status));
3662 correct = False;
3665 if (!torture_close_connection(cli1)) {
3666 correct = False;
3669 if (!*shared_correct) {
3670 correct = False;
3673 printf("finished oplock test 2\n");
3675 return correct;
3678 struct oplock4_state {
3679 struct tevent_context *ev;
3680 struct cli_state *cli;
3681 bool *got_break;
3682 uint16_t *fnum2;
3685 static void oplock4_got_break(struct tevent_req *req);
3686 static void oplock4_got_open(struct tevent_req *req);
3688 static bool run_oplock4(int dummy)
3690 struct tevent_context *ev;
3691 struct cli_state *cli1, *cli2;
3692 struct tevent_req *oplock_req, *open_req;
3693 const char *fname = "\\lockt4.lck";
3694 const char *fname_ln = "\\lockt4_ln.lck";
3695 uint16_t fnum1, fnum2;
3696 int saved_use_oplocks = use_oplocks;
3697 NTSTATUS status;
3698 bool correct = true;
3700 bool got_break;
3702 struct oplock4_state *state;
3704 printf("starting oplock test 4\n");
3706 if (!torture_open_connection(&cli1, 0)) {
3707 use_level_II_oplocks = false;
3708 use_oplocks = saved_use_oplocks;
3709 return false;
3712 if (!torture_open_connection(&cli2, 1)) {
3713 use_level_II_oplocks = false;
3714 use_oplocks = saved_use_oplocks;
3715 return false;
3718 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3719 cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3721 cli_sockopt(cli1, sockops);
3722 cli_sockopt(cli2, sockops);
3724 /* Create the file. */
3725 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3726 &fnum1);
3727 if (!NT_STATUS_IS_OK(status)) {
3728 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3729 return false;
3732 status = cli_close(cli1, fnum1);
3733 if (!NT_STATUS_IS_OK(status)) {
3734 printf("close1 failed (%s)\n", nt_errstr(status));
3735 return false;
3738 /* Now create a hardlink. */
3739 status = cli_nt_hardlink(cli1, fname, fname_ln);
3740 if (!NT_STATUS_IS_OK(status)) {
3741 printf("nt hardlink failed (%s)\n", nt_errstr(status));
3742 return false;
3745 /* Prove that opening hardlinks cause deny modes to conflict. */
3746 status = cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
3747 if (!NT_STATUS_IS_OK(status)) {
3748 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3749 return false;
3752 status = cli_open(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
3753 if (NT_STATUS_IS_OK(status)) {
3754 printf("open of %s succeeded - should fail with sharing violation.\n",
3755 fname_ln);
3756 return false;
3759 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3760 printf("open of %s should fail with sharing violation. Got %s\n",
3761 fname_ln, nt_errstr(status));
3762 return false;
3765 status = cli_close(cli1, fnum1);
3766 if (!NT_STATUS_IS_OK(status)) {
3767 printf("close1 failed (%s)\n", nt_errstr(status));
3768 return false;
3771 cli1->use_oplocks = true;
3772 cli2->use_oplocks = true;
3774 status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3775 if (!NT_STATUS_IS_OK(status)) {
3776 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3777 return false;
3780 ev = tevent_context_init(talloc_tos());
3781 if (ev == NULL) {
3782 printf("tevent_req_create failed\n");
3783 return false;
3786 state = talloc(ev, struct oplock4_state);
3787 if (state == NULL) {
3788 printf("talloc failed\n");
3789 return false;
3791 state->ev = ev;
3792 state->cli = cli1;
3793 state->got_break = &got_break;
3794 state->fnum2 = &fnum2;
3796 oplock_req = cli_smb_oplock_break_waiter_send(
3797 talloc_tos(), ev, cli1);
3798 if (oplock_req == NULL) {
3799 printf("cli_smb_oplock_break_waiter_send failed\n");
3800 return false;
3802 tevent_req_set_callback(oplock_req, oplock4_got_break, state);
3804 open_req = cli_open_send(
3805 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
3806 if (oplock_req == NULL) {
3807 printf("cli_open_send failed\n");
3808 return false;
3810 tevent_req_set_callback(open_req, oplock4_got_open, state);
3812 got_break = false;
3813 fnum2 = 0xffff;
3815 while (!got_break || fnum2 == 0xffff) {
3816 int ret;
3817 ret = tevent_loop_once(ev);
3818 if (ret == -1) {
3819 printf("tevent_loop_once failed: %s\n",
3820 strerror(errno));
3821 return false;
3825 status = cli_close(cli2, fnum2);
3826 if (!NT_STATUS_IS_OK(status)) {
3827 printf("close2 failed (%s)\n", nt_errstr(status));
3828 correct = false;
3831 status = cli_close(cli1, fnum1);
3832 if (!NT_STATUS_IS_OK(status)) {
3833 printf("close1 failed (%s)\n", nt_errstr(status));
3834 correct = false;
3837 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3838 if (!NT_STATUS_IS_OK(status)) {
3839 printf("unlink failed (%s)\n", nt_errstr(status));
3840 correct = false;
3843 status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3844 if (!NT_STATUS_IS_OK(status)) {
3845 printf("unlink failed (%s)\n", nt_errstr(status));
3846 correct = false;
3849 if (!torture_close_connection(cli1)) {
3850 correct = false;
3853 if (!got_break) {
3854 correct = false;
3857 printf("finished oplock test 4\n");
3859 return correct;
3862 static void oplock4_got_break(struct tevent_req *req)
3864 struct oplock4_state *state = tevent_req_callback_data(
3865 req, struct oplock4_state);
3866 uint16_t fnum;
3867 uint8_t level;
3868 NTSTATUS status;
3870 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
3871 TALLOC_FREE(req);
3872 if (!NT_STATUS_IS_OK(status)) {
3873 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
3874 nt_errstr(status));
3875 return;
3877 *state->got_break = true;
3879 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
3880 NO_OPLOCK);
3881 if (req == NULL) {
3882 printf("cli_oplock_ack_send failed\n");
3883 return;
3887 static void oplock4_got_open(struct tevent_req *req)
3889 struct oplock4_state *state = tevent_req_callback_data(
3890 req, struct oplock4_state);
3891 NTSTATUS status;
3893 status = cli_open_recv(req, state->fnum2);
3894 if (!NT_STATUS_IS_OK(status)) {
3895 printf("cli_open_recv returned %s\n", nt_errstr(status));
3896 *state->fnum2 = 0xffff;
3901 Test delete on close semantics.
3903 static bool run_deletetest(int dummy)
3905 struct cli_state *cli1 = NULL;
3906 struct cli_state *cli2 = NULL;
3907 const char *fname = "\\delete.file";
3908 uint16_t fnum1 = (uint16_t)-1;
3909 uint16_t fnum2 = (uint16_t)-1;
3910 bool correct = True;
3911 NTSTATUS status;
3913 printf("starting delete test\n");
3915 if (!torture_open_connection(&cli1, 0)) {
3916 return False;
3919 cli_sockopt(cli1, sockops);
3921 /* Test 1 - this should delete the file on close. */
3923 cli_setatr(cli1, fname, 0, 0);
3924 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3926 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
3927 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
3928 FILE_DELETE_ON_CLOSE, 0, &fnum1);
3929 if (!NT_STATUS_IS_OK(status)) {
3930 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
3931 correct = False;
3932 goto fail;
3935 status = cli_close(cli1, fnum1);
3936 if (!NT_STATUS_IS_OK(status)) {
3937 printf("[1] close failed (%s)\n", nt_errstr(status));
3938 correct = False;
3939 goto fail;
3942 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1))) {
3943 printf("[1] open of %s succeeded (should fail)\n", fname);
3944 correct = False;
3945 goto fail;
3948 printf("first delete on close test succeeded.\n");
3950 /* Test 2 - this should delete the file on close. */
3952 cli_setatr(cli1, fname, 0, 0);
3953 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3955 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3956 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
3957 FILE_OVERWRITE_IF, 0, 0, &fnum1);
3958 if (!NT_STATUS_IS_OK(status)) {
3959 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
3960 correct = False;
3961 goto fail;
3964 status = cli_nt_delete_on_close(cli1, fnum1, true);
3965 if (!NT_STATUS_IS_OK(status)) {
3966 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
3967 correct = False;
3968 goto fail;
3971 status = cli_close(cli1, fnum1);
3972 if (!NT_STATUS_IS_OK(status)) {
3973 printf("[2] close failed (%s)\n", nt_errstr(status));
3974 correct = False;
3975 goto fail;
3978 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3979 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
3980 status = cli_close(cli1, fnum1);
3981 if (!NT_STATUS_IS_OK(status)) {
3982 printf("[2] close failed (%s)\n", nt_errstr(status));
3983 correct = False;
3984 goto fail;
3986 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3987 } else
3988 printf("second delete on close test succeeded.\n");
3990 /* Test 3 - ... */
3991 cli_setatr(cli1, fname, 0, 0);
3992 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3994 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3995 FILE_ATTRIBUTE_NORMAL,
3996 FILE_SHARE_READ|FILE_SHARE_WRITE,
3997 FILE_OVERWRITE_IF, 0, 0, &fnum1);
3998 if (!NT_STATUS_IS_OK(status)) {
3999 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
4000 correct = False;
4001 goto fail;
4004 /* This should fail with a sharing violation - open for delete is only compatible
4005 with SHARE_DELETE. */
4007 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4008 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, 0, &fnum2))) {
4009 printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
4010 correct = False;
4011 goto fail;
4014 /* This should succeed. */
4015 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4016 FILE_ATTRIBUTE_NORMAL,
4017 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4018 FILE_OPEN, 0, 0, &fnum2);
4019 if (!NT_STATUS_IS_OK(status)) {
4020 printf("[3] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
4021 correct = False;
4022 goto fail;
4025 status = cli_nt_delete_on_close(cli1, fnum1, true);
4026 if (!NT_STATUS_IS_OK(status)) {
4027 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
4028 correct = False;
4029 goto fail;
4032 status = cli_close(cli1, fnum1);
4033 if (!NT_STATUS_IS_OK(status)) {
4034 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
4035 correct = False;
4036 goto fail;
4039 status = cli_close(cli1, fnum2);
4040 if (!NT_STATUS_IS_OK(status)) {
4041 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
4042 correct = False;
4043 goto fail;
4046 /* This should fail - file should no longer be there. */
4048 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
4049 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
4050 status = cli_close(cli1, fnum1);
4051 if (!NT_STATUS_IS_OK(status)) {
4052 printf("[3] close failed (%s)\n", nt_errstr(status));
4054 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4055 correct = False;
4056 goto fail;
4057 } else
4058 printf("third delete on close test succeeded.\n");
4060 /* Test 4 ... */
4061 cli_setatr(cli1, fname, 0, 0);
4062 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4064 status = cli_ntcreate(cli1, fname, 0,
4065 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4066 FILE_ATTRIBUTE_NORMAL,
4067 FILE_SHARE_READ|FILE_SHARE_WRITE,
4068 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4069 if (!NT_STATUS_IS_OK(status)) {
4070 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
4071 correct = False;
4072 goto fail;
4075 /* This should succeed. */
4076 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4077 FILE_ATTRIBUTE_NORMAL,
4078 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4079 FILE_OPEN, 0, 0, &fnum2);
4080 if (!NT_STATUS_IS_OK(status)) {
4081 printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
4082 correct = False;
4083 goto fail;
4086 status = cli_close(cli1, fnum2);
4087 if (!NT_STATUS_IS_OK(status)) {
4088 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
4089 correct = False;
4090 goto fail;
4093 status = cli_nt_delete_on_close(cli1, fnum1, true);
4094 if (!NT_STATUS_IS_OK(status)) {
4095 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
4096 correct = False;
4097 goto fail;
4100 /* This should fail - no more opens once delete on close set. */
4101 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4102 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4103 FILE_OPEN, 0, 0, &fnum2))) {
4104 printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
4105 correct = False;
4106 goto fail;
4107 } else
4108 printf("fourth delete on close test succeeded.\n");
4110 status = cli_close(cli1, fnum1);
4111 if (!NT_STATUS_IS_OK(status)) {
4112 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
4113 correct = False;
4114 goto fail;
4117 /* Test 5 ... */
4118 cli_setatr(cli1, fname, 0, 0);
4119 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4121 status = cli_open(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
4122 if (!NT_STATUS_IS_OK(status)) {
4123 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4124 correct = False;
4125 goto fail;
4128 /* This should fail - only allowed on NT opens with DELETE access. */
4130 if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4131 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
4132 correct = False;
4133 goto fail;
4136 status = cli_close(cli1, fnum1);
4137 if (!NT_STATUS_IS_OK(status)) {
4138 printf("[5] close - 2 failed (%s)\n", nt_errstr(status));
4139 correct = False;
4140 goto fail;
4143 printf("fifth delete on close test succeeded.\n");
4145 /* Test 6 ... */
4146 cli_setatr(cli1, fname, 0, 0);
4147 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4149 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4150 FILE_ATTRIBUTE_NORMAL,
4151 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4152 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4153 if (!NT_STATUS_IS_OK(status)) {
4154 printf("[6] open of %s failed (%s)\n", fname,
4155 nt_errstr(status));
4156 correct = False;
4157 goto fail;
4160 /* This should fail - only allowed on NT opens with DELETE access. */
4162 if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4163 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
4164 correct = False;
4165 goto fail;
4168 status = cli_close(cli1, fnum1);
4169 if (!NT_STATUS_IS_OK(status)) {
4170 printf("[6] close - 2 failed (%s)\n", nt_errstr(status));
4171 correct = False;
4172 goto fail;
4175 printf("sixth delete on close test succeeded.\n");
4177 /* Test 7 ... */
4178 cli_setatr(cli1, fname, 0, 0);
4179 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4181 status = cli_ntcreate(cli1, fname, 0,
4182 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4183 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
4184 0, 0, &fnum1);
4185 if (!NT_STATUS_IS_OK(status)) {
4186 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4187 correct = False;
4188 goto fail;
4191 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4192 printf("[7] setting delete_on_close on file failed !\n");
4193 correct = False;
4194 goto fail;
4197 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, false))) {
4198 printf("[7] unsetting delete_on_close on file failed !\n");
4199 correct = False;
4200 goto fail;
4203 status = cli_close(cli1, fnum1);
4204 if (!NT_STATUS_IS_OK(status)) {
4205 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4206 correct = False;
4207 goto fail;
4210 /* This next open should succeed - we reset the flag. */
4211 status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4212 if (!NT_STATUS_IS_OK(status)) {
4213 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4214 correct = False;
4215 goto fail;
4218 status = cli_close(cli1, fnum1);
4219 if (!NT_STATUS_IS_OK(status)) {
4220 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4221 correct = False;
4222 goto fail;
4225 printf("seventh delete on close test succeeded.\n");
4227 /* Test 7 ... */
4228 cli_setatr(cli1, fname, 0, 0);
4229 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4231 if (!torture_open_connection(&cli2, 1)) {
4232 printf("[8] failed to open second connection.\n");
4233 correct = False;
4234 goto fail;
4237 cli_sockopt(cli1, sockops);
4239 status = cli_ntcreate(cli1, fname, 0,
4240 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4241 FILE_ATTRIBUTE_NORMAL,
4242 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4243 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4244 if (!NT_STATUS_IS_OK(status)) {
4245 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4246 correct = False;
4247 goto fail;
4250 status = cli_ntcreate(cli2, fname, 0,
4251 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4252 FILE_ATTRIBUTE_NORMAL,
4253 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4254 FILE_OPEN, 0, 0, &fnum2);
4255 if (!NT_STATUS_IS_OK(status)) {
4256 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4257 correct = False;
4258 goto fail;
4261 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4262 printf("[8] setting delete_on_close on file failed !\n");
4263 correct = False;
4264 goto fail;
4267 status = cli_close(cli1, fnum1);
4268 if (!NT_STATUS_IS_OK(status)) {
4269 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
4270 correct = False;
4271 goto fail;
4274 status = cli_close(cli2, fnum2);
4275 if (!NT_STATUS_IS_OK(status)) {
4276 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
4277 correct = False;
4278 goto fail;
4281 /* This should fail.. */
4282 status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4283 if (NT_STATUS_IS_OK(status)) {
4284 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
4285 goto fail;
4286 correct = False;
4287 } else
4288 printf("eighth delete on close test succeeded.\n");
4290 /* This should fail - we need to set DELETE_ACCESS. */
4291 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0,FILE_READ_DATA|FILE_WRITE_DATA,
4292 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE, 0, &fnum1))) {
4293 printf("[9] open of %s succeeded should have failed!\n", fname);
4294 correct = False;
4295 goto fail;
4298 printf("ninth delete on close test succeeded.\n");
4300 status = cli_ntcreate(cli1, fname, 0,
4301 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4302 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4303 FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
4304 0, &fnum1);
4305 if (!NT_STATUS_IS_OK(status)) {
4306 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
4307 correct = False;
4308 goto fail;
4311 /* This should delete the file. */
4312 status = cli_close(cli1, fnum1);
4313 if (!NT_STATUS_IS_OK(status)) {
4314 printf("[10] close failed (%s)\n", nt_errstr(status));
4315 correct = False;
4316 goto fail;
4319 /* This should fail.. */
4320 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
4321 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
4322 goto fail;
4323 correct = False;
4324 } else
4325 printf("tenth delete on close test succeeded.\n");
4327 cli_setatr(cli1, fname, 0, 0);
4328 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4330 /* What error do we get when attempting to open a read-only file with
4331 delete access ? */
4333 /* Create a readonly file. */
4334 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4335 FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
4336 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4337 if (!NT_STATUS_IS_OK(status)) {
4338 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
4339 correct = False;
4340 goto fail;
4343 status = cli_close(cli1, fnum1);
4344 if (!NT_STATUS_IS_OK(status)) {
4345 printf("[11] close failed (%s)\n", nt_errstr(status));
4346 correct = False;
4347 goto fail;
4350 /* Now try open for delete access. */
4351 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES|DELETE_ACCESS,
4352 0, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4353 FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4354 printf("[11] open of %s succeeded should have been denied with ACCESS_DENIED!\n", fname);
4355 cli_close(cli1, fnum1);
4356 goto fail;
4357 correct = False;
4358 } else {
4359 NTSTATUS nterr = cli_nt_error(cli1);
4360 if (!NT_STATUS_EQUAL(nterr,NT_STATUS_ACCESS_DENIED)) {
4361 printf("[11] open of %s should have been denied with ACCESS_DENIED! Got error %s\n", fname, nt_errstr(nterr));
4362 goto fail;
4363 correct = False;
4364 } else {
4365 printf("eleventh delete on close test succeeded.\n");
4369 printf("finished delete test\n");
4371 fail:
4372 /* FIXME: This will crash if we aborted before cli2 got
4373 * intialized, because these functions don't handle
4374 * uninitialized connections. */
4376 if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
4377 if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
4378 cli_setatr(cli1, fname, 0, 0);
4379 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4381 if (cli1 && !torture_close_connection(cli1)) {
4382 correct = False;
4384 if (cli2 && !torture_close_connection(cli2)) {
4385 correct = False;
4387 return correct;
4390 static bool run_deletetest_ln(int dummy)
4392 struct cli_state *cli;
4393 const char *fname = "\\delete1";
4394 const char *fname_ln = "\\delete1_ln";
4395 uint16_t fnum;
4396 uint16_t fnum1;
4397 NTSTATUS status;
4398 bool correct = true;
4399 time_t t;
4401 printf("starting deletetest-ln\n");
4403 if (!torture_open_connection(&cli, 0)) {
4404 return false;
4407 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4408 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4410 cli_sockopt(cli, sockops);
4412 /* Create the file. */
4413 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
4414 if (!NT_STATUS_IS_OK(status)) {
4415 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4416 return false;
4419 status = cli_close(cli, fnum);
4420 if (!NT_STATUS_IS_OK(status)) {
4421 printf("close1 failed (%s)\n", nt_errstr(status));
4422 return false;
4425 /* Now create a hardlink. */
4426 status = cli_nt_hardlink(cli, fname, fname_ln);
4427 if (!NT_STATUS_IS_OK(status)) {
4428 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4429 return false;
4432 /* Open the original file. */
4433 status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
4434 FILE_ATTRIBUTE_NORMAL,
4435 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4436 FILE_OPEN_IF, 0, 0, &fnum);
4437 if (!NT_STATUS_IS_OK(status)) {
4438 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
4439 return false;
4442 /* Unlink the hard link path. */
4443 status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
4444 FILE_ATTRIBUTE_NORMAL,
4445 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4446 FILE_OPEN_IF, 0, 0, &fnum1);
4447 if (!NT_STATUS_IS_OK(status)) {
4448 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
4449 return false;
4451 status = cli_nt_delete_on_close(cli, fnum1, true);
4452 if (!NT_STATUS_IS_OK(status)) {
4453 d_printf("(%s) failed to set delete_on_close %s: %s\n",
4454 __location__, fname_ln, nt_errstr(status));
4455 return false;
4458 status = cli_close(cli, fnum1);
4459 if (!NT_STATUS_IS_OK(status)) {
4460 printf("close %s failed (%s)\n",
4461 fname_ln, nt_errstr(status));
4462 return false;
4465 status = cli_close(cli, fnum);
4466 if (!NT_STATUS_IS_OK(status)) {
4467 printf("close %s failed (%s)\n",
4468 fname, nt_errstr(status));
4469 return false;
4472 /* Ensure the original file is still there. */
4473 status = cli_getatr(cli, fname, NULL, NULL, &t);
4474 if (!NT_STATUS_IS_OK(status)) {
4475 printf("%s getatr on file %s failed (%s)\n",
4476 __location__,
4477 fname,
4478 nt_errstr(status));
4479 correct = False;
4482 /* Ensure the link path is gone. */
4483 status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
4484 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4485 printf("%s, getatr for file %s returned wrong error code %s "
4486 "- should have been deleted\n",
4487 __location__,
4488 fname_ln, nt_errstr(status));
4489 correct = False;
4492 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4493 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4495 if (!torture_close_connection(cli)) {
4496 correct = false;
4499 printf("finished deletetest-ln\n");
4501 return correct;
4505 print out server properties
4507 static bool run_properties(int dummy)
4509 struct cli_state *cli;
4510 bool correct = True;
4512 printf("starting properties test\n");
4514 ZERO_STRUCT(cli);
4516 if (!torture_open_connection(&cli, 0)) {
4517 return False;
4520 cli_sockopt(cli, sockops);
4522 d_printf("Capabilities 0x%08x\n", cli_state_capabilities(cli));
4524 if (!torture_close_connection(cli)) {
4525 correct = False;
4528 return correct;
4533 /* FIRST_DESIRED_ACCESS 0xf019f */
4534 #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
4535 FILE_READ_EA| /* 0xf */ \
4536 FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
4537 FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
4538 DELETE_ACCESS|READ_CONTROL_ACCESS|\
4539 WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
4540 /* SECOND_DESIRED_ACCESS 0xe0080 */
4541 #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
4542 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4543 WRITE_OWNER_ACCESS /* 0xe0000 */
4545 #if 0
4546 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
4547 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4548 FILE_READ_DATA|\
4549 WRITE_OWNER_ACCESS /* */
4550 #endif
4553 Test ntcreate calls made by xcopy
4555 static bool run_xcopy(int dummy)
4557 static struct cli_state *cli1;
4558 const char *fname = "\\test.txt";
4559 bool correct = True;
4560 uint16_t fnum1, fnum2;
4561 NTSTATUS status;
4563 printf("starting xcopy test\n");
4565 if (!torture_open_connection(&cli1, 0)) {
4566 return False;
4569 status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
4570 FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
4571 FILE_OVERWRITE_IF, 0x4044, 0, &fnum1);
4572 if (!NT_STATUS_IS_OK(status)) {
4573 printf("First open failed - %s\n", nt_errstr(status));
4574 return False;
4577 status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
4578 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4579 FILE_OPEN, 0x200000, 0, &fnum2);
4580 if (!NT_STATUS_IS_OK(status)) {
4581 printf("second open failed - %s\n", nt_errstr(status));
4582 return False;
4585 if (!torture_close_connection(cli1)) {
4586 correct = False;
4589 return correct;
4593 Test rename on files open with share delete and no share delete.
4595 static bool run_rename(int dummy)
4597 static struct cli_state *cli1;
4598 const char *fname = "\\test.txt";
4599 const char *fname1 = "\\test1.txt";
4600 bool correct = True;
4601 uint16_t fnum1;
4602 uint16_t attr;
4603 NTSTATUS status;
4605 printf("starting rename test\n");
4607 if (!torture_open_connection(&cli1, 0)) {
4608 return False;
4611 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4612 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4614 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4615 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
4616 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4617 if (!NT_STATUS_IS_OK(status)) {
4618 printf("First open failed - %s\n", nt_errstr(status));
4619 return False;
4622 status = cli_rename(cli1, fname, fname1);
4623 if (!NT_STATUS_IS_OK(status)) {
4624 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
4625 } else {
4626 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
4627 correct = False;
4630 status = cli_close(cli1, fnum1);
4631 if (!NT_STATUS_IS_OK(status)) {
4632 printf("close - 1 failed (%s)\n", nt_errstr(status));
4633 return False;
4636 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4637 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4638 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4639 #if 0
4640 FILE_SHARE_DELETE|FILE_SHARE_NONE,
4641 #else
4642 FILE_SHARE_DELETE|FILE_SHARE_READ,
4643 #endif
4644 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4645 if (!NT_STATUS_IS_OK(status)) {
4646 printf("Second open failed - %s\n", nt_errstr(status));
4647 return False;
4650 status = cli_rename(cli1, fname, fname1);
4651 if (!NT_STATUS_IS_OK(status)) {
4652 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
4653 correct = False;
4654 } else {
4655 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
4658 status = cli_close(cli1, fnum1);
4659 if (!NT_STATUS_IS_OK(status)) {
4660 printf("close - 2 failed (%s)\n", nt_errstr(status));
4661 return False;
4664 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4665 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4667 status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
4668 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4669 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4670 if (!NT_STATUS_IS_OK(status)) {
4671 printf("Third open failed - %s\n", nt_errstr(status));
4672 return False;
4676 #if 0
4678 uint16_t fnum2;
4680 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
4681 FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4682 printf("Fourth open failed - %s\n", cli_errstr(cli1));
4683 return False;
4685 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum2, true))) {
4686 printf("[8] setting delete_on_close on file failed !\n");
4687 return False;
4690 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
4691 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
4692 return False;
4695 #endif
4697 status = cli_rename(cli1, fname, fname1);
4698 if (!NT_STATUS_IS_OK(status)) {
4699 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
4700 correct = False;
4701 } else {
4702 printf("Third rename succeeded (SHARE_NONE)\n");
4705 status = cli_close(cli1, fnum1);
4706 if (!NT_STATUS_IS_OK(status)) {
4707 printf("close - 3 failed (%s)\n", nt_errstr(status));
4708 return False;
4711 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4712 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4714 /*----*/
4716 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4717 FILE_ATTRIBUTE_NORMAL,
4718 FILE_SHARE_READ | FILE_SHARE_WRITE,
4719 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4720 if (!NT_STATUS_IS_OK(status)) {
4721 printf("Fourth open failed - %s\n", nt_errstr(status));
4722 return False;
4725 status = cli_rename(cli1, fname, fname1);
4726 if (!NT_STATUS_IS_OK(status)) {
4727 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
4728 } else {
4729 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
4730 correct = False;
4733 status = cli_close(cli1, fnum1);
4734 if (!NT_STATUS_IS_OK(status)) {
4735 printf("close - 4 failed (%s)\n", nt_errstr(status));
4736 return False;
4739 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4740 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4742 /*--*/
4744 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4745 FILE_ATTRIBUTE_NORMAL,
4746 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4747 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4748 if (!NT_STATUS_IS_OK(status)) {
4749 printf("Fifth open failed - %s\n", nt_errstr(status));
4750 return False;
4753 status = cli_rename(cli1, fname, fname1);
4754 if (!NT_STATUS_IS_OK(status)) {
4755 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
4756 correct = False;
4757 } else {
4758 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
4762 * Now check if the first name still exists ...
4765 /* if (!NT_STATUS_OP(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4766 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4767 printf("Opening original file after rename of open file fails: %s\n",
4768 cli_errstr(cli1));
4770 else {
4771 printf("Opening original file after rename of open file works ...\n");
4772 (void)cli_close(cli1, fnum2);
4773 } */
4775 /*--*/
4776 status = cli_close(cli1, fnum1);
4777 if (!NT_STATUS_IS_OK(status)) {
4778 printf("close - 5 failed (%s)\n", nt_errstr(status));
4779 return False;
4782 /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
4783 status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
4784 if (!NT_STATUS_IS_OK(status)) {
4785 printf("getatr on file %s failed - %s ! \n",
4786 fname1, nt_errstr(status));
4787 correct = False;
4788 } else {
4789 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
4790 printf("Renamed file %s has wrong attr 0x%x "
4791 "(should be 0x%x)\n",
4792 fname1,
4793 attr,
4794 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
4795 correct = False;
4796 } else {
4797 printf("Renamed file %s has archive bit set\n", fname1);
4801 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4802 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4804 if (!torture_close_connection(cli1)) {
4805 correct = False;
4808 return correct;
4811 static bool run_pipe_number(int dummy)
4813 struct cli_state *cli1;
4814 const char *pipe_name = "\\SPOOLSS";
4815 uint16_t fnum;
4816 int num_pipes = 0;
4817 NTSTATUS status;
4819 printf("starting pipenumber test\n");
4820 if (!torture_open_connection(&cli1, 0)) {
4821 return False;
4824 cli_sockopt(cli1, sockops);
4825 while(1) {
4826 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
4827 FILE_ATTRIBUTE_NORMAL,
4828 FILE_SHARE_READ|FILE_SHARE_WRITE,
4829 FILE_OPEN_IF, 0, 0, &fnum);
4830 if (!NT_STATUS_IS_OK(status)) {
4831 printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
4832 break;
4834 num_pipes++;
4835 printf("\r%6d", num_pipes);
4838 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
4839 torture_close_connection(cli1);
4840 return True;
4844 Test open mode returns on read-only files.
4846 static bool run_opentest(int dummy)
4848 static struct cli_state *cli1;
4849 static struct cli_state *cli2;
4850 const char *fname = "\\readonly.file";
4851 uint16_t fnum1, fnum2;
4852 char buf[20];
4853 SMB_OFF_T fsize;
4854 bool correct = True;
4855 char *tmp_path;
4856 NTSTATUS status;
4858 printf("starting open test\n");
4860 if (!torture_open_connection(&cli1, 0)) {
4861 return False;
4864 cli_setatr(cli1, fname, 0, 0);
4865 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4867 cli_sockopt(cli1, sockops);
4869 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4870 if (!NT_STATUS_IS_OK(status)) {
4871 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4872 return False;
4875 status = cli_close(cli1, fnum1);
4876 if (!NT_STATUS_IS_OK(status)) {
4877 printf("close2 failed (%s)\n", nt_errstr(status));
4878 return False;
4881 status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
4882 if (!NT_STATUS_IS_OK(status)) {
4883 printf("cli_setatr failed (%s)\n", nt_errstr(status));
4884 return False;
4887 status = cli_open(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4888 if (!NT_STATUS_IS_OK(status)) {
4889 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4890 return False;
4893 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
4894 status = cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4896 if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
4897 NT_STATUS_ACCESS_DENIED)) {
4898 printf("correct error code ERRDOS/ERRnoaccess returned\n");
4901 printf("finished open test 1\n");
4903 cli_close(cli1, fnum1);
4905 /* Now try not readonly and ensure ERRbadshare is returned. */
4907 cli_setatr(cli1, fname, 0, 0);
4909 status = cli_open(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4910 if (!NT_STATUS_IS_OK(status)) {
4911 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4912 return False;
4915 /* This will fail - but the error should be ERRshare. */
4916 status = cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4918 if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
4919 NT_STATUS_SHARING_VIOLATION)) {
4920 printf("correct error code ERRDOS/ERRbadshare returned\n");
4923 status = cli_close(cli1, fnum1);
4924 if (!NT_STATUS_IS_OK(status)) {
4925 printf("close2 failed (%s)\n", nt_errstr(status));
4926 return False;
4929 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4931 printf("finished open test 2\n");
4933 /* Test truncate open disposition on file opened for read. */
4934 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4935 if (!NT_STATUS_IS_OK(status)) {
4936 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
4937 return False;
4940 /* write 20 bytes. */
4942 memset(buf, '\0', 20);
4944 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
4945 if (!NT_STATUS_IS_OK(status)) {
4946 printf("write failed (%s)\n", nt_errstr(status));
4947 correct = False;
4950 status = cli_close(cli1, fnum1);
4951 if (!NT_STATUS_IS_OK(status)) {
4952 printf("(3) close1 failed (%s)\n", nt_errstr(status));
4953 return False;
4956 /* Ensure size == 20. */
4957 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
4958 if (!NT_STATUS_IS_OK(status)) {
4959 printf("(3) getatr failed (%s)\n", nt_errstr(status));
4960 return False;
4963 if (fsize != 20) {
4964 printf("(3) file size != 20\n");
4965 return False;
4968 /* Now test if we can truncate a file opened for readonly. */
4969 status = cli_open(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
4970 if (!NT_STATUS_IS_OK(status)) {
4971 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
4972 return False;
4975 status = cli_close(cli1, fnum1);
4976 if (!NT_STATUS_IS_OK(status)) {
4977 printf("close2 failed (%s)\n", nt_errstr(status));
4978 return False;
4981 /* Ensure size == 0. */
4982 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
4983 if (!NT_STATUS_IS_OK(status)) {
4984 printf("(3) getatr failed (%s)\n", nt_errstr(status));
4985 return False;
4988 if (fsize != 0) {
4989 printf("(3) file size != 0\n");
4990 return False;
4992 printf("finished open test 3\n");
4994 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4996 printf("Do ctemp tests\n");
4997 status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
4998 if (!NT_STATUS_IS_OK(status)) {
4999 printf("ctemp failed (%s)\n", nt_errstr(status));
5000 return False;
5003 printf("ctemp gave path %s\n", tmp_path);
5004 status = cli_close(cli1, fnum1);
5005 if (!NT_STATUS_IS_OK(status)) {
5006 printf("close of temp failed (%s)\n", nt_errstr(status));
5009 status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5010 if (!NT_STATUS_IS_OK(status)) {
5011 printf("unlink of temp failed (%s)\n", nt_errstr(status));
5014 /* Test the non-io opens... */
5016 if (!torture_open_connection(&cli2, 1)) {
5017 return False;
5020 cli_setatr(cli2, fname, 0, 0);
5021 cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5023 cli_sockopt(cli2, sockops);
5025 printf("TEST #1 testing 2 non-io opens (no delete)\n");
5026 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5027 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5028 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5029 if (!NT_STATUS_IS_OK(status)) {
5030 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5031 return False;
5034 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5035 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5036 FILE_OPEN_IF, 0, 0, &fnum2);
5037 if (!NT_STATUS_IS_OK(status)) {
5038 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5039 return False;
5042 status = cli_close(cli1, fnum1);
5043 if (!NT_STATUS_IS_OK(status)) {
5044 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5045 return False;
5048 status = cli_close(cli2, fnum2);
5049 if (!NT_STATUS_IS_OK(status)) {
5050 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5051 return False;
5054 printf("non-io open test #1 passed.\n");
5056 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5058 printf("TEST #2 testing 2 non-io opens (first with delete)\n");
5060 status = cli_ntcreate(cli1, fname, 0,
5061 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5062 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5063 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5064 if (!NT_STATUS_IS_OK(status)) {
5065 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5066 return False;
5069 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5070 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5071 FILE_OPEN_IF, 0, 0, &fnum2);
5072 if (!NT_STATUS_IS_OK(status)) {
5073 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5074 return False;
5077 status = cli_close(cli1, fnum1);
5078 if (!NT_STATUS_IS_OK(status)) {
5079 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5080 return False;
5083 status = cli_close(cli2, fnum2);
5084 if (!NT_STATUS_IS_OK(status)) {
5085 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5086 return False;
5089 printf("non-io open test #2 passed.\n");
5091 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5093 printf("TEST #3 testing 2 non-io opens (second with delete)\n");
5095 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5096 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5097 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5098 if (!NT_STATUS_IS_OK(status)) {
5099 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5100 return False;
5103 status = cli_ntcreate(cli2, fname, 0,
5104 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5105 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5106 FILE_OPEN_IF, 0, 0, &fnum2);
5107 if (!NT_STATUS_IS_OK(status)) {
5108 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5109 return False;
5112 status = cli_close(cli1, fnum1);
5113 if (!NT_STATUS_IS_OK(status)) {
5114 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5115 return False;
5118 status = cli_close(cli2, fnum2);
5119 if (!NT_STATUS_IS_OK(status)) {
5120 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5121 return False;
5124 printf("non-io open test #3 passed.\n");
5126 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5128 printf("TEST #4 testing 2 non-io opens (both with delete)\n");
5130 status = cli_ntcreate(cli1, fname, 0,
5131 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5132 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5133 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5134 if (!NT_STATUS_IS_OK(status)) {
5135 printf("TEST #4 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, FILE_SHARE_NONE,
5142 FILE_OPEN_IF, 0, 0, &fnum2);
5143 if (NT_STATUS_IS_OK(status)) {
5144 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5145 return False;
5148 printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5150 status = cli_close(cli1, fnum1);
5151 if (!NT_STATUS_IS_OK(status)) {
5152 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5153 return False;
5156 printf("non-io open test #4 passed.\n");
5158 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5160 printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
5162 status = cli_ntcreate(cli1, fname, 0,
5163 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5164 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5165 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5166 if (!NT_STATUS_IS_OK(status)) {
5167 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5168 return False;
5171 status = cli_ntcreate(cli2, fname, 0,
5172 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5173 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5174 FILE_OPEN_IF, 0, 0, &fnum2);
5175 if (!NT_STATUS_IS_OK(status)) {
5176 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5177 return False;
5180 status = cli_close(cli1, fnum1);
5181 if (!NT_STATUS_IS_OK(status)) {
5182 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5183 return False;
5186 status = cli_close(cli2, fnum2);
5187 if (!NT_STATUS_IS_OK(status)) {
5188 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5189 return False;
5192 printf("non-io open test #5 passed.\n");
5194 printf("TEST #6 testing 1 non-io open, one io open\n");
5196 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5198 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5199 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5200 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5201 if (!NT_STATUS_IS_OK(status)) {
5202 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5203 return False;
5206 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5207 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
5208 FILE_OPEN_IF, 0, 0, &fnum2);
5209 if (!NT_STATUS_IS_OK(status)) {
5210 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5211 return False;
5214 status = cli_close(cli1, fnum1);
5215 if (!NT_STATUS_IS_OK(status)) {
5216 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5217 return False;
5220 status = cli_close(cli2, fnum2);
5221 if (!NT_STATUS_IS_OK(status)) {
5222 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5223 return False;
5226 printf("non-io open test #6 passed.\n");
5228 printf("TEST #7 testing 1 non-io open, one io open with delete\n");
5230 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5232 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5233 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5234 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5235 if (!NT_STATUS_IS_OK(status)) {
5236 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5237 return False;
5240 status = cli_ntcreate(cli2, fname, 0,
5241 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5242 FILE_ATTRIBUTE_NORMAL,
5243 FILE_SHARE_READ|FILE_SHARE_DELETE,
5244 FILE_OPEN_IF, 0, 0, &fnum2);
5245 if (NT_STATUS_IS_OK(status)) {
5246 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5247 return False;
5250 printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5252 status = cli_close(cli1, fnum1);
5253 if (!NT_STATUS_IS_OK(status)) {
5254 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5255 return False;
5258 printf("non-io open test #7 passed.\n");
5260 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5262 printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
5263 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
5264 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5265 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5266 if (!NT_STATUS_IS_OK(status)) {
5267 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
5268 correct = false;
5269 goto out;
5272 /* Write to ensure we have to update the file time. */
5273 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5274 NULL);
5275 if (!NT_STATUS_IS_OK(status)) {
5276 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
5277 correct = false;
5278 goto out;
5281 status = cli_close(cli1, fnum1);
5282 if (!NT_STATUS_IS_OK(status)) {
5283 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
5284 correct = false;
5287 out:
5289 if (!torture_close_connection(cli1)) {
5290 correct = False;
5292 if (!torture_close_connection(cli2)) {
5293 correct = False;
5296 return correct;
5299 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
5301 uint16 major, minor;
5302 uint32 caplow, caphigh;
5303 NTSTATUS status;
5305 if (!SERVER_HAS_UNIX_CIFS(cli)) {
5306 printf("Server doesn't support UNIX CIFS extensions.\n");
5307 return NT_STATUS_NOT_SUPPORTED;
5310 status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
5311 &caphigh);
5312 if (!NT_STATUS_IS_OK(status)) {
5313 printf("Server didn't return UNIX CIFS extensions: %s\n",
5314 nt_errstr(status));
5315 return status;
5318 status = cli_set_unix_extensions_capabilities(cli, major, minor,
5319 caplow, caphigh);
5320 if (!NT_STATUS_IS_OK(status)) {
5321 printf("Server doesn't support setting UNIX CIFS extensions: "
5322 "%s.\n", nt_errstr(status));
5323 return status;
5326 return NT_STATUS_OK;
5330 Test POSIX open /mkdir calls.
5332 static bool run_simple_posix_open_test(int dummy)
5334 static struct cli_state *cli1;
5335 const char *fname = "posix:file";
5336 const char *hname = "posix:hlink";
5337 const char *sname = "posix:symlink";
5338 const char *dname = "posix:dir";
5339 char buf[10];
5340 char namebuf[11];
5341 uint16_t fnum1 = (uint16_t)-1;
5342 SMB_STRUCT_STAT sbuf;
5343 bool correct = false;
5344 NTSTATUS status;
5345 size_t nread;
5347 printf("Starting simple POSIX open test\n");
5349 if (!torture_open_connection(&cli1, 0)) {
5350 return false;
5353 cli_sockopt(cli1, sockops);
5355 status = torture_setup_unix_extensions(cli1);
5356 if (!NT_STATUS_IS_OK(status)) {
5357 return false;
5360 cli_setatr(cli1, fname, 0, 0);
5361 cli_posix_unlink(cli1, fname);
5362 cli_setatr(cli1, dname, 0, 0);
5363 cli_posix_rmdir(cli1, dname);
5364 cli_setatr(cli1, hname, 0, 0);
5365 cli_posix_unlink(cli1, hname);
5366 cli_setatr(cli1, sname, 0, 0);
5367 cli_posix_unlink(cli1, sname);
5369 /* Create a directory. */
5370 status = cli_posix_mkdir(cli1, dname, 0777);
5371 if (!NT_STATUS_IS_OK(status)) {
5372 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
5373 goto out;
5376 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5377 0600, &fnum1);
5378 if (!NT_STATUS_IS_OK(status)) {
5379 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5380 goto out;
5383 /* Test ftruncate - set file size. */
5384 status = cli_ftruncate(cli1, fnum1, 1000);
5385 if (!NT_STATUS_IS_OK(status)) {
5386 printf("ftruncate failed (%s)\n", nt_errstr(status));
5387 goto out;
5390 /* Ensure st_size == 1000 */
5391 status = cli_posix_stat(cli1, fname, &sbuf);
5392 if (!NT_STATUS_IS_OK(status)) {
5393 printf("stat failed (%s)\n", nt_errstr(status));
5394 goto out;
5397 if (sbuf.st_ex_size != 1000) {
5398 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5399 goto out;
5402 /* Test ftruncate - set file size back to zero. */
5403 status = cli_ftruncate(cli1, fnum1, 0);
5404 if (!NT_STATUS_IS_OK(status)) {
5405 printf("ftruncate failed (%s)\n", nt_errstr(status));
5406 goto out;
5409 status = cli_close(cli1, fnum1);
5410 if (!NT_STATUS_IS_OK(status)) {
5411 printf("close failed (%s)\n", nt_errstr(status));
5412 goto out;
5415 /* Now open the file again for read only. */
5416 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5417 if (!NT_STATUS_IS_OK(status)) {
5418 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
5419 goto out;
5422 /* Now unlink while open. */
5423 status = cli_posix_unlink(cli1, fname);
5424 if (!NT_STATUS_IS_OK(status)) {
5425 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5426 goto out;
5429 status = cli_close(cli1, fnum1);
5430 if (!NT_STATUS_IS_OK(status)) {
5431 printf("close(2) failed (%s)\n", nt_errstr(status));
5432 goto out;
5435 /* Ensure the file has gone. */
5436 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5437 if (NT_STATUS_IS_OK(status)) {
5438 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
5439 goto out;
5442 /* Create again to test open with O_TRUNC. */
5443 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
5444 if (!NT_STATUS_IS_OK(status)) {
5445 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5446 goto out;
5449 /* Test ftruncate - set file size. */
5450 status = cli_ftruncate(cli1, fnum1, 1000);
5451 if (!NT_STATUS_IS_OK(status)) {
5452 printf("ftruncate failed (%s)\n", nt_errstr(status));
5453 goto out;
5456 /* Ensure st_size == 1000 */
5457 status = cli_posix_stat(cli1, fname, &sbuf);
5458 if (!NT_STATUS_IS_OK(status)) {
5459 printf("stat failed (%s)\n", nt_errstr(status));
5460 goto out;
5463 if (sbuf.st_ex_size != 1000) {
5464 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5465 goto out;
5468 status = cli_close(cli1, fnum1);
5469 if (!NT_STATUS_IS_OK(status)) {
5470 printf("close(2) failed (%s)\n", nt_errstr(status));
5471 goto out;
5474 /* Re-open with O_TRUNC. */
5475 status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
5476 if (!NT_STATUS_IS_OK(status)) {
5477 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5478 goto out;
5481 /* Ensure st_size == 0 */
5482 status = cli_posix_stat(cli1, fname, &sbuf);
5483 if (!NT_STATUS_IS_OK(status)) {
5484 printf("stat failed (%s)\n", nt_errstr(status));
5485 goto out;
5488 if (sbuf.st_ex_size != 0) {
5489 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
5490 goto out;
5493 status = cli_close(cli1, fnum1);
5494 if (!NT_STATUS_IS_OK(status)) {
5495 printf("close failed (%s)\n", nt_errstr(status));
5496 goto out;
5499 status = cli_posix_unlink(cli1, fname);
5500 if (!NT_STATUS_IS_OK(status)) {
5501 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5502 goto out;
5505 status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
5506 if (!NT_STATUS_IS_OK(status)) {
5507 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
5508 dname, nt_errstr(status));
5509 goto out;
5512 cli_close(cli1, fnum1);
5514 /* What happens when we try and POSIX open a directory for write ? */
5515 status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
5516 if (NT_STATUS_IS_OK(status)) {
5517 printf("POSIX open of directory %s succeeded, should have failed.\n", fname);
5518 goto out;
5519 } else {
5520 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
5521 NT_STATUS_FILE_IS_A_DIRECTORY)) {
5522 goto out;
5526 /* Create the file. */
5527 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5528 0600, &fnum1);
5529 if (!NT_STATUS_IS_OK(status)) {
5530 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5531 goto out;
5534 /* Write some data into it. */
5535 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5536 NULL);
5537 if (!NT_STATUS_IS_OK(status)) {
5538 printf("cli_write failed: %s\n", nt_errstr(status));
5539 goto out;
5542 cli_close(cli1, fnum1);
5544 /* Now create a hardlink. */
5545 status = cli_posix_hardlink(cli1, fname, hname);
5546 if (!NT_STATUS_IS_OK(status)) {
5547 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
5548 goto out;
5551 /* Now create a symlink. */
5552 status = cli_posix_symlink(cli1, fname, sname);
5553 if (!NT_STATUS_IS_OK(status)) {
5554 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
5555 goto out;
5558 /* Open the hardlink for read. */
5559 status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
5560 if (!NT_STATUS_IS_OK(status)) {
5561 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
5562 goto out;
5565 status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
5566 if (!NT_STATUS_IS_OK(status)) {
5567 printf("POSIX read of %s failed (%s)\n", hname,
5568 nt_errstr(status));
5569 goto out;
5570 } else if (nread != 10) {
5571 printf("POSIX read of %s failed. Received %ld, expected %d\n",
5572 hname, (unsigned long)nread, 10);
5573 goto out;
5576 if (memcmp(buf, "TEST DATA\n", 10)) {
5577 printf("invalid data read from hardlink\n");
5578 goto out;
5581 /* Do a POSIX lock/unlock. */
5582 status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
5583 if (!NT_STATUS_IS_OK(status)) {
5584 printf("POSIX lock failed %s\n", nt_errstr(status));
5585 goto out;
5588 /* Punch a hole in the locked area. */
5589 status = cli_posix_unlock(cli1, fnum1, 10, 80);
5590 if (!NT_STATUS_IS_OK(status)) {
5591 printf("POSIX unlock failed %s\n", nt_errstr(status));
5592 goto out;
5595 cli_close(cli1, fnum1);
5597 /* Open the symlink for read - this should fail. A POSIX
5598 client should not be doing opens on a symlink. */
5599 status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
5600 if (NT_STATUS_IS_OK(status)) {
5601 printf("POSIX open of %s succeeded (should have failed)\n", sname);
5602 goto out;
5603 } else {
5604 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
5605 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
5606 printf("POSIX open of %s should have failed "
5607 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
5608 "failed with %s instead.\n",
5609 sname, nt_errstr(status));
5610 goto out;
5614 status = cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf));
5615 if (!NT_STATUS_IS_OK(status)) {
5616 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
5617 goto out;
5620 if (strcmp(namebuf, fname) != 0) {
5621 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
5622 sname, fname, namebuf);
5623 goto out;
5626 status = cli_posix_rmdir(cli1, dname);
5627 if (!NT_STATUS_IS_OK(status)) {
5628 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
5629 goto out;
5632 printf("Simple POSIX open test passed\n");
5633 correct = true;
5635 out:
5637 if (fnum1 != (uint16_t)-1) {
5638 cli_close(cli1, fnum1);
5639 fnum1 = (uint16_t)-1;
5642 cli_setatr(cli1, sname, 0, 0);
5643 cli_posix_unlink(cli1, sname);
5644 cli_setatr(cli1, hname, 0, 0);
5645 cli_posix_unlink(cli1, hname);
5646 cli_setatr(cli1, fname, 0, 0);
5647 cli_posix_unlink(cli1, fname);
5648 cli_setatr(cli1, dname, 0, 0);
5649 cli_posix_rmdir(cli1, dname);
5651 if (!torture_close_connection(cli1)) {
5652 correct = false;
5655 return correct;
5659 static uint32 open_attrs_table[] = {
5660 FILE_ATTRIBUTE_NORMAL,
5661 FILE_ATTRIBUTE_ARCHIVE,
5662 FILE_ATTRIBUTE_READONLY,
5663 FILE_ATTRIBUTE_HIDDEN,
5664 FILE_ATTRIBUTE_SYSTEM,
5666 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
5667 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
5668 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
5669 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5670 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5671 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5673 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5674 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5675 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5676 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
5679 struct trunc_open_results {
5680 unsigned int num;
5681 uint32 init_attr;
5682 uint32 trunc_attr;
5683 uint32 result_attr;
5686 static struct trunc_open_results attr_results[] = {
5687 { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5688 { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5689 { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5690 { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5691 { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5692 { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5693 { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5694 { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5695 { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5696 { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5697 { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5698 { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
5699 { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5700 { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5701 { 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 },
5702 { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5703 { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5704 { 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 },
5705 { 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 },
5706 { 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 },
5707 { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5708 { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5709 { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5710 { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5711 { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5712 { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
5715 static bool run_openattrtest(int dummy)
5717 static struct cli_state *cli1;
5718 const char *fname = "\\openattr.file";
5719 uint16_t fnum1;
5720 bool correct = True;
5721 uint16 attr;
5722 unsigned int i, j, k, l;
5723 NTSTATUS status;
5725 printf("starting open attr test\n");
5727 if (!torture_open_connection(&cli1, 0)) {
5728 return False;
5731 cli_sockopt(cli1, sockops);
5733 for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32); i++) {
5734 cli_setatr(cli1, fname, 0, 0);
5735 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5737 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
5738 open_attrs_table[i], FILE_SHARE_NONE,
5739 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5740 if (!NT_STATUS_IS_OK(status)) {
5741 printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5742 return False;
5745 status = cli_close(cli1, fnum1);
5746 if (!NT_STATUS_IS_OK(status)) {
5747 printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5748 return False;
5751 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32); j++) {
5752 status = cli_ntcreate(cli1, fname, 0,
5753 FILE_READ_DATA|FILE_WRITE_DATA,
5754 open_attrs_table[j],
5755 FILE_SHARE_NONE, FILE_OVERWRITE,
5756 0, 0, &fnum1);
5757 if (!NT_STATUS_IS_OK(status)) {
5758 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5759 if (attr_results[l].num == k) {
5760 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
5761 k, open_attrs_table[i],
5762 open_attrs_table[j],
5763 fname, NT_STATUS_V(status), nt_errstr(status));
5764 correct = False;
5768 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5769 printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
5770 k, open_attrs_table[i], open_attrs_table[j],
5771 nt_errstr(status));
5772 correct = False;
5774 #if 0
5775 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
5776 #endif
5777 k++;
5778 continue;
5781 status = cli_close(cli1, fnum1);
5782 if (!NT_STATUS_IS_OK(status)) {
5783 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
5784 return False;
5787 status = cli_getatr(cli1, fname, &attr, NULL, NULL);
5788 if (!NT_STATUS_IS_OK(status)) {
5789 printf("getatr(2) failed (%s)\n", nt_errstr(status));
5790 return False;
5793 #if 0
5794 printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
5795 k, open_attrs_table[i], open_attrs_table[j], attr );
5796 #endif
5798 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5799 if (attr_results[l].num == k) {
5800 if (attr != attr_results[l].result_attr ||
5801 open_attrs_table[i] != attr_results[l].init_attr ||
5802 open_attrs_table[j] != attr_results[l].trunc_attr) {
5803 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
5804 open_attrs_table[i],
5805 open_attrs_table[j],
5806 (unsigned int)attr,
5807 attr_results[l].result_attr);
5808 correct = False;
5810 break;
5813 k++;
5817 cli_setatr(cli1, fname, 0, 0);
5818 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5820 printf("open attr test %s.\n", correct ? "passed" : "failed");
5822 if (!torture_close_connection(cli1)) {
5823 correct = False;
5825 return correct;
5828 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
5829 const char *name, void *state)
5831 int *matched = (int *)state;
5832 if (matched != NULL) {
5833 *matched += 1;
5835 return NT_STATUS_OK;
5839 test directory listing speed
5841 static bool run_dirtest(int dummy)
5843 int i;
5844 static struct cli_state *cli;
5845 uint16_t fnum;
5846 struct timeval core_start;
5847 bool correct = True;
5848 int matched;
5850 printf("starting directory test\n");
5852 if (!torture_open_connection(&cli, 0)) {
5853 return False;
5856 cli_sockopt(cli, sockops);
5858 srandom(0);
5859 for (i=0;i<torture_numops;i++) {
5860 fstring fname;
5861 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5862 if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
5863 fprintf(stderr,"Failed to open %s\n", fname);
5864 return False;
5866 cli_close(cli, fnum);
5869 core_start = timeval_current();
5871 matched = 0;
5872 cli_list(cli, "a*.*", 0, list_fn, &matched);
5873 printf("Matched %d\n", matched);
5875 matched = 0;
5876 cli_list(cli, "b*.*", 0, list_fn, &matched);
5877 printf("Matched %d\n", matched);
5879 matched = 0;
5880 cli_list(cli, "xyzabc", 0, list_fn, &matched);
5881 printf("Matched %d\n", matched);
5883 printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
5885 srandom(0);
5886 for (i=0;i<torture_numops;i++) {
5887 fstring fname;
5888 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5889 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5892 if (!torture_close_connection(cli)) {
5893 correct = False;
5896 printf("finished dirtest\n");
5898 return correct;
5901 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
5902 void *state)
5904 struct cli_state *pcli = (struct cli_state *)state;
5905 fstring fname;
5906 slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
5908 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
5909 return NT_STATUS_OK;
5911 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
5912 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
5913 printf("del_fn: failed to rmdir %s\n,", fname );
5914 } else {
5915 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
5916 printf("del_fn: failed to unlink %s\n,", fname );
5918 return NT_STATUS_OK;
5923 sees what IOCTLs are supported
5925 bool torture_ioctl_test(int dummy)
5927 static struct cli_state *cli;
5928 uint16_t device, function;
5929 uint16_t fnum;
5930 const char *fname = "\\ioctl.dat";
5931 DATA_BLOB blob;
5932 NTSTATUS status;
5934 if (!torture_open_connection(&cli, 0)) {
5935 return False;
5938 printf("starting ioctl test\n");
5940 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5942 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5943 if (!NT_STATUS_IS_OK(status)) {
5944 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5945 return False;
5948 status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
5949 printf("ioctl device info: %s\n", nt_errstr(status));
5951 status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
5952 printf("ioctl job info: %s\n", nt_errstr(status));
5954 for (device=0;device<0x100;device++) {
5955 printf("ioctl test with device = 0x%x\n", device);
5956 for (function=0;function<0x100;function++) {
5957 uint32 code = (device<<16) | function;
5959 status = cli_raw_ioctl(cli, fnum, code, &blob);
5961 if (NT_STATUS_IS_OK(status)) {
5962 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
5963 (int)blob.length);
5964 data_blob_free(&blob);
5969 if (!torture_close_connection(cli)) {
5970 return False;
5973 return True;
5978 tries varients of chkpath
5980 bool torture_chkpath_test(int dummy)
5982 static struct cli_state *cli;
5983 uint16_t fnum;
5984 bool ret;
5985 NTSTATUS status;
5987 if (!torture_open_connection(&cli, 0)) {
5988 return False;
5991 printf("starting chkpath test\n");
5993 /* cleanup from an old run */
5994 cli_rmdir(cli, "\\chkpath.dir\\dir2");
5995 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5996 cli_rmdir(cli, "\\chkpath.dir");
5998 status = cli_mkdir(cli, "\\chkpath.dir");
5999 if (!NT_STATUS_IS_OK(status)) {
6000 printf("mkdir1 failed : %s\n", nt_errstr(status));
6001 return False;
6004 status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
6005 if (!NT_STATUS_IS_OK(status)) {
6006 printf("mkdir2 failed : %s\n", nt_errstr(status));
6007 return False;
6010 status = cli_open(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
6011 DENY_NONE, &fnum);
6012 if (!NT_STATUS_IS_OK(status)) {
6013 printf("open1 failed (%s)\n", nt_errstr(status));
6014 return False;
6016 cli_close(cli, fnum);
6018 status = cli_chkpath(cli, "\\chkpath.dir");
6019 if (!NT_STATUS_IS_OK(status)) {
6020 printf("chkpath1 failed: %s\n", nt_errstr(status));
6021 ret = False;
6024 status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
6025 if (!NT_STATUS_IS_OK(status)) {
6026 printf("chkpath2 failed: %s\n", nt_errstr(status));
6027 ret = False;
6030 status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
6031 if (!NT_STATUS_IS_OK(status)) {
6032 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
6033 NT_STATUS_NOT_A_DIRECTORY);
6034 } else {
6035 printf("* chkpath on a file should fail\n");
6036 ret = False;
6039 status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
6040 if (!NT_STATUS_IS_OK(status)) {
6041 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
6042 NT_STATUS_OBJECT_NAME_NOT_FOUND);
6043 } else {
6044 printf("* chkpath on a non existant file should fail\n");
6045 ret = False;
6048 status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
6049 if (!NT_STATUS_IS_OK(status)) {
6050 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
6051 NT_STATUS_OBJECT_PATH_NOT_FOUND);
6052 } else {
6053 printf("* chkpath on a non existent component should fail\n");
6054 ret = False;
6057 cli_rmdir(cli, "\\chkpath.dir\\dir2");
6058 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6059 cli_rmdir(cli, "\\chkpath.dir");
6061 if (!torture_close_connection(cli)) {
6062 return False;
6065 return ret;
6068 static bool run_eatest(int dummy)
6070 static struct cli_state *cli;
6071 const char *fname = "\\eatest.txt";
6072 bool correct = True;
6073 uint16_t fnum;
6074 int i;
6075 size_t num_eas;
6076 struct ea_struct *ea_list = NULL;
6077 TALLOC_CTX *mem_ctx = talloc_init("eatest");
6078 NTSTATUS status;
6080 printf("starting eatest\n");
6082 if (!torture_open_connection(&cli, 0)) {
6083 talloc_destroy(mem_ctx);
6084 return False;
6087 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6089 status = cli_ntcreate(cli, fname, 0,
6090 FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6091 FILE_SHARE_NONE, FILE_OVERWRITE_IF,
6092 0x4044, 0, &fnum);
6093 if (!NT_STATUS_IS_OK(status)) {
6094 printf("open failed - %s\n", nt_errstr(status));
6095 talloc_destroy(mem_ctx);
6096 return False;
6099 for (i = 0; i < 10; i++) {
6100 fstring ea_name, ea_val;
6102 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
6103 memset(ea_val, (char)i+1, i+1);
6104 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
6105 if (!NT_STATUS_IS_OK(status)) {
6106 printf("ea_set of name %s failed - %s\n", ea_name,
6107 nt_errstr(status));
6108 talloc_destroy(mem_ctx);
6109 return False;
6113 cli_close(cli, fnum);
6114 for (i = 0; i < 10; i++) {
6115 fstring ea_name, ea_val;
6117 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
6118 memset(ea_val, (char)i+1, i+1);
6119 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
6120 if (!NT_STATUS_IS_OK(status)) {
6121 printf("ea_set of name %s failed - %s\n", ea_name,
6122 nt_errstr(status));
6123 talloc_destroy(mem_ctx);
6124 return False;
6128 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6129 if (!NT_STATUS_IS_OK(status)) {
6130 printf("ea_get list failed - %s\n", nt_errstr(status));
6131 correct = False;
6134 printf("num_eas = %d\n", (int)num_eas);
6136 if (num_eas != 20) {
6137 printf("Should be 20 EA's stored... failing.\n");
6138 correct = False;
6141 for (i = 0; i < num_eas; i++) {
6142 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6143 dump_data(0, ea_list[i].value.data,
6144 ea_list[i].value.length);
6147 /* Setting EA's to zero length deletes them. Test this */
6148 printf("Now deleting all EA's - case indepenent....\n");
6150 #if 1
6151 cli_set_ea_path(cli, fname, "", "", 0);
6152 #else
6153 for (i = 0; i < 20; i++) {
6154 fstring ea_name;
6155 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
6156 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
6157 if (!NT_STATUS_IS_OK(status)) {
6158 printf("ea_set of name %s failed - %s\n", ea_name,
6159 nt_errstr(status));
6160 talloc_destroy(mem_ctx);
6161 return False;
6164 #endif
6166 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6167 if (!NT_STATUS_IS_OK(status)) {
6168 printf("ea_get list failed - %s\n", nt_errstr(status));
6169 correct = False;
6172 printf("num_eas = %d\n", (int)num_eas);
6173 for (i = 0; i < num_eas; i++) {
6174 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6175 dump_data(0, ea_list[i].value.data,
6176 ea_list[i].value.length);
6179 if (num_eas != 0) {
6180 printf("deleting EA's failed.\n");
6181 correct = False;
6184 /* Try and delete a non existant EA. */
6185 status = cli_set_ea_path(cli, fname, "foo", "", 0);
6186 if (!NT_STATUS_IS_OK(status)) {
6187 printf("deleting non-existant EA 'foo' should succeed. %s\n",
6188 nt_errstr(status));
6189 correct = False;
6192 talloc_destroy(mem_ctx);
6193 if (!torture_close_connection(cli)) {
6194 correct = False;
6197 return correct;
6200 static bool run_dirtest1(int dummy)
6202 int i;
6203 static struct cli_state *cli;
6204 uint16_t fnum;
6205 int num_seen;
6206 bool correct = True;
6208 printf("starting directory test\n");
6210 if (!torture_open_connection(&cli, 0)) {
6211 return False;
6214 cli_sockopt(cli, sockops);
6216 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6217 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6218 cli_rmdir(cli, "\\LISTDIR");
6219 cli_mkdir(cli, "\\LISTDIR");
6221 /* Create 1000 files and 1000 directories. */
6222 for (i=0;i<1000;i++) {
6223 fstring fname;
6224 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
6225 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6226 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum))) {
6227 fprintf(stderr,"Failed to open %s\n", fname);
6228 return False;
6230 cli_close(cli, fnum);
6232 for (i=0;i<1000;i++) {
6233 fstring fname;
6234 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
6235 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
6236 fprintf(stderr,"Failed to open %s\n", fname);
6237 return False;
6241 /* Now ensure that doing an old list sees both files and directories. */
6242 num_seen = 0;
6243 cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6244 printf("num_seen = %d\n", num_seen );
6245 /* We should see 100 files + 1000 directories + . and .. */
6246 if (num_seen != 2002)
6247 correct = False;
6249 /* Ensure if we have the "must have" bits we only see the
6250 * relevent entries.
6252 num_seen = 0;
6253 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6254 printf("num_seen = %d\n", num_seen );
6255 if (num_seen != 1002)
6256 correct = False;
6258 num_seen = 0;
6259 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6260 printf("num_seen = %d\n", num_seen );
6261 if (num_seen != 1000)
6262 correct = False;
6264 /* Delete everything. */
6265 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6266 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6267 cli_rmdir(cli, "\\LISTDIR");
6269 #if 0
6270 printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
6271 printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
6272 printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
6273 #endif
6275 if (!torture_close_connection(cli)) {
6276 correct = False;
6279 printf("finished dirtest1\n");
6281 return correct;
6284 static bool run_error_map_extract(int dummy) {
6286 static struct cli_state *c_dos;
6287 static struct cli_state *c_nt;
6288 NTSTATUS status;
6290 uint32 error;
6292 uint32 errnum;
6293 uint8 errclass;
6295 NTSTATUS nt_status;
6297 fstring user;
6299 /* NT-Error connection */
6301 disable_spnego = true;
6302 if (!(c_nt = open_nbt_connection())) {
6303 disable_spnego = false;
6304 return False;
6306 disable_spnego = false;
6308 status = cli_negprot(c_nt, PROTOCOL_NT1);
6310 if (!NT_STATUS_IS_OK(status)) {
6311 printf("%s rejected the NT-error negprot (%s)\n", host,
6312 nt_errstr(status));
6313 cli_shutdown(c_nt);
6314 return False;
6317 status = cli_session_setup(c_nt, "", "", 0, "", 0, workgroup);
6318 if (!NT_STATUS_IS_OK(status)) {
6319 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
6320 return False;
6323 /* DOS-Error connection */
6325 disable_spnego = true;
6326 force_dos_errors = true;
6327 if (!(c_dos = open_nbt_connection())) {
6328 disable_spnego = false;
6329 force_dos_errors = false;
6330 return False;
6332 disable_spnego = false;
6333 force_dos_errors = false;
6335 status = cli_negprot(c_dos, PROTOCOL_NT1);
6336 if (!NT_STATUS_IS_OK(status)) {
6337 printf("%s rejected the DOS-error negprot (%s)\n", host,
6338 nt_errstr(status));
6339 cli_shutdown(c_dos);
6340 return False;
6343 status = cli_session_setup(c_dos, "", "", 0, "", 0, workgroup);
6344 if (!NT_STATUS_IS_OK(status)) {
6345 printf("%s rejected the DOS-error initial session setup (%s)\n",
6346 host, nt_errstr(status));
6347 return False;
6350 for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
6351 fstr_sprintf(user, "%X", error);
6353 status = cli_session_setup(c_nt, user,
6354 password, strlen(password),
6355 password, strlen(password),
6356 workgroup);
6357 if (NT_STATUS_IS_OK(status)) {
6358 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
6361 /* Case #1: 32-bit NT errors */
6362 if (cli_is_nt_error(c_nt)) {
6363 nt_status = cli_nt_error(c_nt);
6364 } else {
6365 printf("/** Dos error on NT connection! (%s) */\n",
6366 cli_errstr(c_nt));
6367 nt_status = NT_STATUS(0xc0000000);
6370 status = cli_session_setup(c_dos, user,
6371 password, strlen(password),
6372 password, strlen(password),
6373 workgroup);
6374 if (NT_STATUS_IS_OK(status)) {
6375 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
6378 /* Case #1: 32-bit NT errors */
6379 if (!cli_is_dos_error(c_dos)) {
6380 printf("/** NT error on DOS connection! (%s) */\n",
6381 cli_errstr(c_dos));
6382 errnum = errclass = 0;
6383 } else {
6384 cli_dos_error(c_dos, &errclass, &errnum);
6387 if (NT_STATUS_V(nt_status) != error) {
6388 printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
6389 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
6390 get_nt_error_c_code(talloc_tos(), nt_status));
6393 printf("\t{%s,\t%s,\t%s},\n",
6394 smb_dos_err_class(errclass),
6395 smb_dos_err_name(errclass, errnum),
6396 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
6398 return True;
6401 static bool run_sesssetup_bench(int dummy)
6403 static struct cli_state *c;
6404 const char *fname = "\\file.dat";
6405 uint16_t fnum;
6406 NTSTATUS status;
6407 int i;
6409 if (!torture_open_connection(&c, 0)) {
6410 return false;
6413 status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6414 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6415 FILE_DELETE_ON_CLOSE, 0, &fnum);
6416 if (!NT_STATUS_IS_OK(status)) {
6417 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
6418 return false;
6421 for (i=0; i<torture_numops; i++) {
6422 status = cli_session_setup(
6423 c, username,
6424 password, strlen(password),
6425 password, strlen(password),
6426 workgroup);
6427 if (!NT_STATUS_IS_OK(status)) {
6428 d_printf("(%s) cli_session_setup failed: %s\n",
6429 __location__, nt_errstr(status));
6430 return false;
6433 d_printf("\r%d ", (int)cli_state_get_uid(c));
6435 status = cli_ulogoff(c);
6436 if (!NT_STATUS_IS_OK(status)) {
6437 d_printf("(%s) cli_ulogoff failed: %s\n",
6438 __location__, nt_errstr(status));
6439 return false;
6443 return true;
6446 static bool subst_test(const char *str, const char *user, const char *domain,
6447 uid_t uid, gid_t gid, const char *expected)
6449 char *subst;
6450 bool result = true;
6452 subst = talloc_sub_specified(talloc_tos(), str, user, domain, uid, gid);
6454 if (strcmp(subst, expected) != 0) {
6455 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
6456 "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
6457 expected);
6458 result = false;
6461 TALLOC_FREE(subst);
6462 return result;
6465 static void chain1_open_completion(struct tevent_req *req)
6467 uint16_t fnum;
6468 NTSTATUS status;
6469 status = cli_open_recv(req, &fnum);
6470 TALLOC_FREE(req);
6472 d_printf("cli_open_recv returned %s: %d\n",
6473 nt_errstr(status),
6474 NT_STATUS_IS_OK(status) ? fnum : -1);
6477 static void chain1_write_completion(struct tevent_req *req)
6479 size_t written;
6480 NTSTATUS status;
6481 status = cli_write_andx_recv(req, &written);
6482 TALLOC_FREE(req);
6484 d_printf("cli_write_andx_recv returned %s: %d\n",
6485 nt_errstr(status),
6486 NT_STATUS_IS_OK(status) ? (int)written : -1);
6489 static void chain1_close_completion(struct tevent_req *req)
6491 NTSTATUS status;
6492 bool *done = (bool *)tevent_req_callback_data_void(req);
6494 status = cli_close_recv(req);
6495 *done = true;
6497 TALLOC_FREE(req);
6499 d_printf("cli_close returned %s\n", nt_errstr(status));
6502 static bool run_chain1(int dummy)
6504 struct cli_state *cli1;
6505 struct event_context *evt = event_context_init(NULL);
6506 struct tevent_req *reqs[3], *smbreqs[3];
6507 bool done = false;
6508 const char *str = "foobar";
6509 NTSTATUS status;
6511 printf("starting chain1 test\n");
6512 if (!torture_open_connection(&cli1, 0)) {
6513 return False;
6516 cli_sockopt(cli1, sockops);
6518 reqs[0] = cli_open_create(talloc_tos(), evt, cli1, "\\test",
6519 O_CREAT|O_RDWR, 0, &smbreqs[0]);
6520 if (reqs[0] == NULL) return false;
6521 tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
6524 reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
6525 (const uint8_t *)str, 0, strlen(str)+1,
6526 smbreqs, 1, &smbreqs[1]);
6527 if (reqs[1] == NULL) return false;
6528 tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
6530 reqs[2] = cli_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
6531 if (reqs[2] == NULL) return false;
6532 tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
6534 status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
6535 if (!NT_STATUS_IS_OK(status)) {
6536 return false;
6539 while (!done) {
6540 tevent_loop_once(evt);
6543 torture_close_connection(cli1);
6544 return True;
6547 static void chain2_sesssetup_completion(struct tevent_req *req)
6549 NTSTATUS status;
6550 status = cli_session_setup_guest_recv(req);
6551 d_printf("sesssetup returned %s\n", nt_errstr(status));
6554 static void chain2_tcon_completion(struct tevent_req *req)
6556 bool *done = (bool *)tevent_req_callback_data_void(req);
6557 NTSTATUS status;
6558 status = cli_tcon_andx_recv(req);
6559 d_printf("tcon_and_x returned %s\n", nt_errstr(status));
6560 *done = true;
6563 static bool run_chain2(int dummy)
6565 struct cli_state *cli1;
6566 struct event_context *evt = event_context_init(NULL);
6567 struct tevent_req *reqs[2], *smbreqs[2];
6568 bool done = false;
6569 NTSTATUS status;
6571 printf("starting chain2 test\n");
6572 status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
6573 port_to_use, SMB_SIGNING_DEFAULT, 0);
6574 if (!NT_STATUS_IS_OK(status)) {
6575 return False;
6578 cli_sockopt(cli1, sockops);
6580 reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
6581 &smbreqs[0]);
6582 if (reqs[0] == NULL) return false;
6583 tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
6585 reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
6586 "?????", NULL, 0, &smbreqs[1]);
6587 if (reqs[1] == NULL) return false;
6588 tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
6590 status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
6591 if (!NT_STATUS_IS_OK(status)) {
6592 return false;
6595 while (!done) {
6596 tevent_loop_once(evt);
6599 torture_close_connection(cli1);
6600 return True;
6604 struct torture_createdel_state {
6605 struct tevent_context *ev;
6606 struct cli_state *cli;
6609 static void torture_createdel_created(struct tevent_req *subreq);
6610 static void torture_createdel_closed(struct tevent_req *subreq);
6612 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
6613 struct tevent_context *ev,
6614 struct cli_state *cli,
6615 const char *name)
6617 struct tevent_req *req, *subreq;
6618 struct torture_createdel_state *state;
6620 req = tevent_req_create(mem_ctx, &state,
6621 struct torture_createdel_state);
6622 if (req == NULL) {
6623 return NULL;
6625 state->ev = ev;
6626 state->cli = cli;
6628 subreq = cli_ntcreate_send(
6629 state, ev, cli, name, 0,
6630 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
6631 FILE_ATTRIBUTE_NORMAL,
6632 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6633 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
6635 if (tevent_req_nomem(subreq, req)) {
6636 return tevent_req_post(req, ev);
6638 tevent_req_set_callback(subreq, torture_createdel_created, req);
6639 return req;
6642 static void torture_createdel_created(struct tevent_req *subreq)
6644 struct tevent_req *req = tevent_req_callback_data(
6645 subreq, struct tevent_req);
6646 struct torture_createdel_state *state = tevent_req_data(
6647 req, struct torture_createdel_state);
6648 NTSTATUS status;
6649 uint16_t fnum;
6651 status = cli_ntcreate_recv(subreq, &fnum);
6652 TALLOC_FREE(subreq);
6653 if (!NT_STATUS_IS_OK(status)) {
6654 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
6655 nt_errstr(status)));
6656 tevent_req_nterror(req, status);
6657 return;
6660 subreq = cli_close_send(state, state->ev, state->cli, fnum);
6661 if (tevent_req_nomem(subreq, req)) {
6662 return;
6664 tevent_req_set_callback(subreq, torture_createdel_closed, req);
6667 static void torture_createdel_closed(struct tevent_req *subreq)
6669 struct tevent_req *req = tevent_req_callback_data(
6670 subreq, struct tevent_req);
6671 NTSTATUS status;
6673 status = cli_close_recv(subreq);
6674 if (!NT_STATUS_IS_OK(status)) {
6675 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
6676 tevent_req_nterror(req, status);
6677 return;
6679 tevent_req_done(req);
6682 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
6684 return tevent_req_simple_recv_ntstatus(req);
6687 struct torture_createdels_state {
6688 struct tevent_context *ev;
6689 struct cli_state *cli;
6690 const char *base_name;
6691 int sent;
6692 int received;
6693 int num_files;
6694 struct tevent_req **reqs;
6697 static void torture_createdels_done(struct tevent_req *subreq);
6699 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
6700 struct tevent_context *ev,
6701 struct cli_state *cli,
6702 const char *base_name,
6703 int num_parallel,
6704 int num_files)
6706 struct tevent_req *req;
6707 struct torture_createdels_state *state;
6708 int i;
6710 req = tevent_req_create(mem_ctx, &state,
6711 struct torture_createdels_state);
6712 if (req == NULL) {
6713 return NULL;
6715 state->ev = ev;
6716 state->cli = cli;
6717 state->base_name = talloc_strdup(state, base_name);
6718 if (tevent_req_nomem(state->base_name, req)) {
6719 return tevent_req_post(req, ev);
6721 state->num_files = MAX(num_parallel, num_files);
6722 state->sent = 0;
6723 state->received = 0;
6725 state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
6726 if (tevent_req_nomem(state->reqs, req)) {
6727 return tevent_req_post(req, ev);
6730 for (i=0; i<num_parallel; i++) {
6731 char *name;
6733 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6734 state->sent);
6735 if (tevent_req_nomem(name, req)) {
6736 return tevent_req_post(req, ev);
6738 state->reqs[i] = torture_createdel_send(
6739 state->reqs, state->ev, state->cli, name);
6740 if (tevent_req_nomem(state->reqs[i], req)) {
6741 return tevent_req_post(req, ev);
6743 name = talloc_move(state->reqs[i], &name);
6744 tevent_req_set_callback(state->reqs[i],
6745 torture_createdels_done, req);
6746 state->sent += 1;
6748 return req;
6751 static void torture_createdels_done(struct tevent_req *subreq)
6753 struct tevent_req *req = tevent_req_callback_data(
6754 subreq, struct tevent_req);
6755 struct torture_createdels_state *state = tevent_req_data(
6756 req, struct torture_createdels_state);
6757 size_t num_parallel = talloc_array_length(state->reqs);
6758 NTSTATUS status;
6759 char *name;
6760 int i;
6762 status = torture_createdel_recv(subreq);
6763 if (!NT_STATUS_IS_OK(status)){
6764 DEBUG(10, ("torture_createdel_recv returned %s\n",
6765 nt_errstr(status)));
6766 TALLOC_FREE(subreq);
6767 tevent_req_nterror(req, status);
6768 return;
6771 for (i=0; i<num_parallel; i++) {
6772 if (subreq == state->reqs[i]) {
6773 break;
6776 if (i == num_parallel) {
6777 DEBUG(10, ("received something we did not send\n"));
6778 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
6779 return;
6781 TALLOC_FREE(state->reqs[i]);
6783 if (state->sent >= state->num_files) {
6784 tevent_req_done(req);
6785 return;
6788 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6789 state->sent);
6790 if (tevent_req_nomem(name, req)) {
6791 return;
6793 state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
6794 state->cli, name);
6795 if (tevent_req_nomem(state->reqs[i], req)) {
6796 return;
6798 name = talloc_move(state->reqs[i], &name);
6799 tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
6800 state->sent += 1;
6803 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
6805 return tevent_req_simple_recv_ntstatus(req);
6808 struct swallow_notify_state {
6809 struct tevent_context *ev;
6810 struct cli_state *cli;
6811 uint16_t fnum;
6812 uint32_t completion_filter;
6813 bool recursive;
6814 bool (*fn)(uint32_t action, const char *name, void *priv);
6815 void *priv;
6818 static void swallow_notify_done(struct tevent_req *subreq);
6820 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
6821 struct tevent_context *ev,
6822 struct cli_state *cli,
6823 uint16_t fnum,
6824 uint32_t completion_filter,
6825 bool recursive,
6826 bool (*fn)(uint32_t action,
6827 const char *name,
6828 void *priv),
6829 void *priv)
6831 struct tevent_req *req, *subreq;
6832 struct swallow_notify_state *state;
6834 req = tevent_req_create(mem_ctx, &state,
6835 struct swallow_notify_state);
6836 if (req == NULL) {
6837 return NULL;
6839 state->ev = ev;
6840 state->cli = cli;
6841 state->fnum = fnum;
6842 state->completion_filter = completion_filter;
6843 state->recursive = recursive;
6844 state->fn = fn;
6845 state->priv = priv;
6847 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6848 0xffff, state->completion_filter,
6849 state->recursive);
6850 if (tevent_req_nomem(subreq, req)) {
6851 return tevent_req_post(req, ev);
6853 tevent_req_set_callback(subreq, swallow_notify_done, req);
6854 return req;
6857 static void swallow_notify_done(struct tevent_req *subreq)
6859 struct tevent_req *req = tevent_req_callback_data(
6860 subreq, struct tevent_req);
6861 struct swallow_notify_state *state = tevent_req_data(
6862 req, struct swallow_notify_state);
6863 NTSTATUS status;
6864 uint32_t i, num_changes;
6865 struct notify_change *changes;
6867 status = cli_notify_recv(subreq, state, &num_changes, &changes);
6868 TALLOC_FREE(subreq);
6869 if (!NT_STATUS_IS_OK(status)) {
6870 DEBUG(10, ("cli_notify_recv returned %s\n",
6871 nt_errstr(status)));
6872 tevent_req_nterror(req, status);
6873 return;
6876 for (i=0; i<num_changes; i++) {
6877 state->fn(changes[i].action, changes[i].name, state->priv);
6879 TALLOC_FREE(changes);
6881 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6882 0xffff, state->completion_filter,
6883 state->recursive);
6884 if (tevent_req_nomem(subreq, req)) {
6885 return;
6887 tevent_req_set_callback(subreq, swallow_notify_done, req);
6890 static bool print_notifies(uint32_t action, const char *name, void *priv)
6892 if (DEBUGLEVEL > 5) {
6893 d_printf("%d %s\n", (int)action, name);
6895 return true;
6898 static void notify_bench_done(struct tevent_req *req)
6900 int *num_finished = (int *)tevent_req_callback_data_void(req);
6901 *num_finished += 1;
6904 static bool run_notify_bench(int dummy)
6906 const char *dname = "\\notify-bench";
6907 struct tevent_context *ev;
6908 NTSTATUS status;
6909 uint16_t dnum;
6910 struct tevent_req *req1;
6911 struct tevent_req *req2 = NULL;
6912 int i, num_unc_names;
6913 int num_finished = 0;
6915 printf("starting notify-bench test\n");
6917 if (use_multishare_conn) {
6918 char **unc_list;
6919 unc_list = file_lines_load(multishare_conn_fname,
6920 &num_unc_names, 0, NULL);
6921 if (!unc_list || num_unc_names <= 0) {
6922 d_printf("Failed to load unc names list from '%s'\n",
6923 multishare_conn_fname);
6924 return false;
6926 TALLOC_FREE(unc_list);
6927 } else {
6928 num_unc_names = 1;
6931 ev = tevent_context_init(talloc_tos());
6932 if (ev == NULL) {
6933 d_printf("tevent_context_init failed\n");
6934 return false;
6937 for (i=0; i<num_unc_names; i++) {
6938 struct cli_state *cli;
6939 char *base_fname;
6941 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
6942 dname, i);
6943 if (base_fname == NULL) {
6944 return false;
6947 if (!torture_open_connection(&cli, i)) {
6948 return false;
6951 status = cli_ntcreate(cli, dname, 0,
6952 MAXIMUM_ALLOWED_ACCESS,
6953 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
6954 FILE_SHARE_DELETE,
6955 FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
6956 &dnum);
6958 if (!NT_STATUS_IS_OK(status)) {
6959 d_printf("Could not create %s: %s\n", dname,
6960 nt_errstr(status));
6961 return false;
6964 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
6965 FILE_NOTIFY_CHANGE_FILE_NAME |
6966 FILE_NOTIFY_CHANGE_DIR_NAME |
6967 FILE_NOTIFY_CHANGE_ATTRIBUTES |
6968 FILE_NOTIFY_CHANGE_LAST_WRITE,
6969 false, print_notifies, NULL);
6970 if (req1 == NULL) {
6971 d_printf("Could not create notify request\n");
6972 return false;
6975 req2 = torture_createdels_send(talloc_tos(), ev, cli,
6976 base_fname, 10, torture_numops);
6977 if (req2 == NULL) {
6978 d_printf("Could not create createdels request\n");
6979 return false;
6981 TALLOC_FREE(base_fname);
6983 tevent_req_set_callback(req2, notify_bench_done,
6984 &num_finished);
6987 while (num_finished < num_unc_names) {
6988 int ret;
6989 ret = tevent_loop_once(ev);
6990 if (ret != 0) {
6991 d_printf("tevent_loop_once failed\n");
6992 return false;
6996 if (!tevent_req_poll(req2, ev)) {
6997 d_printf("tevent_req_poll failed\n");
7000 status = torture_createdels_recv(req2);
7001 d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
7003 return true;
7006 static bool run_mangle1(int dummy)
7008 struct cli_state *cli;
7009 const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
7010 uint16_t fnum;
7011 fstring alt_name;
7012 NTSTATUS status;
7013 time_t change_time, access_time, write_time;
7014 SMB_OFF_T size;
7015 uint16_t mode;
7017 printf("starting mangle1 test\n");
7018 if (!torture_open_connection(&cli, 0)) {
7019 return False;
7022 cli_sockopt(cli, sockops);
7024 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
7025 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
7026 0, 0, &fnum);
7027 if (!NT_STATUS_IS_OK(status)) {
7028 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
7029 return false;
7031 cli_close(cli, fnum);
7033 status = cli_qpathinfo_alt_name(cli, fname, alt_name);
7034 if (!NT_STATUS_IS_OK(status)) {
7035 d_printf("cli_qpathinfo_alt_name failed: %s\n",
7036 nt_errstr(status));
7037 return false;
7039 d_printf("alt_name: %s\n", alt_name);
7041 status = cli_open(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
7042 if (!NT_STATUS_IS_OK(status)) {
7043 d_printf("cli_open(%s) failed: %s\n", alt_name,
7044 nt_errstr(status));
7045 return false;
7047 cli_close(cli, fnum);
7049 status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
7050 &write_time, &size, &mode);
7051 if (!NT_STATUS_IS_OK(status)) {
7052 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
7053 nt_errstr(status));
7054 return false;
7057 return true;
7060 static size_t null_source(uint8_t *buf, size_t n, void *priv)
7062 size_t *to_pull = (size_t *)priv;
7063 size_t thistime = *to_pull;
7065 thistime = MIN(thistime, n);
7066 if (thistime == 0) {
7067 return 0;
7070 memset(buf, 0, thistime);
7071 *to_pull -= thistime;
7072 return thistime;
7075 static bool run_windows_write(int dummy)
7077 struct cli_state *cli1;
7078 uint16_t fnum;
7079 int i;
7080 bool ret = false;
7081 const char *fname = "\\writetest.txt";
7082 struct timeval start_time;
7083 double seconds;
7084 double kbytes;
7085 NTSTATUS status;
7087 printf("starting windows_write test\n");
7088 if (!torture_open_connection(&cli1, 0)) {
7089 return False;
7092 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
7093 if (!NT_STATUS_IS_OK(status)) {
7094 printf("open failed (%s)\n", nt_errstr(status));
7095 return False;
7098 cli_sockopt(cli1, sockops);
7100 start_time = timeval_current();
7102 for (i=0; i<torture_numops; i++) {
7103 uint8_t c = 0;
7104 off_t start = i * torture_blocksize;
7105 size_t to_pull = torture_blocksize - 1;
7107 status = cli_writeall(cli1, fnum, 0, &c,
7108 start + torture_blocksize - 1, 1, NULL);
7109 if (!NT_STATUS_IS_OK(status)) {
7110 printf("cli_write failed: %s\n", nt_errstr(status));
7111 goto fail;
7114 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
7115 null_source, &to_pull);
7116 if (!NT_STATUS_IS_OK(status)) {
7117 printf("cli_push returned: %s\n", nt_errstr(status));
7118 goto fail;
7122 seconds = timeval_elapsed(&start_time);
7123 kbytes = (double)torture_blocksize * torture_numops;
7124 kbytes /= 1024;
7126 printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
7127 (double)seconds, (int)(kbytes/seconds));
7129 ret = true;
7130 fail:
7131 cli_close(cli1, fnum);
7132 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7133 torture_close_connection(cli1);
7134 return ret;
7137 static bool run_cli_echo(int dummy)
7139 struct cli_state *cli;
7140 NTSTATUS status;
7142 printf("starting cli_echo test\n");
7143 if (!torture_open_connection(&cli, 0)) {
7144 return false;
7146 cli_sockopt(cli, sockops);
7148 status = cli_echo(cli, 5, data_blob_const("hello", 5));
7150 d_printf("cli_echo returned %s\n", nt_errstr(status));
7152 torture_close_connection(cli);
7153 return NT_STATUS_IS_OK(status);
7156 static bool run_uid_regression_test(int dummy)
7158 static struct cli_state *cli;
7159 int16_t old_vuid;
7160 int16_t old_cnum;
7161 bool correct = True;
7162 NTSTATUS status;
7164 printf("starting uid regression test\n");
7166 if (!torture_open_connection(&cli, 0)) {
7167 return False;
7170 cli_sockopt(cli, sockops);
7172 /* Ok - now save then logoff our current user. */
7173 old_vuid = cli_state_get_uid(cli);
7175 status = cli_ulogoff(cli);
7176 if (!NT_STATUS_IS_OK(status)) {
7177 d_printf("(%s) cli_ulogoff failed: %s\n",
7178 __location__, nt_errstr(status));
7179 correct = false;
7180 goto out;
7183 cli_state_set_uid(cli, old_vuid);
7185 /* Try an operation. */
7186 status = cli_mkdir(cli, "\\uid_reg_test");
7187 if (NT_STATUS_IS_OK(status)) {
7188 d_printf("(%s) cli_mkdir succeeded\n",
7189 __location__);
7190 correct = false;
7191 goto out;
7192 } else {
7193 /* Should be bad uid. */
7194 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
7195 NT_STATUS_USER_SESSION_DELETED)) {
7196 correct = false;
7197 goto out;
7201 old_cnum = cli_state_get_tid(cli);
7203 /* Now try a SMBtdis with the invald vuid set to zero. */
7204 cli_state_set_uid(cli, 0);
7206 /* This should succeed. */
7207 status = cli_tdis(cli);
7209 if (NT_STATUS_IS_OK(status)) {
7210 d_printf("First tdis with invalid vuid should succeed.\n");
7211 } else {
7212 d_printf("First tdis failed (%s)\n", nt_errstr(status));
7213 correct = false;
7214 goto out;
7217 cli_state_set_uid(cli, old_vuid);
7218 cli_state_set_tid(cli, old_cnum);
7220 /* This should fail. */
7221 status = cli_tdis(cli);
7222 if (NT_STATUS_IS_OK(status)) {
7223 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
7224 correct = false;
7225 goto out;
7226 } else {
7227 /* Should be bad tid. */
7228 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
7229 NT_STATUS_NETWORK_NAME_DELETED)) {
7230 correct = false;
7231 goto out;
7235 cli_rmdir(cli, "\\uid_reg_test");
7237 out:
7239 cli_shutdown(cli);
7240 return correct;
7244 static const char *illegal_chars = "*\\/?<>|\":";
7245 static char force_shortname_chars[] = " +,.[];=\177";
7247 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
7248 const char *mask, void *state)
7250 struct cli_state *pcli = (struct cli_state *)state;
7251 fstring fname;
7252 NTSTATUS status = NT_STATUS_OK;
7254 slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
7256 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
7257 return NT_STATUS_OK;
7259 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
7260 status = cli_rmdir(pcli, fname);
7261 if (!NT_STATUS_IS_OK(status)) {
7262 printf("del_fn: failed to rmdir %s\n,", fname );
7264 } else {
7265 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7266 if (!NT_STATUS_IS_OK(status)) {
7267 printf("del_fn: failed to unlink %s\n,", fname );
7270 return status;
7273 struct sn_state {
7274 int matched;
7275 int i;
7276 bool val;
7279 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
7280 const char *name, void *state)
7282 struct sn_state *s = (struct sn_state *)state;
7283 int i = s->i;
7285 #if 0
7286 printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
7287 i, finfo->name, finfo->short_name);
7288 #endif
7290 if (strchr(force_shortname_chars, i)) {
7291 if (!finfo->short_name) {
7292 /* Shortname not created when it should be. */
7293 d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
7294 __location__, finfo->name, i);
7295 s->val = true;
7297 } else if (finfo->short_name){
7298 /* Shortname created when it should not be. */
7299 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
7300 __location__, finfo->short_name, finfo->name);
7301 s->val = true;
7303 s->matched += 1;
7304 return NT_STATUS_OK;
7307 static bool run_shortname_test(int dummy)
7309 static struct cli_state *cli;
7310 bool correct = True;
7311 int i;
7312 struct sn_state s;
7313 char fname[20];
7314 NTSTATUS status;
7316 printf("starting shortname test\n");
7318 if (!torture_open_connection(&cli, 0)) {
7319 return False;
7322 cli_sockopt(cli, sockops);
7324 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7325 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7326 cli_rmdir(cli, "\\shortname");
7328 status = cli_mkdir(cli, "\\shortname");
7329 if (!NT_STATUS_IS_OK(status)) {
7330 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
7331 __location__, nt_errstr(status));
7332 correct = false;
7333 goto out;
7336 strlcpy(fname, "\\shortname\\", sizeof(fname));
7337 strlcat(fname, "test .txt", sizeof(fname));
7339 s.val = false;
7341 for (i = 32; i < 128; i++) {
7342 uint16_t fnum = (uint16_t)-1;
7344 s.i = i;
7346 if (strchr(illegal_chars, i)) {
7347 continue;
7349 fname[15] = i;
7351 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
7352 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum);
7353 if (!NT_STATUS_IS_OK(status)) {
7354 d_printf("(%s) cli_nt_create of %s failed: %s\n",
7355 __location__, fname, nt_errstr(status));
7356 correct = false;
7357 goto out;
7359 cli_close(cli, fnum);
7361 s.matched = 0;
7362 status = cli_list(cli, "\\shortname\\test*.*", 0,
7363 shortname_list_fn, &s);
7364 if (s.matched != 1) {
7365 d_printf("(%s) failed to list %s: %s\n",
7366 __location__, fname, nt_errstr(status));
7367 correct = false;
7368 goto out;
7371 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7372 if (!NT_STATUS_IS_OK(status)) {
7373 d_printf("(%s) failed to delete %s: %s\n",
7374 __location__, fname, nt_errstr(status));
7375 correct = false;
7376 goto out;
7379 if (s.val) {
7380 correct = false;
7381 goto out;
7385 out:
7387 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7388 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7389 cli_rmdir(cli, "\\shortname");
7390 torture_close_connection(cli);
7391 return correct;
7394 static void pagedsearch_cb(struct tevent_req *req)
7396 int rc;
7397 struct tldap_message *msg;
7398 char *dn;
7400 rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
7401 if (rc != TLDAP_SUCCESS) {
7402 d_printf("tldap_search_paged_recv failed: %s\n",
7403 tldap_err2string(rc));
7404 return;
7406 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
7407 TALLOC_FREE(msg);
7408 return;
7410 if (!tldap_entry_dn(msg, &dn)) {
7411 d_printf("tldap_entry_dn failed\n");
7412 return;
7414 d_printf("%s\n", dn);
7415 TALLOC_FREE(msg);
7418 static bool run_tldap(int dummy)
7420 struct tldap_context *ld;
7421 int fd, rc;
7422 NTSTATUS status;
7423 struct sockaddr_storage addr;
7424 struct tevent_context *ev;
7425 struct tevent_req *req;
7426 char *basedn;
7427 const char *filter;
7429 if (!resolve_name(host, &addr, 0, false)) {
7430 d_printf("could not find host %s\n", host);
7431 return false;
7433 status = open_socket_out(&addr, 389, 9999, &fd);
7434 if (!NT_STATUS_IS_OK(status)) {
7435 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
7436 return false;
7439 ld = tldap_context_create(talloc_tos(), fd);
7440 if (ld == NULL) {
7441 close(fd);
7442 d_printf("tldap_context_create failed\n");
7443 return false;
7446 rc = tldap_fetch_rootdse(ld);
7447 if (rc != TLDAP_SUCCESS) {
7448 d_printf("tldap_fetch_rootdse failed: %s\n",
7449 tldap_errstr(talloc_tos(), ld, rc));
7450 return false;
7453 basedn = tldap_talloc_single_attribute(
7454 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
7455 if (basedn == NULL) {
7456 d_printf("no defaultNamingContext\n");
7457 return false;
7459 d_printf("defaultNamingContext: %s\n", basedn);
7461 ev = tevent_context_init(talloc_tos());
7462 if (ev == NULL) {
7463 d_printf("tevent_context_init failed\n");
7464 return false;
7467 req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
7468 TLDAP_SCOPE_SUB, "(objectclass=*)",
7469 NULL, 0, 0,
7470 NULL, 0, NULL, 0, 0, 0, 0, 5);
7471 if (req == NULL) {
7472 d_printf("tldap_search_paged_send failed\n");
7473 return false;
7475 tevent_req_set_callback(req, pagedsearch_cb, NULL);
7477 tevent_req_poll(req, ev);
7479 TALLOC_FREE(req);
7481 /* test search filters against rootDSE */
7482 filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
7483 "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
7485 rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
7486 NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
7487 talloc_tos(), NULL, NULL);
7488 if (rc != TLDAP_SUCCESS) {
7489 d_printf("tldap_search with complex filter failed: %s\n",
7490 tldap_errstr(talloc_tos(), ld, rc));
7491 return false;
7494 TALLOC_FREE(ld);
7495 return true;
7498 /* Torture test to ensure no regression of :
7499 https://bugzilla.samba.org/show_bug.cgi?id=7084
7502 static bool run_dir_createtime(int dummy)
7504 struct cli_state *cli;
7505 const char *dname = "\\testdir";
7506 const char *fname = "\\testdir\\testfile";
7507 NTSTATUS status;
7508 struct timespec create_time;
7509 struct timespec create_time1;
7510 uint16_t fnum;
7511 bool ret = false;
7513 if (!torture_open_connection(&cli, 0)) {
7514 return false;
7517 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7518 cli_rmdir(cli, dname);
7520 status = cli_mkdir(cli, dname);
7521 if (!NT_STATUS_IS_OK(status)) {
7522 printf("mkdir failed: %s\n", nt_errstr(status));
7523 goto out;
7526 status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
7527 NULL, NULL, NULL);
7528 if (!NT_STATUS_IS_OK(status)) {
7529 printf("cli_qpathinfo2 returned %s\n",
7530 nt_errstr(status));
7531 goto out;
7534 /* Sleep 3 seconds, then create a file. */
7535 sleep(3);
7537 status = cli_open(cli, fname, O_RDWR | O_CREAT | O_EXCL,
7538 DENY_NONE, &fnum);
7539 if (!NT_STATUS_IS_OK(status)) {
7540 printf("cli_open failed: %s\n", nt_errstr(status));
7541 goto out;
7544 status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
7545 NULL, NULL, NULL);
7546 if (!NT_STATUS_IS_OK(status)) {
7547 printf("cli_qpathinfo2 (2) returned %s\n",
7548 nt_errstr(status));
7549 goto out;
7552 if (timespec_compare(&create_time1, &create_time)) {
7553 printf("run_dir_createtime: create time was updated (error)\n");
7554 } else {
7555 printf("run_dir_createtime: create time was not updated (correct)\n");
7556 ret = true;
7559 out:
7561 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7562 cli_rmdir(cli, dname);
7563 if (!torture_close_connection(cli)) {
7564 ret = false;
7566 return ret;
7570 static bool run_streamerror(int dummy)
7572 struct cli_state *cli;
7573 const char *dname = "\\testdir";
7574 const char *streamname =
7575 "testdir:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
7576 NTSTATUS status;
7577 time_t change_time, access_time, write_time;
7578 SMB_OFF_T size;
7579 uint16_t mode, fnum;
7580 bool ret = true;
7582 if (!torture_open_connection(&cli, 0)) {
7583 return false;
7586 cli_unlink(cli, "\\testdir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7587 cli_rmdir(cli, dname);
7589 status = cli_mkdir(cli, dname);
7590 if (!NT_STATUS_IS_OK(status)) {
7591 printf("mkdir failed: %s\n", nt_errstr(status));
7592 return false;
7595 cli_qpathinfo1(cli, streamname, &change_time, &access_time, &write_time,
7596 &size, &mode);
7597 status = cli_nt_error(cli);
7599 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7600 printf("pathinfo returned %s, expected "
7601 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
7602 nt_errstr(status));
7603 ret = false;
7606 status = cli_ntcreate(cli, streamname, 0x16,
7607 FILE_READ_DATA|FILE_READ_EA|
7608 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
7609 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7610 FILE_OPEN, 0, 0, &fnum);
7612 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7613 printf("ntcreate returned %s, expected "
7614 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
7615 nt_errstr(status));
7616 ret = false;
7620 cli_rmdir(cli, dname);
7621 return ret;
7624 static bool run_local_substitute(int dummy)
7626 bool ok = true;
7628 ok &= subst_test("%U", "bla", "", -1, -1, "bla");
7629 ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
7630 ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
7631 ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
7632 ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
7633 ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
7634 ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
7635 ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
7637 /* Different captialization rules in sub_basic... */
7639 ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
7640 "blaDOM") == 0);
7642 return ok;
7645 static bool run_local_base64(int dummy)
7647 int i;
7648 bool ret = true;
7650 for (i=1; i<2000; i++) {
7651 DATA_BLOB blob1, blob2;
7652 char *b64;
7654 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
7655 blob1.length = i;
7656 generate_random_buffer(blob1.data, blob1.length);
7658 b64 = base64_encode_data_blob(talloc_tos(), blob1);
7659 if (b64 == NULL) {
7660 d_fprintf(stderr, "base64_encode_data_blob failed "
7661 "for %d bytes\n", i);
7662 ret = false;
7664 blob2 = base64_decode_data_blob(b64);
7665 TALLOC_FREE(b64);
7667 if (data_blob_cmp(&blob1, &blob2)) {
7668 d_fprintf(stderr, "data_blob_cmp failed for %d "
7669 "bytes\n", i);
7670 ret = false;
7672 TALLOC_FREE(blob1.data);
7673 data_blob_free(&blob2);
7675 return ret;
7678 static bool run_local_gencache(int dummy)
7680 char *val;
7681 time_t tm;
7682 DATA_BLOB blob;
7684 if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
7685 d_printf("%s: gencache_set() failed\n", __location__);
7686 return False;
7689 if (!gencache_get("foo", NULL, NULL)) {
7690 d_printf("%s: gencache_get() failed\n", __location__);
7691 return False;
7694 if (!gencache_get("foo", &val, &tm)) {
7695 d_printf("%s: gencache_get() failed\n", __location__);
7696 return False;
7699 if (strcmp(val, "bar") != 0) {
7700 d_printf("%s: gencache_get() returned %s, expected %s\n",
7701 __location__, val, "bar");
7702 SAFE_FREE(val);
7703 return False;
7706 SAFE_FREE(val);
7708 if (!gencache_del("foo")) {
7709 d_printf("%s: gencache_del() failed\n", __location__);
7710 return False;
7712 if (gencache_del("foo")) {
7713 d_printf("%s: second gencache_del() succeeded\n",
7714 __location__);
7715 return False;
7718 if (gencache_get("foo", &val, &tm)) {
7719 d_printf("%s: gencache_get() on deleted entry "
7720 "succeeded\n", __location__);
7721 return False;
7724 blob = data_blob_string_const_null("bar");
7725 tm = time(NULL) + 60;
7727 if (!gencache_set_data_blob("foo", &blob, tm)) {
7728 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
7729 return False;
7732 if (!gencache_get_data_blob("foo", &blob, NULL, NULL)) {
7733 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
7734 return False;
7737 if (strcmp((const char *)blob.data, "bar") != 0) {
7738 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
7739 __location__, (const char *)blob.data, "bar");
7740 data_blob_free(&blob);
7741 return False;
7744 data_blob_free(&blob);
7746 if (!gencache_del("foo")) {
7747 d_printf("%s: gencache_del() failed\n", __location__);
7748 return False;
7750 if (gencache_del("foo")) {
7751 d_printf("%s: second gencache_del() succeeded\n",
7752 __location__);
7753 return False;
7756 if (gencache_get_data_blob("foo", &blob, NULL, NULL)) {
7757 d_printf("%s: gencache_get_data_blob() on deleted entry "
7758 "succeeded\n", __location__);
7759 return False;
7762 return True;
7765 static bool rbt_testval(struct db_context *db, const char *key,
7766 const char *value)
7768 struct db_record *rec;
7769 TDB_DATA data = string_tdb_data(value);
7770 bool ret = false;
7771 NTSTATUS status;
7772 TDB_DATA dbvalue;
7774 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
7775 if (rec == NULL) {
7776 d_fprintf(stderr, "fetch_locked failed\n");
7777 goto done;
7779 status = dbwrap_record_store(rec, data, 0);
7780 if (!NT_STATUS_IS_OK(status)) {
7781 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
7782 goto done;
7784 TALLOC_FREE(rec);
7786 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
7787 if (rec == NULL) {
7788 d_fprintf(stderr, "second fetch_locked failed\n");
7789 goto done;
7792 dbvalue = dbwrap_record_get_value(rec);
7793 if ((dbvalue.dsize != data.dsize)
7794 || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
7795 d_fprintf(stderr, "Got wrong data back\n");
7796 goto done;
7799 ret = true;
7800 done:
7801 TALLOC_FREE(rec);
7802 return ret;
7805 static bool run_local_rbtree(int dummy)
7807 struct db_context *db;
7808 bool ret = false;
7809 int i;
7811 db = db_open_rbt(NULL);
7813 if (db == NULL) {
7814 d_fprintf(stderr, "db_open_rbt failed\n");
7815 return false;
7818 for (i=0; i<1000; i++) {
7819 char *key, *value;
7821 if (asprintf(&key, "key%ld", random()) == -1) {
7822 goto done;
7824 if (asprintf(&value, "value%ld", random()) == -1) {
7825 SAFE_FREE(key);
7826 goto done;
7829 if (!rbt_testval(db, key, value)) {
7830 SAFE_FREE(key);
7831 SAFE_FREE(value);
7832 goto done;
7835 SAFE_FREE(value);
7836 if (asprintf(&value, "value%ld", random()) == -1) {
7837 SAFE_FREE(key);
7838 goto done;
7841 if (!rbt_testval(db, key, value)) {
7842 SAFE_FREE(key);
7843 SAFE_FREE(value);
7844 goto done;
7847 SAFE_FREE(key);
7848 SAFE_FREE(value);
7851 ret = true;
7853 done:
7854 TALLOC_FREE(db);
7855 return ret;
7860 local test for character set functions
7862 This is a very simple test for the functionality in convert_string_error()
7864 static bool run_local_convert_string(int dummy)
7866 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
7867 const char *test_strings[2] = { "March", "M\303\244rz" };
7868 char dst[7];
7869 int i;
7871 for (i=0; i<2; i++) {
7872 const char *str = test_strings[i];
7873 int len = strlen(str);
7874 size_t converted_size;
7875 bool ret;
7877 memset(dst, 'X', sizeof(dst));
7879 /* first try with real source length */
7880 ret = convert_string_error(CH_UNIX, CH_UTF8,
7881 str, len,
7882 dst, sizeof(dst),
7883 &converted_size);
7884 if (ret != true) {
7885 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
7886 goto failed;
7889 if (converted_size != len) {
7890 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
7891 str, len, (int)converted_size);
7892 goto failed;
7895 if (strncmp(str, dst, converted_size) != 0) {
7896 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
7897 goto failed;
7900 if (strlen(str) != converted_size) {
7901 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
7902 (int)strlen(str), (int)converted_size);
7903 goto failed;
7906 if (dst[converted_size] != 'X') {
7907 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
7908 goto failed;
7911 /* now with srclen==-1, this causes the nul to be
7912 * converted too */
7913 ret = convert_string_error(CH_UNIX, CH_UTF8,
7914 str, -1,
7915 dst, sizeof(dst),
7916 &converted_size);
7917 if (ret != true) {
7918 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
7919 goto failed;
7922 if (converted_size != len+1) {
7923 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
7924 str, len, (int)converted_size);
7925 goto failed;
7928 if (strncmp(str, dst, converted_size) != 0) {
7929 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
7930 goto failed;
7933 if (len+1 != converted_size) {
7934 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
7935 len+1, (int)converted_size);
7936 goto failed;
7939 if (dst[converted_size] != 'X') {
7940 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
7941 goto failed;
7947 TALLOC_FREE(tmp_ctx);
7948 return true;
7949 failed:
7950 TALLOC_FREE(tmp_ctx);
7951 return false;
7955 struct talloc_dict_test {
7956 int content;
7959 static int talloc_dict_traverse_fn(DATA_BLOB key, void *data, void *priv)
7961 int *count = (int *)priv;
7962 *count += 1;
7963 return 0;
7966 static bool run_local_talloc_dict(int dummy)
7968 struct talloc_dict *dict;
7969 struct talloc_dict_test *t;
7970 int key, count;
7972 dict = talloc_dict_init(talloc_tos());
7973 if (dict == NULL) {
7974 return false;
7977 t = talloc(talloc_tos(), struct talloc_dict_test);
7978 if (t == NULL) {
7979 return false;
7982 key = 1;
7983 t->content = 1;
7984 if (!talloc_dict_set(dict, data_blob_const(&key, sizeof(key)), t)) {
7985 return false;
7988 count = 0;
7989 if (talloc_dict_traverse(dict, talloc_dict_traverse_fn, &count) != 0) {
7990 return false;
7993 if (count != 1) {
7994 return false;
7997 TALLOC_FREE(dict);
7999 return true;
8002 static bool run_local_string_to_sid(int dummy) {
8003 struct dom_sid sid;
8005 if (string_to_sid(&sid, "S--1-5-32-545")) {
8006 printf("allowing S--1-5-32-545\n");
8007 return false;
8009 if (string_to_sid(&sid, "S-1-5-32-+545")) {
8010 printf("allowing S-1-5-32-+545\n");
8011 return false;
8013 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")) {
8014 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
8015 return false;
8017 if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
8018 printf("allowing S-1-5-32-545-abc\n");
8019 return false;
8021 if (!string_to_sid(&sid, "S-1-5-32-545")) {
8022 printf("could not parse S-1-5-32-545\n");
8023 return false;
8025 if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
8026 printf("mis-parsed S-1-5-32-545 as %s\n",
8027 sid_string_tos(&sid));
8028 return false;
8030 return true;
8033 static bool run_local_binary_to_sid(int dummy) {
8034 struct dom_sid *sid = talloc(NULL, struct dom_sid);
8035 static const char good_binary_sid[] = {
8036 0x1, /* revision number */
8037 15, /* num auths */
8038 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8039 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8040 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8041 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8042 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8043 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8044 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8045 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8046 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8047 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8048 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8049 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8050 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8051 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8052 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8053 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8056 static const char long_binary_sid[] = {
8057 0x1, /* revision number */
8058 15, /* num auths */
8059 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8060 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8061 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8062 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8063 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8064 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8065 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8066 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8067 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8068 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8069 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8070 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8071 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8072 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8073 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8074 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8075 0x1, 0x1, 0x1, 0x1, /* auth[15] */
8076 0x1, 0x1, 0x1, 0x1, /* auth[16] */
8077 0x1, 0x1, 0x1, 0x1, /* auth[17] */
8080 static const char long_binary_sid2[] = {
8081 0x1, /* revision number */
8082 32, /* num auths */
8083 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8084 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8085 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8086 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8087 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8088 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8089 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8090 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8091 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8092 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8093 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8094 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8095 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8096 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8097 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8098 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8099 0x1, 0x1, 0x1, 0x1, /* auth[15] */
8100 0x1, 0x1, 0x1, 0x1, /* auth[16] */
8101 0x1, 0x1, 0x1, 0x1, /* auth[17] */
8102 0x1, 0x1, 0x1, 0x1, /* auth[18] */
8103 0x1, 0x1, 0x1, 0x1, /* auth[19] */
8104 0x1, 0x1, 0x1, 0x1, /* auth[20] */
8105 0x1, 0x1, 0x1, 0x1, /* auth[21] */
8106 0x1, 0x1, 0x1, 0x1, /* auth[22] */
8107 0x1, 0x1, 0x1, 0x1, /* auth[23] */
8108 0x1, 0x1, 0x1, 0x1, /* auth[24] */
8109 0x1, 0x1, 0x1, 0x1, /* auth[25] */
8110 0x1, 0x1, 0x1, 0x1, /* auth[26] */
8111 0x1, 0x1, 0x1, 0x1, /* auth[27] */
8112 0x1, 0x1, 0x1, 0x1, /* auth[28] */
8113 0x1, 0x1, 0x1, 0x1, /* auth[29] */
8114 0x1, 0x1, 0x1, 0x1, /* auth[30] */
8115 0x1, 0x1, 0x1, 0x1, /* auth[31] */
8118 if (!sid_parse(good_binary_sid, sizeof(good_binary_sid), sid)) {
8119 return false;
8121 if (sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid)) {
8122 return false;
8124 if (sid_parse(long_binary_sid, sizeof(long_binary_sid), sid)) {
8125 return false;
8127 return true;
8130 /* Split a path name into filename and stream name components. Canonicalise
8131 * such that an implicit $DATA token is always explicit.
8133 * The "specification" of this function can be found in the
8134 * run_local_stream_name() function in torture.c, I've tried those
8135 * combinations against a W2k3 server.
8138 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
8139 char **pbase, char **pstream)
8141 char *base = NULL;
8142 char *stream = NULL;
8143 char *sname; /* stream name */
8144 const char *stype; /* stream type */
8146 DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
8148 sname = strchr_m(fname, ':');
8150 if (lp_posix_pathnames() || (sname == NULL)) {
8151 if (pbase != NULL) {
8152 base = talloc_strdup(mem_ctx, fname);
8153 NT_STATUS_HAVE_NO_MEMORY(base);
8155 goto done;
8158 if (pbase != NULL) {
8159 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
8160 NT_STATUS_HAVE_NO_MEMORY(base);
8163 sname += 1;
8165 stype = strchr_m(sname, ':');
8167 if (stype == NULL) {
8168 sname = talloc_strdup(mem_ctx, sname);
8169 stype = "$DATA";
8171 else {
8172 if (strcasecmp_m(stype, ":$DATA") != 0) {
8174 * If there is an explicit stream type, so far we only
8175 * allow $DATA. Is there anything else allowed? -- vl
8177 DEBUG(10, ("[%s] is an invalid stream type\n", stype));
8178 TALLOC_FREE(base);
8179 return NT_STATUS_OBJECT_NAME_INVALID;
8181 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
8182 stype += 1;
8185 if (sname == NULL) {
8186 TALLOC_FREE(base);
8187 return NT_STATUS_NO_MEMORY;
8190 if (sname[0] == '\0') {
8192 * no stream name, so no stream
8194 goto done;
8197 if (pstream != NULL) {
8198 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
8199 if (stream == NULL) {
8200 TALLOC_FREE(sname);
8201 TALLOC_FREE(base);
8202 return NT_STATUS_NO_MEMORY;
8205 * upper-case the type field
8207 strupper_m(strchr_m(stream, ':')+1);
8210 done:
8211 if (pbase != NULL) {
8212 *pbase = base;
8214 if (pstream != NULL) {
8215 *pstream = stream;
8217 return NT_STATUS_OK;
8220 static bool test_stream_name(const char *fname, const char *expected_base,
8221 const char *expected_stream,
8222 NTSTATUS expected_status)
8224 NTSTATUS status;
8225 char *base = NULL;
8226 char *stream = NULL;
8228 status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
8229 if (!NT_STATUS_EQUAL(status, expected_status)) {
8230 goto error;
8233 if (!NT_STATUS_IS_OK(status)) {
8234 return true;
8237 if (base == NULL) goto error;
8239 if (strcmp(expected_base, base) != 0) goto error;
8241 if ((expected_stream != NULL) && (stream == NULL)) goto error;
8242 if ((expected_stream == NULL) && (stream != NULL)) goto error;
8244 if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
8245 goto error;
8247 TALLOC_FREE(base);
8248 TALLOC_FREE(stream);
8249 return true;
8251 error:
8252 d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
8253 fname, expected_base ? expected_base : "<NULL>",
8254 expected_stream ? expected_stream : "<NULL>",
8255 nt_errstr(expected_status));
8256 d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
8257 base ? base : "<NULL>", stream ? stream : "<NULL>",
8258 nt_errstr(status));
8259 TALLOC_FREE(base);
8260 TALLOC_FREE(stream);
8261 return false;
8264 static bool run_local_stream_name(int dummy)
8266 bool ret = true;
8268 ret &= test_stream_name(
8269 "bla", "bla", NULL, NT_STATUS_OK);
8270 ret &= test_stream_name(
8271 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
8272 ret &= test_stream_name(
8273 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8274 ret &= test_stream_name(
8275 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
8276 ret &= test_stream_name(
8277 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8278 ret &= test_stream_name(
8279 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
8280 ret &= test_stream_name(
8281 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
8282 ret &= test_stream_name(
8283 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
8285 return ret;
8288 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
8290 if (a.length != b.length) {
8291 printf("a.length=%d != b.length=%d\n",
8292 (int)a.length, (int)b.length);
8293 return false;
8295 if (memcmp(a.data, b.data, a.length) != 0) {
8296 printf("a.data and b.data differ\n");
8297 return false;
8299 return true;
8302 static bool run_local_memcache(int dummy)
8304 struct memcache *cache;
8305 DATA_BLOB k1, k2;
8306 DATA_BLOB d1, d2, d3;
8307 DATA_BLOB v1, v2, v3;
8309 TALLOC_CTX *mem_ctx;
8310 char *str1, *str2;
8311 size_t size1, size2;
8312 bool ret = false;
8314 cache = memcache_init(NULL, 100);
8316 if (cache == NULL) {
8317 printf("memcache_init failed\n");
8318 return false;
8321 d1 = data_blob_const("d1", 2);
8322 d2 = data_blob_const("d2", 2);
8323 d3 = data_blob_const("d3", 2);
8325 k1 = data_blob_const("d1", 2);
8326 k2 = data_blob_const("d2", 2);
8328 memcache_add(cache, STAT_CACHE, k1, d1);
8329 memcache_add(cache, GETWD_CACHE, k2, d2);
8331 if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
8332 printf("could not find k1\n");
8333 return false;
8335 if (!data_blob_equal(d1, v1)) {
8336 return false;
8339 if (!memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8340 printf("could not find k2\n");
8341 return false;
8343 if (!data_blob_equal(d2, v2)) {
8344 return false;
8347 memcache_add(cache, STAT_CACHE, k1, d3);
8349 if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
8350 printf("could not find replaced k1\n");
8351 return false;
8353 if (!data_blob_equal(d3, v3)) {
8354 return false;
8357 memcache_add(cache, GETWD_CACHE, k1, d1);
8359 if (memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8360 printf("Did find k2, should have been purged\n");
8361 return false;
8364 TALLOC_FREE(cache);
8366 cache = memcache_init(NULL, 0);
8368 mem_ctx = talloc_init("foo");
8370 str1 = talloc_strdup(mem_ctx, "string1");
8371 str2 = talloc_strdup(mem_ctx, "string2");
8373 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8374 data_blob_string_const("torture"), &str1);
8375 size1 = talloc_total_size(cache);
8377 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8378 data_blob_string_const("torture"), &str2);
8379 size2 = talloc_total_size(cache);
8381 printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
8383 if (size2 > size1) {
8384 printf("memcache leaks memory!\n");
8385 goto fail;
8388 ret = true;
8389 fail:
8390 TALLOC_FREE(cache);
8391 return ret;
8394 static void wbclient_done(struct tevent_req *req)
8396 wbcErr wbc_err;
8397 struct winbindd_response *wb_resp;
8398 int *i = (int *)tevent_req_callback_data_void(req);
8400 wbc_err = wb_trans_recv(req, req, &wb_resp);
8401 TALLOC_FREE(req);
8402 *i += 1;
8403 d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
8406 static bool run_local_wbclient(int dummy)
8408 struct event_context *ev;
8409 struct wb_context **wb_ctx;
8410 struct winbindd_request wb_req;
8411 bool result = false;
8412 int i, j;
8414 BlockSignals(True, SIGPIPE);
8416 ev = tevent_context_init_byname(talloc_tos(), "epoll");
8417 if (ev == NULL) {
8418 goto fail;
8421 wb_ctx = talloc_array(ev, struct wb_context *, nprocs);
8422 if (wb_ctx == NULL) {
8423 goto fail;
8426 ZERO_STRUCT(wb_req);
8427 wb_req.cmd = WINBINDD_PING;
8429 d_printf("nprocs=%d, numops=%d\n", (int)nprocs, (int)torture_numops);
8431 for (i=0; i<nprocs; i++) {
8432 wb_ctx[i] = wb_context_init(ev, NULL);
8433 if (wb_ctx[i] == NULL) {
8434 goto fail;
8436 for (j=0; j<torture_numops; j++) {
8437 struct tevent_req *req;
8438 req = wb_trans_send(ev, ev, wb_ctx[i],
8439 (j % 2) == 0, &wb_req);
8440 if (req == NULL) {
8441 goto fail;
8443 tevent_req_set_callback(req, wbclient_done, &i);
8447 i = 0;
8449 while (i < nprocs * torture_numops) {
8450 tevent_loop_once(ev);
8453 result = true;
8454 fail:
8455 TALLOC_FREE(ev);
8456 return result;
8459 static void getaddrinfo_finished(struct tevent_req *req)
8461 char *name = (char *)tevent_req_callback_data_void(req);
8462 struct addrinfo *ainfo;
8463 int res;
8465 res = getaddrinfo_recv(req, &ainfo);
8466 if (res != 0) {
8467 d_printf("gai(%s) returned %s\n", name, gai_strerror(res));
8468 return;
8470 d_printf("gai(%s) succeeded\n", name);
8471 freeaddrinfo(ainfo);
8474 static bool run_getaddrinfo_send(int dummy)
8476 TALLOC_CTX *frame = talloc_stackframe();
8477 struct fncall_context *ctx;
8478 struct tevent_context *ev;
8479 bool result = false;
8480 const char *names[4] = { "www.samba.org", "notfound.samba.org",
8481 "www.slashdot.org", "heise.de" };
8482 struct tevent_req *reqs[4];
8483 int i;
8485 ev = event_context_init(frame);
8486 if (ev == NULL) {
8487 goto fail;
8490 ctx = fncall_context_init(frame, 4);
8492 for (i=0; i<ARRAY_SIZE(names); i++) {
8493 reqs[i] = getaddrinfo_send(frame, ev, ctx, names[i], NULL,
8494 NULL);
8495 if (reqs[i] == NULL) {
8496 goto fail;
8498 tevent_req_set_callback(reqs[i], getaddrinfo_finished,
8499 discard_const_p(void, names[i]));
8502 for (i=0; i<ARRAY_SIZE(reqs); i++) {
8503 tevent_loop_once(ev);
8506 result = true;
8507 fail:
8508 TALLOC_FREE(frame);
8509 return result;
8512 static bool dbtrans_inc(struct db_context *db)
8514 struct db_record *rec;
8515 uint32_t *val;
8516 bool ret = false;
8517 NTSTATUS status;
8518 TDB_DATA value;
8520 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
8521 if (rec == NULL) {
8522 printf(__location__ "fetch_lock failed\n");
8523 return false;
8526 value = dbwrap_record_get_value(rec);
8528 if (value.dsize != sizeof(uint32_t)) {
8529 printf(__location__ "value.dsize = %d\n",
8530 (int)value.dsize);
8531 goto fail;
8534 val = (uint32_t *)value.dptr;
8535 *val += 1;
8537 status = dbwrap_record_store(rec, make_tdb_data((uint8_t *)val,
8538 sizeof(uint32_t)),
8540 if (!NT_STATUS_IS_OK(status)) {
8541 printf(__location__ "store failed: %s\n",
8542 nt_errstr(status));
8543 goto fail;
8546 ret = true;
8547 fail:
8548 TALLOC_FREE(rec);
8549 return ret;
8552 static bool run_local_dbtrans(int dummy)
8554 struct db_context *db;
8555 struct db_record *rec;
8556 NTSTATUS status;
8557 uint32_t initial;
8558 int res;
8559 TDB_DATA value;
8561 db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
8562 O_RDWR|O_CREAT, 0600);
8563 if (db == NULL) {
8564 printf("Could not open transtest.db\n");
8565 return false;
8568 res = dbwrap_transaction_start(db);
8569 if (res != 0) {
8570 printf(__location__ "transaction_start failed\n");
8571 return false;
8574 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
8575 if (rec == NULL) {
8576 printf(__location__ "fetch_lock failed\n");
8577 return false;
8580 value = dbwrap_record_get_value(rec);
8582 if (value.dptr == NULL) {
8583 initial = 0;
8584 status = dbwrap_record_store(
8585 rec, make_tdb_data((uint8_t *)&initial,
8586 sizeof(initial)),
8588 if (!NT_STATUS_IS_OK(status)) {
8589 printf(__location__ "store returned %s\n",
8590 nt_errstr(status));
8591 return false;
8595 TALLOC_FREE(rec);
8597 res = dbwrap_transaction_commit(db);
8598 if (res != 0) {
8599 printf(__location__ "transaction_commit failed\n");
8600 return false;
8603 while (true) {
8604 uint32_t val, val2;
8605 int i;
8607 res = dbwrap_transaction_start(db);
8608 if (res != 0) {
8609 printf(__location__ "transaction_start failed\n");
8610 break;
8613 status = dbwrap_fetch_uint32(db, "transtest", &val);
8614 if (!NT_STATUS_IS_OK(status)) {
8615 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
8616 nt_errstr(status));
8617 break;
8620 for (i=0; i<10; i++) {
8621 if (!dbtrans_inc(db)) {
8622 return false;
8626 status = dbwrap_fetch_uint32(db, "transtest", &val2);
8627 if (!NT_STATUS_IS_OK(status)) {
8628 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
8629 nt_errstr(status));
8630 break;
8633 if (val2 != val + 10) {
8634 printf(__location__ "val=%d, val2=%d\n",
8635 (int)val, (int)val2);
8636 break;
8639 printf("val2=%d\r", val2);
8641 res = dbwrap_transaction_commit(db);
8642 if (res != 0) {
8643 printf(__location__ "transaction_commit failed\n");
8644 break;
8648 TALLOC_FREE(db);
8649 return true;
8653 * Just a dummy test to be run under a debugger. There's no real way
8654 * to inspect the tevent_select specific function from outside of
8655 * tevent_select.c.
8658 static bool run_local_tevent_select(int dummy)
8660 struct tevent_context *ev;
8661 struct tevent_fd *fd1, *fd2;
8662 bool result = false;
8664 ev = tevent_context_init_byname(NULL, "select");
8665 if (ev == NULL) {
8666 d_fprintf(stderr, "tevent_context_init_byname failed\n");
8667 goto fail;
8670 fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
8671 if (fd1 == NULL) {
8672 d_fprintf(stderr, "tevent_add_fd failed\n");
8673 goto fail;
8675 fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
8676 if (fd2 == NULL) {
8677 d_fprintf(stderr, "tevent_add_fd failed\n");
8678 goto fail;
8680 TALLOC_FREE(fd2);
8682 fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
8683 if (fd2 == NULL) {
8684 d_fprintf(stderr, "tevent_add_fd failed\n");
8685 goto fail;
8688 result = true;
8689 fail:
8690 TALLOC_FREE(ev);
8691 return result;
8694 static double create_procs(bool (*fn)(int), bool *result)
8696 int i, status;
8697 volatile pid_t *child_status;
8698 volatile bool *child_status_out;
8699 int synccount;
8700 int tries = 8;
8701 struct timeval start;
8703 synccount = 0;
8705 child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*nprocs);
8706 if (!child_status) {
8707 printf("Failed to setup shared memory\n");
8708 return -1;
8711 child_status_out = (volatile bool *)shm_setup(sizeof(bool)*nprocs);
8712 if (!child_status_out) {
8713 printf("Failed to setup result status shared memory\n");
8714 return -1;
8717 for (i = 0; i < nprocs; i++) {
8718 child_status[i] = 0;
8719 child_status_out[i] = True;
8722 start = timeval_current();
8724 for (i=0;i<nprocs;i++) {
8725 procnum = i;
8726 if (fork() == 0) {
8727 pid_t mypid = getpid();
8728 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
8730 slprintf(myname,sizeof(myname),"CLIENT%d", i);
8732 while (1) {
8733 if (torture_open_connection(&current_cli, i)) break;
8734 if (tries-- == 0) {
8735 printf("pid %d failed to start\n", (int)getpid());
8736 _exit(1);
8738 smb_msleep(10);
8741 child_status[i] = getpid();
8743 while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
8745 child_status_out[i] = fn(i);
8746 _exit(0);
8750 do {
8751 synccount = 0;
8752 for (i=0;i<nprocs;i++) {
8753 if (child_status[i]) synccount++;
8755 if (synccount == nprocs) break;
8756 smb_msleep(10);
8757 } while (timeval_elapsed(&start) < 30);
8759 if (synccount != nprocs) {
8760 printf("FAILED TO START %d CLIENTS (started %d)\n", nprocs, synccount);
8761 *result = False;
8762 return timeval_elapsed(&start);
8765 /* start the client load */
8766 start = timeval_current();
8768 for (i=0;i<nprocs;i++) {
8769 child_status[i] = 0;
8772 printf("%d clients started\n", nprocs);
8774 for (i=0;i<nprocs;i++) {
8775 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
8778 printf("\n");
8780 for (i=0;i<nprocs;i++) {
8781 if (!child_status_out[i]) {
8782 *result = False;
8785 return timeval_elapsed(&start);
8788 #define FLAG_MULTIPROC 1
8790 static struct {
8791 const char *name;
8792 bool (*fn)(int);
8793 unsigned flags;
8794 } torture_ops[] = {
8795 {"FDPASS", run_fdpasstest, 0},
8796 {"LOCK1", run_locktest1, 0},
8797 {"LOCK2", run_locktest2, 0},
8798 {"LOCK3", run_locktest3, 0},
8799 {"LOCK4", run_locktest4, 0},
8800 {"LOCK5", run_locktest5, 0},
8801 {"LOCK6", run_locktest6, 0},
8802 {"LOCK7", run_locktest7, 0},
8803 {"LOCK8", run_locktest8, 0},
8804 {"LOCK9", run_locktest9, 0},
8805 {"UNLINK", run_unlinktest, 0},
8806 {"BROWSE", run_browsetest, 0},
8807 {"ATTR", run_attrtest, 0},
8808 {"TRANS2", run_trans2test, 0},
8809 {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
8810 {"TORTURE",run_torture, FLAG_MULTIPROC},
8811 {"RANDOMIPC", run_randomipc, 0},
8812 {"NEGNOWAIT", run_negprot_nowait, 0},
8813 {"NBENCH", run_nbench, 0},
8814 {"NBENCH2", run_nbench2, 0},
8815 {"OPLOCK1", run_oplock1, 0},
8816 {"OPLOCK2", run_oplock2, 0},
8817 {"OPLOCK4", run_oplock4, 0},
8818 {"DIR", run_dirtest, 0},
8819 {"DIR1", run_dirtest1, 0},
8820 {"DIR-CREATETIME", run_dir_createtime, 0},
8821 {"DENY1", torture_denytest1, 0},
8822 {"DENY2", torture_denytest2, 0},
8823 {"TCON", run_tcon_test, 0},
8824 {"TCONDEV", run_tcon_devtype_test, 0},
8825 {"RW1", run_readwritetest, 0},
8826 {"RW2", run_readwritemulti, FLAG_MULTIPROC},
8827 {"RW3", run_readwritelarge, 0},
8828 {"RW-SIGNING", run_readwritelarge_signtest, 0},
8829 {"OPEN", run_opentest, 0},
8830 {"POSIX", run_simple_posix_open_test, 0},
8831 {"POSIX-APPEND", run_posix_append, 0},
8832 {"CASE-INSENSITIVE-CREATE", run_case_insensitive_create, 0},
8833 {"ASYNC-ECHO", run_async_echo, 0},
8834 { "UID-REGRESSION-TEST", run_uid_regression_test, 0},
8835 { "SHORTNAME-TEST", run_shortname_test, 0},
8836 { "ADDRCHANGE", run_addrchange, 0},
8837 #if 1
8838 {"OPENATTR", run_openattrtest, 0},
8839 #endif
8840 {"XCOPY", run_xcopy, 0},
8841 {"RENAME", run_rename, 0},
8842 {"DELETE", run_deletetest, 0},
8843 {"DELETE-LN", run_deletetest_ln, 0},
8844 {"PROPERTIES", run_properties, 0},
8845 {"MANGLE", torture_mangle, 0},
8846 {"MANGLE1", run_mangle1, 0},
8847 {"W2K", run_w2ktest, 0},
8848 {"TRANS2SCAN", torture_trans2_scan, 0},
8849 {"NTTRANSSCAN", torture_nttrans_scan, 0},
8850 {"UTABLE", torture_utable, 0},
8851 {"CASETABLE", torture_casetable, 0},
8852 {"ERRMAPEXTRACT", run_error_map_extract, 0},
8853 {"PIPE_NUMBER", run_pipe_number, 0},
8854 {"TCON2", run_tcon2_test, 0},
8855 {"IOCTL", torture_ioctl_test, 0},
8856 {"CHKPATH", torture_chkpath_test, 0},
8857 {"FDSESS", run_fdsesstest, 0},
8858 { "EATEST", run_eatest, 0},
8859 { "SESSSETUP_BENCH", run_sesssetup_bench, 0},
8860 { "CHAIN1", run_chain1, 0},
8861 { "CHAIN2", run_chain2, 0},
8862 { "WINDOWS-WRITE", run_windows_write, 0},
8863 { "NTTRANS-CREATE", run_nttrans_create, 0},
8864 { "NTTRANS-FSCTL", run_nttrans_fsctl, 0},
8865 { "CLI_ECHO", run_cli_echo, 0},
8866 { "GETADDRINFO", run_getaddrinfo_send, 0},
8867 { "TLDAP", run_tldap },
8868 { "STREAMERROR", run_streamerror },
8869 { "NOTIFY-BENCH", run_notify_bench },
8870 { "BAD-NBT-SESSION", run_bad_nbt_session },
8871 { "SMB-ANY-CONNECT", run_smb_any_connect },
8872 { "NOTIFY-ONLINE", run_notify_online },
8873 { "SMB2-BASIC", run_smb2_basic },
8874 { "LOCAL-SUBSTITUTE", run_local_substitute, 0},
8875 { "LOCAL-GENCACHE", run_local_gencache, 0},
8876 { "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0},
8877 { "LOCAL-BASE64", run_local_base64, 0},
8878 { "LOCAL-RBTREE", run_local_rbtree, 0},
8879 { "LOCAL-MEMCACHE", run_local_memcache, 0},
8880 { "LOCAL-STREAM-NAME", run_local_stream_name, 0},
8881 { "LOCAL-WBCLIENT", run_local_wbclient, 0},
8882 { "LOCAL-string_to_sid", run_local_string_to_sid, 0},
8883 { "LOCAL-binary_to_sid", run_local_binary_to_sid, 0},
8884 { "LOCAL-DBTRANS", run_local_dbtrans, 0},
8885 { "LOCAL-TEVENT-SELECT", run_local_tevent_select, 0},
8886 { "LOCAL-CONVERT-STRING", run_local_convert_string, 0},
8887 { "LOCAL-CONV-AUTH-INFO", run_local_conv_auth_info, 0},
8888 { "LOCAL-sprintf_append", run_local_sprintf_append, 0},
8889 {NULL, NULL, 0}};
8893 /****************************************************************************
8894 run a specified test or "ALL"
8895 ****************************************************************************/
8896 static bool run_test(const char *name)
8898 bool ret = True;
8899 bool result = True;
8900 bool found = False;
8901 int i;
8902 double t;
8903 if (strequal(name,"ALL")) {
8904 for (i=0;torture_ops[i].name;i++) {
8905 run_test(torture_ops[i].name);
8907 found = True;
8910 for (i=0;torture_ops[i].name;i++) {
8911 fstr_sprintf(randomfname, "\\XX%x",
8912 (unsigned)random());
8914 if (strequal(name, torture_ops[i].name)) {
8915 found = True;
8916 printf("Running %s\n", name);
8917 if (torture_ops[i].flags & FLAG_MULTIPROC) {
8918 t = create_procs(torture_ops[i].fn, &result);
8919 if (!result) {
8920 ret = False;
8921 printf("TEST %s FAILED!\n", name);
8923 } else {
8924 struct timeval start;
8925 start = timeval_current();
8926 if (!torture_ops[i].fn(0)) {
8927 ret = False;
8928 printf("TEST %s FAILED!\n", name);
8930 t = timeval_elapsed(&start);
8932 printf("%s took %g secs\n\n", name, t);
8936 if (!found) {
8937 printf("Did not find a test named %s\n", name);
8938 ret = False;
8941 return ret;
8945 static void usage(void)
8947 int i;
8949 printf("WARNING samba4 test suite is much more complete nowadays.\n");
8950 printf("Please use samba4 torture.\n\n");
8952 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
8954 printf("\t-d debuglevel\n");
8955 printf("\t-U user%%pass\n");
8956 printf("\t-k use kerberos\n");
8957 printf("\t-N numprocs\n");
8958 printf("\t-n my_netbios_name\n");
8959 printf("\t-W workgroup\n");
8960 printf("\t-o num_operations\n");
8961 printf("\t-O socket_options\n");
8962 printf("\t-m maximum protocol\n");
8963 printf("\t-L use oplocks\n");
8964 printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
8965 printf("\t-A showall\n");
8966 printf("\t-p port\n");
8967 printf("\t-s seed\n");
8968 printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
8969 printf("\t-f filename filename to test\n");
8970 printf("\n\n");
8972 printf("tests are:");
8973 for (i=0;torture_ops[i].name;i++) {
8974 printf(" %s", torture_ops[i].name);
8976 printf("\n");
8978 printf("default test is ALL\n");
8980 exit(1);
8983 /****************************************************************************
8984 main program
8985 ****************************************************************************/
8986 int main(int argc,char *argv[])
8988 int opt, i;
8989 char *p;
8990 int gotuser = 0;
8991 int gotpass = 0;
8992 bool correct = True;
8993 TALLOC_CTX *frame = talloc_stackframe();
8994 int seed = time(NULL);
8996 #ifdef HAVE_SETBUFFER
8997 setbuffer(stdout, NULL, 0);
8998 #endif
9000 setup_logging("smbtorture", DEBUG_STDOUT);
9002 load_case_tables();
9004 if (is_default_dyn_CONFIGFILE()) {
9005 if(getenv("SMB_CONF_PATH")) {
9006 set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
9009 lp_load_global(get_dyn_CONFIGFILE());
9010 load_interfaces();
9012 if (argc < 2) {
9013 usage();
9016 for(p = argv[1]; *p; p++)
9017 if(*p == '\\')
9018 *p = '/';
9020 if (strncmp(argv[1], "//", 2)) {
9021 usage();
9024 fstrcpy(host, &argv[1][2]);
9025 p = strchr_m(&host[2],'/');
9026 if (!p) {
9027 usage();
9029 *p = 0;
9030 fstrcpy(share, p+1);
9032 fstrcpy(myname, get_myname(talloc_tos()));
9033 if (!*myname) {
9034 fprintf(stderr, "Failed to get my hostname.\n");
9035 return 1;
9038 if (*username == 0 && getenv("LOGNAME")) {
9039 fstrcpy(username,getenv("LOGNAME"));
9042 argc--;
9043 argv++;
9045 fstrcpy(workgroup, lp_workgroup());
9047 while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
9048 != EOF) {
9049 switch (opt) {
9050 case 'p':
9051 port_to_use = atoi(optarg);
9052 break;
9053 case 's':
9054 seed = atoi(optarg);
9055 break;
9056 case 'W':
9057 fstrcpy(workgroup,optarg);
9058 break;
9059 case 'm':
9060 max_protocol = interpret_protocol(optarg, max_protocol);
9061 break;
9062 case 'N':
9063 nprocs = atoi(optarg);
9064 break;
9065 case 'o':
9066 torture_numops = atoi(optarg);
9067 break;
9068 case 'd':
9069 lp_set_cmdline("log level", optarg);
9070 break;
9071 case 'O':
9072 sockops = optarg;
9073 break;
9074 case 'L':
9075 use_oplocks = True;
9076 break;
9077 case 'l':
9078 local_path = optarg;
9079 break;
9080 case 'A':
9081 torture_showall = True;
9082 break;
9083 case 'n':
9084 fstrcpy(myname, optarg);
9085 break;
9086 case 'c':
9087 client_txt = optarg;
9088 break;
9089 case 'e':
9090 do_encrypt = true;
9091 break;
9092 case 'k':
9093 #ifdef HAVE_KRB5
9094 use_kerberos = True;
9095 #else
9096 d_printf("No kerberos support compiled in\n");
9097 exit(1);
9098 #endif
9099 break;
9100 case 'U':
9101 gotuser = 1;
9102 fstrcpy(username,optarg);
9103 p = strchr_m(username,'%');
9104 if (p) {
9105 *p = 0;
9106 fstrcpy(password, p+1);
9107 gotpass = 1;
9109 break;
9110 case 'b':
9111 fstrcpy(multishare_conn_fname, optarg);
9112 use_multishare_conn = True;
9113 break;
9114 case 'B':
9115 torture_blocksize = atoi(optarg);
9116 break;
9117 case 'f':
9118 test_filename = SMB_STRDUP(optarg);
9119 break;
9120 default:
9121 printf("Unknown option %c (%d)\n", (char)opt, opt);
9122 usage();
9126 d_printf("using seed %d\n", seed);
9128 srandom(seed);
9130 if(use_kerberos && !gotuser) gotpass = True;
9132 while (!gotpass) {
9133 p = getpass("Password:");
9134 if (p) {
9135 fstrcpy(password, p);
9136 gotpass = 1;
9140 printf("host=%s share=%s user=%s myname=%s\n",
9141 host, share, username, myname);
9143 if (argc == optind) {
9144 correct = run_test("ALL");
9145 } else {
9146 for (i=optind;i<argc;i++) {
9147 if (!run_test(argv[i])) {
9148 correct = False;
9153 TALLOC_FREE(frame);
9155 if (correct) {
9156 return(0);
9157 } else {
9158 return(1);