s3: Make torture_nprocs globally available
[Samba/gbeck.git] / source3 / torture / torture.c
blob0a951eb37a046a7817dfbb3b61eac38d3895999d
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 int torture_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_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
614 DENY_NONE, &fnum2);
615 if (!NT_STATUS_IS_OK(status)) {
616 status = cli_openx(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_openx(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_openx(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_openx(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_openx(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_openx(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 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_openx(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_openx(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(torture_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_openx(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_openx(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_openx(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_openx(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_tree_connect(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_tree_connect(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(status, expected_error)) {
1557 ret = True;
1558 } else {
1559 printf("Returned unexpected error\n");
1560 ret = False;
1564 return ret;
1568 checks for correct tconX support
1570 static bool run_tcon_devtype_test(int dummy)
1572 static struct cli_state *cli1 = NULL;
1573 int flags = 0;
1574 NTSTATUS status;
1575 bool ret = True;
1577 status = cli_full_connection(&cli1, myname,
1578 host, NULL, port_to_use,
1579 NULL, NULL,
1580 username, workgroup,
1581 password, flags, signing_state);
1583 if (!NT_STATUS_IS_OK(status)) {
1584 printf("could not open connection\n");
1585 return False;
1588 if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1589 ret = False;
1591 if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1592 ret = False;
1594 if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1595 ret = False;
1597 if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1598 ret = False;
1600 if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1601 ret = False;
1603 if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1604 ret = False;
1606 if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1607 ret = False;
1609 if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1610 ret = False;
1612 if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1613 ret = False;
1615 if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1616 ret = False;
1618 cli_shutdown(cli1);
1620 if (ret)
1621 printf("Passed tcondevtest\n");
1623 return ret;
1628 This test checks that
1630 1) the server supports multiple locking contexts on the one SMB
1631 connection, distinguished by PID.
1633 2) the server correctly fails overlapping locks made by the same PID (this
1634 goes against POSIX behaviour, which is why it is tricky to implement)
1636 3) the server denies unlock requests by an incorrect client PID
1638 static bool run_locktest2(int dummy)
1640 static struct cli_state *cli;
1641 const char *fname = "\\lockt2.lck";
1642 uint16_t fnum1, fnum2, fnum3;
1643 bool correct = True;
1644 NTSTATUS status;
1646 if (!torture_open_connection(&cli, 0)) {
1647 return False;
1650 cli_sockopt(cli, sockops);
1652 printf("starting locktest2\n");
1654 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1656 cli_setpid(cli, 1);
1658 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1659 if (!NT_STATUS_IS_OK(status)) {
1660 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1661 return False;
1664 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1665 if (!NT_STATUS_IS_OK(status)) {
1666 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1667 return False;
1670 cli_setpid(cli, 2);
1672 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1673 if (!NT_STATUS_IS_OK(status)) {
1674 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1675 return False;
1678 cli_setpid(cli, 1);
1680 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1681 if (!NT_STATUS_IS_OK(status)) {
1682 printf("lock1 failed (%s)\n", nt_errstr(status));
1683 return false;
1686 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1687 if (NT_STATUS_IS_OK(status)) {
1688 printf("WRITE lock1 succeeded! This is a locking bug\n");
1689 correct = false;
1690 } else {
1691 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1692 NT_STATUS_LOCK_NOT_GRANTED)) {
1693 return false;
1697 status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1698 if (NT_STATUS_IS_OK(status)) {
1699 printf("WRITE lock2 succeeded! This is a locking bug\n");
1700 correct = false;
1701 } else {
1702 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1703 NT_STATUS_LOCK_NOT_GRANTED)) {
1704 return false;
1708 status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1709 if (NT_STATUS_IS_OK(status)) {
1710 printf("READ lock2 succeeded! This is a locking bug\n");
1711 correct = false;
1712 } else {
1713 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1714 NT_STATUS_FILE_LOCK_CONFLICT)) {
1715 return false;
1719 status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1720 if (!NT_STATUS_IS_OK(status)) {
1721 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1723 cli_setpid(cli, 2);
1724 if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1725 printf("unlock at 100 succeeded! This is a locking bug\n");
1726 correct = False;
1729 status = cli_unlock(cli, fnum1, 0, 4);
1730 if (NT_STATUS_IS_OK(status)) {
1731 printf("unlock1 succeeded! This is a locking bug\n");
1732 correct = false;
1733 } else {
1734 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1735 NT_STATUS_RANGE_NOT_LOCKED)) {
1736 return false;
1740 status = cli_unlock(cli, fnum1, 0, 8);
1741 if (NT_STATUS_IS_OK(status)) {
1742 printf("unlock2 succeeded! This is a locking bug\n");
1743 correct = false;
1744 } else {
1745 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1746 NT_STATUS_RANGE_NOT_LOCKED)) {
1747 return false;
1751 status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1752 if (NT_STATUS_IS_OK(status)) {
1753 printf("lock3 succeeded! This is a locking bug\n");
1754 correct = false;
1755 } else {
1756 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1757 NT_STATUS_LOCK_NOT_GRANTED)) {
1758 return false;
1762 cli_setpid(cli, 1);
1764 status = cli_close(cli, fnum1);
1765 if (!NT_STATUS_IS_OK(status)) {
1766 printf("close1 failed (%s)\n", nt_errstr(status));
1767 return False;
1770 status = cli_close(cli, fnum2);
1771 if (!NT_STATUS_IS_OK(status)) {
1772 printf("close2 failed (%s)\n", nt_errstr(status));
1773 return False;
1776 status = cli_close(cli, fnum3);
1777 if (!NT_STATUS_IS_OK(status)) {
1778 printf("close3 failed (%s)\n", nt_errstr(status));
1779 return False;
1782 if (!torture_close_connection(cli)) {
1783 correct = False;
1786 printf("locktest2 finished\n");
1788 return correct;
1793 This test checks that
1795 1) the server supports the full offset range in lock requests
1797 static bool run_locktest3(int dummy)
1799 static struct cli_state *cli1, *cli2;
1800 const char *fname = "\\lockt3.lck";
1801 uint16_t fnum1, fnum2;
1802 int i;
1803 uint32 offset;
1804 bool correct = True;
1805 NTSTATUS status;
1807 #define NEXT_OFFSET offset += (~(uint32)0) / torture_numops
1809 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1810 return False;
1812 cli_sockopt(cli1, sockops);
1813 cli_sockopt(cli2, sockops);
1815 printf("starting locktest3\n");
1817 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1819 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1820 &fnum1);
1821 if (!NT_STATUS_IS_OK(status)) {
1822 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1823 return False;
1826 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1827 if (!NT_STATUS_IS_OK(status)) {
1828 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1829 return False;
1832 for (offset=i=0;i<torture_numops;i++) {
1833 NEXT_OFFSET;
1835 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1836 if (!NT_STATUS_IS_OK(status)) {
1837 printf("lock1 %d failed (%s)\n",
1839 nt_errstr(status));
1840 return False;
1843 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1844 if (!NT_STATUS_IS_OK(status)) {
1845 printf("lock2 %d failed (%s)\n",
1847 nt_errstr(status));
1848 return False;
1852 for (offset=i=0;i<torture_numops;i++) {
1853 NEXT_OFFSET;
1855 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1856 if (NT_STATUS_IS_OK(status)) {
1857 printf("error: lock1 %d succeeded!\n", i);
1858 return False;
1861 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1862 if (NT_STATUS_IS_OK(status)) {
1863 printf("error: lock2 %d succeeded!\n", i);
1864 return False;
1867 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1868 if (NT_STATUS_IS_OK(status)) {
1869 printf("error: lock3 %d succeeded!\n", i);
1870 return False;
1873 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1874 if (NT_STATUS_IS_OK(status)) {
1875 printf("error: lock4 %d succeeded!\n", i);
1876 return False;
1880 for (offset=i=0;i<torture_numops;i++) {
1881 NEXT_OFFSET;
1883 status = cli_unlock(cli1, fnum1, offset-1, 1);
1884 if (!NT_STATUS_IS_OK(status)) {
1885 printf("unlock1 %d failed (%s)\n",
1887 nt_errstr(status));
1888 return False;
1891 status = cli_unlock(cli2, fnum2, offset-2, 1);
1892 if (!NT_STATUS_IS_OK(status)) {
1893 printf("unlock2 %d failed (%s)\n",
1895 nt_errstr(status));
1896 return False;
1900 status = cli_close(cli1, fnum1);
1901 if (!NT_STATUS_IS_OK(status)) {
1902 printf("close1 failed (%s)\n", nt_errstr(status));
1903 return False;
1906 status = cli_close(cli2, fnum2);
1907 if (!NT_STATUS_IS_OK(status)) {
1908 printf("close2 failed (%s)\n", nt_errstr(status));
1909 return False;
1912 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1913 if (!NT_STATUS_IS_OK(status)) {
1914 printf("unlink failed (%s)\n", nt_errstr(status));
1915 return False;
1918 if (!torture_close_connection(cli1)) {
1919 correct = False;
1922 if (!torture_close_connection(cli2)) {
1923 correct = False;
1926 printf("finished locktest3\n");
1928 return correct;
1931 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
1932 char *buf, off_t offset, size_t size,
1933 size_t *nread, size_t expect)
1935 NTSTATUS status;
1936 size_t l_nread;
1938 status = cli_read(cli, fnum, buf, offset, size, &l_nread);
1940 if(!NT_STATUS_IS_OK(status)) {
1941 return false;
1942 } else if (l_nread != expect) {
1943 return false;
1946 if (nread) {
1947 *nread = l_nread;
1950 return true;
1953 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1954 printf("** "); correct = False; \
1958 looks at overlapping locks
1960 static bool run_locktest4(int dummy)
1962 static struct cli_state *cli1, *cli2;
1963 const char *fname = "\\lockt4.lck";
1964 uint16_t fnum1, fnum2, f;
1965 bool ret;
1966 char buf[1000];
1967 bool correct = True;
1968 NTSTATUS status;
1970 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1971 return False;
1974 cli_sockopt(cli1, sockops);
1975 cli_sockopt(cli2, sockops);
1977 printf("starting locktest4\n");
1979 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1981 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1982 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1984 memset(buf, 0, sizeof(buf));
1986 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
1987 NULL);
1988 if (!NT_STATUS_IS_OK(status)) {
1989 printf("Failed to create file: %s\n", nt_errstr(status));
1990 correct = False;
1991 goto fail;
1994 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1995 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
1996 EXPECTED(ret, False);
1997 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1999 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
2000 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
2001 EXPECTED(ret, True);
2002 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
2004 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
2005 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
2006 EXPECTED(ret, False);
2007 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
2009 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
2010 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
2011 EXPECTED(ret, True);
2012 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
2014 ret = (cli_setpid(cli1, 1),
2015 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
2016 (cli_setpid(cli1, 2),
2017 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
2018 EXPECTED(ret, False);
2019 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
2021 ret = (cli_setpid(cli1, 1),
2022 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
2023 (cli_setpid(cli1, 2),
2024 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
2025 EXPECTED(ret, True);
2026 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
2028 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
2029 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
2030 EXPECTED(ret, True);
2031 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
2033 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
2034 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
2035 EXPECTED(ret, False);
2036 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
2038 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
2039 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
2040 EXPECTED(ret, False);
2041 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
2043 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
2044 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2045 EXPECTED(ret, True);
2046 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2048 ret = (cli_setpid(cli1, 1),
2049 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2050 (cli_setpid(cli1, 2),
2051 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2052 EXPECTED(ret, False);
2053 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2055 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2056 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2057 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2058 EXPECTED(ret, False);
2059 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2062 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2063 test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2064 EXPECTED(ret, False);
2065 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2067 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2068 ret = NT_STATUS_IS_OK(status);
2069 if (ret) {
2070 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2071 NULL);
2072 ret = NT_STATUS_IS_OK(status);
2074 EXPECTED(ret, False);
2075 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2078 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2079 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2080 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2081 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2082 EXPECTED(ret, True);
2083 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2086 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2087 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2088 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2089 test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2090 !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2091 150, 4, NULL))) &&
2092 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2093 EXPECTED(ret, True);
2094 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2096 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2097 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2098 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2099 160, 4, NULL)) &&
2100 test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2101 EXPECTED(ret, True);
2102 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2104 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2105 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2106 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2107 170, 4, NULL)) &&
2108 test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2109 EXPECTED(ret, True);
2110 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2112 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2113 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2114 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2115 !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2116 190, 4, NULL)) &&
2117 test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2118 EXPECTED(ret, True);
2119 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2121 cli_close(cli1, fnum1);
2122 cli_close(cli2, fnum2);
2123 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2124 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2125 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2126 NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2127 NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2128 NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2129 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2130 cli_close(cli1, f);
2131 cli_close(cli1, fnum1);
2132 EXPECTED(ret, True);
2133 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2135 fail:
2136 cli_close(cli1, fnum1);
2137 cli_close(cli2, fnum2);
2138 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2139 torture_close_connection(cli1);
2140 torture_close_connection(cli2);
2142 printf("finished locktest4\n");
2143 return correct;
2147 looks at lock upgrade/downgrade.
2149 static bool run_locktest5(int dummy)
2151 static struct cli_state *cli1, *cli2;
2152 const char *fname = "\\lockt5.lck";
2153 uint16_t fnum1, fnum2, fnum3;
2154 bool ret;
2155 char buf[1000];
2156 bool correct = True;
2157 NTSTATUS status;
2159 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2160 return False;
2163 cli_sockopt(cli1, sockops);
2164 cli_sockopt(cli2, sockops);
2166 printf("starting locktest5\n");
2168 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2170 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2171 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2172 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2174 memset(buf, 0, sizeof(buf));
2176 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2177 NULL);
2178 if (!NT_STATUS_IS_OK(status)) {
2179 printf("Failed to create file: %s\n", nt_errstr(status));
2180 correct = False;
2181 goto fail;
2184 /* Check for NT bug... */
2185 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2186 NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2187 cli_close(cli1, fnum1);
2188 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2189 status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2190 ret = NT_STATUS_IS_OK(status);
2191 EXPECTED(ret, True);
2192 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2193 cli_close(cli1, fnum1);
2194 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2195 cli_unlock(cli1, fnum3, 0, 1);
2197 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2198 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2199 EXPECTED(ret, True);
2200 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2202 status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2203 ret = NT_STATUS_IS_OK(status);
2204 EXPECTED(ret, False);
2206 printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2208 /* Unlock the process 2 lock. */
2209 cli_unlock(cli2, fnum2, 0, 4);
2211 status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2212 ret = NT_STATUS_IS_OK(status);
2213 EXPECTED(ret, False);
2215 printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
2217 /* Unlock the process 1 fnum3 lock. */
2218 cli_unlock(cli1, fnum3, 0, 4);
2220 /* Stack 2 more locks here. */
2221 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2222 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2224 EXPECTED(ret, True);
2225 printf("the same process %s stack read locks\n", ret?"can":"cannot");
2227 /* Unlock the first process lock, then check this was the WRITE lock that was
2228 removed. */
2230 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2231 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2233 EXPECTED(ret, True);
2234 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2236 /* Unlock the process 2 lock. */
2237 cli_unlock(cli2, fnum2, 0, 4);
2239 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2241 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2242 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2243 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2245 EXPECTED(ret, True);
2246 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2248 /* Ensure the next unlock fails. */
2249 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2250 EXPECTED(ret, False);
2251 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2253 /* Ensure connection 2 can get a write lock. */
2254 status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2255 ret = NT_STATUS_IS_OK(status);
2256 EXPECTED(ret, True);
2258 printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2261 fail:
2262 cli_close(cli1, fnum1);
2263 cli_close(cli2, fnum2);
2264 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2265 if (!torture_close_connection(cli1)) {
2266 correct = False;
2268 if (!torture_close_connection(cli2)) {
2269 correct = False;
2272 printf("finished locktest5\n");
2274 return correct;
2278 tries the unusual lockingX locktype bits
2280 static bool run_locktest6(int dummy)
2282 static struct cli_state *cli;
2283 const char *fname[1] = { "\\lock6.txt" };
2284 int i;
2285 uint16_t fnum;
2286 NTSTATUS status;
2288 if (!torture_open_connection(&cli, 0)) {
2289 return False;
2292 cli_sockopt(cli, sockops);
2294 printf("starting locktest6\n");
2296 for (i=0;i<1;i++) {
2297 printf("Testing %s\n", fname[i]);
2299 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2301 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2302 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2303 cli_close(cli, fnum);
2304 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2306 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2307 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2308 cli_close(cli, fnum);
2309 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2311 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2314 torture_close_connection(cli);
2316 printf("finished locktest6\n");
2317 return True;
2320 static bool run_locktest7(int dummy)
2322 struct cli_state *cli1;
2323 const char *fname = "\\lockt7.lck";
2324 uint16_t fnum1;
2325 char buf[200];
2326 bool correct = False;
2327 size_t nread;
2328 NTSTATUS status;
2330 if (!torture_open_connection(&cli1, 0)) {
2331 return False;
2334 cli_sockopt(cli1, sockops);
2336 printf("starting locktest7\n");
2338 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2340 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2342 memset(buf, 0, sizeof(buf));
2344 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2345 NULL);
2346 if (!NT_STATUS_IS_OK(status)) {
2347 printf("Failed to create file: %s\n", nt_errstr(status));
2348 goto fail;
2351 cli_setpid(cli1, 1);
2353 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2354 if (!NT_STATUS_IS_OK(status)) {
2355 printf("Unable to apply read lock on range 130:4, "
2356 "error was %s\n", nt_errstr(status));
2357 goto fail;
2358 } else {
2359 printf("pid1 successfully locked range 130:4 for READ\n");
2362 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2363 if (!NT_STATUS_IS_OK(status)) {
2364 printf("pid1 unable to read the range 130:4, error was %s\n",
2365 nt_errstr(status));
2366 goto fail;
2367 } else if (nread != 4) {
2368 printf("pid1 unable to read the range 130:4, "
2369 "recv %ld req %d\n", (unsigned long)nread, 4);
2370 goto fail;
2371 } else {
2372 printf("pid1 successfully read the range 130:4\n");
2375 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2376 if (!NT_STATUS_IS_OK(status)) {
2377 printf("pid1 unable to write to the range 130:4, error was "
2378 "%s\n", nt_errstr(status));
2379 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2380 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2381 goto fail;
2383 } else {
2384 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2385 goto fail;
2388 cli_setpid(cli1, 2);
2390 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2391 if (!NT_STATUS_IS_OK(status)) {
2392 printf("pid2 unable to read the range 130:4, error was %s\n",
2393 nt_errstr(status));
2394 goto fail;
2395 } else if (nread != 4) {
2396 printf("pid2 unable to read the range 130:4, "
2397 "recv %ld req %d\n", (unsigned long)nread, 4);
2398 goto fail;
2399 } else {
2400 printf("pid2 successfully read the range 130:4\n");
2403 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2404 if (!NT_STATUS_IS_OK(status)) {
2405 printf("pid2 unable to write to the range 130:4, error was "
2406 "%s\n", nt_errstr(status));
2407 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2408 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2409 goto fail;
2411 } else {
2412 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2413 goto fail;
2416 cli_setpid(cli1, 1);
2417 cli_unlock(cli1, fnum1, 130, 4);
2419 status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2420 if (!NT_STATUS_IS_OK(status)) {
2421 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2422 goto fail;
2423 } else {
2424 printf("pid1 successfully locked range 130:4 for WRITE\n");
2427 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2428 if (!NT_STATUS_IS_OK(status)) {
2429 printf("pid1 unable to read the range 130:4, error was %s\n",
2430 nt_errstr(status));
2431 goto fail;
2432 } else if (nread != 4) {
2433 printf("pid1 unable to read the range 130:4, "
2434 "recv %ld req %d\n", (unsigned long)nread, 4);
2435 goto fail;
2436 } else {
2437 printf("pid1 successfully read the range 130:4\n");
2440 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2441 if (!NT_STATUS_IS_OK(status)) {
2442 printf("pid1 unable to write to the range 130:4, error was "
2443 "%s\n", nt_errstr(status));
2444 goto fail;
2445 } else {
2446 printf("pid1 successfully wrote to the range 130:4\n");
2449 cli_setpid(cli1, 2);
2451 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2452 if (!NT_STATUS_IS_OK(status)) {
2453 printf("pid2 unable to read the range 130:4, error was "
2454 "%s\n", nt_errstr(status));
2455 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2456 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2457 goto fail;
2459 } else {
2460 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2461 (unsigned long)nread);
2462 goto fail;
2465 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2466 if (!NT_STATUS_IS_OK(status)) {
2467 printf("pid2 unable to write to the range 130:4, error was "
2468 "%s\n", nt_errstr(status));
2469 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2470 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2471 goto fail;
2473 } else {
2474 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2475 goto fail;
2478 cli_unlock(cli1, fnum1, 130, 0);
2479 correct = True;
2481 fail:
2482 cli_close(cli1, fnum1);
2483 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2484 torture_close_connection(cli1);
2486 printf("finished locktest7\n");
2487 return correct;
2491 * This demonstrates a problem with our use of GPFS share modes: A file
2492 * descriptor sitting in the pending close queue holding a GPFS share mode
2493 * blocks opening a file another time. Happens with Word 2007 temp files.
2494 * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2495 * open is denied with NT_STATUS_SHARING_VIOLATION.
2498 static bool run_locktest8(int dummy)
2500 struct cli_state *cli1;
2501 const char *fname = "\\lockt8.lck";
2502 uint16_t fnum1, fnum2;
2503 char buf[200];
2504 bool correct = False;
2505 NTSTATUS status;
2507 if (!torture_open_connection(&cli1, 0)) {
2508 return False;
2511 cli_sockopt(cli1, sockops);
2513 printf("starting locktest8\n");
2515 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2517 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2518 &fnum1);
2519 if (!NT_STATUS_IS_OK(status)) {
2520 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2521 return false;
2524 memset(buf, 0, sizeof(buf));
2526 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2527 if (!NT_STATUS_IS_OK(status)) {
2528 d_fprintf(stderr, "cli_openx second time returned %s\n",
2529 nt_errstr(status));
2530 goto fail;
2533 status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2534 if (!NT_STATUS_IS_OK(status)) {
2535 printf("Unable to apply read lock on range 1:1, error was "
2536 "%s\n", nt_errstr(status));
2537 goto fail;
2540 status = cli_close(cli1, fnum1);
2541 if (!NT_STATUS_IS_OK(status)) {
2542 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2543 goto fail;
2546 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2547 if (!NT_STATUS_IS_OK(status)) {
2548 d_fprintf(stderr, "cli_openx third time returned %s\n",
2549 nt_errstr(status));
2550 goto fail;
2553 correct = true;
2555 fail:
2556 cli_close(cli1, fnum1);
2557 cli_close(cli1, fnum2);
2558 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2559 torture_close_connection(cli1);
2561 printf("finished locktest8\n");
2562 return correct;
2566 * This test is designed to be run in conjunction with
2567 * external NFS or POSIX locks taken in the filesystem.
2568 * It checks that the smbd server will block until the
2569 * lock is released and then acquire it. JRA.
2572 static bool got_alarm;
2573 static struct cli_state *alarm_cli;
2575 static void alarm_handler(int dummy)
2577 got_alarm = True;
2580 static void alarm_handler_parent(int dummy)
2582 cli_state_disconnect(alarm_cli);
2585 static void do_local_lock(int read_fd, int write_fd)
2587 int fd;
2588 char c = '\0';
2589 struct flock lock;
2590 const char *local_pathname = NULL;
2591 int ret;
2593 local_pathname = talloc_asprintf(talloc_tos(),
2594 "%s/lockt9.lck", local_path);
2595 if (!local_pathname) {
2596 printf("child: alloc fail\n");
2597 exit(1);
2600 unlink(local_pathname);
2601 fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2602 if (fd == -1) {
2603 printf("child: open of %s failed %s.\n",
2604 local_pathname, strerror(errno));
2605 exit(1);
2608 /* Now take a fcntl lock. */
2609 lock.l_type = F_WRLCK;
2610 lock.l_whence = SEEK_SET;
2611 lock.l_start = 0;
2612 lock.l_len = 4;
2613 lock.l_pid = getpid();
2615 ret = fcntl(fd,F_SETLK,&lock);
2616 if (ret == -1) {
2617 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2618 local_pathname, strerror(errno));
2619 exit(1);
2620 } else {
2621 printf("child: got lock 0:4 on file %s.\n",
2622 local_pathname );
2623 fflush(stdout);
2626 CatchSignal(SIGALRM, alarm_handler);
2627 alarm(5);
2628 /* Signal the parent. */
2629 if (write(write_fd, &c, 1) != 1) {
2630 printf("child: start signal fail %s.\n",
2631 strerror(errno));
2632 exit(1);
2634 alarm(0);
2636 alarm(10);
2637 /* Wait for the parent to be ready. */
2638 if (read(read_fd, &c, 1) != 1) {
2639 printf("child: reply signal fail %s.\n",
2640 strerror(errno));
2641 exit(1);
2643 alarm(0);
2645 sleep(5);
2646 close(fd);
2647 printf("child: released lock 0:4 on file %s.\n",
2648 local_pathname );
2649 fflush(stdout);
2650 exit(0);
2653 static bool run_locktest9(int dummy)
2655 struct cli_state *cli1;
2656 const char *fname = "\\lockt9.lck";
2657 uint16_t fnum;
2658 bool correct = False;
2659 int pipe_in[2], pipe_out[2];
2660 pid_t child_pid;
2661 char c = '\0';
2662 int ret;
2663 struct timeval start;
2664 double seconds;
2665 NTSTATUS status;
2667 printf("starting locktest9\n");
2669 if (local_path == NULL) {
2670 d_fprintf(stderr, "locktest9 must be given a local path via -l <localpath>\n");
2671 return false;
2674 if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2675 return false;
2678 child_pid = fork();
2679 if (child_pid == -1) {
2680 return false;
2683 if (child_pid == 0) {
2684 /* Child. */
2685 do_local_lock(pipe_out[0], pipe_in[1]);
2686 exit(0);
2689 close(pipe_out[0]);
2690 close(pipe_in[1]);
2691 pipe_out[0] = -1;
2692 pipe_in[1] = -1;
2694 /* Parent. */
2695 ret = read(pipe_in[0], &c, 1);
2696 if (ret != 1) {
2697 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2698 strerror(errno));
2699 return false;
2702 if (!torture_open_connection(&cli1, 0)) {
2703 return false;
2706 cli_sockopt(cli1, sockops);
2708 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE,
2709 &fnum);
2710 if (!NT_STATUS_IS_OK(status)) {
2711 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2712 return false;
2715 /* Ensure the child has the lock. */
2716 status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2717 if (NT_STATUS_IS_OK(status)) {
2718 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2719 goto fail;
2720 } else {
2721 d_printf("Child has the lock.\n");
2724 /* Tell the child to wait 5 seconds then exit. */
2725 ret = write(pipe_out[1], &c, 1);
2726 if (ret != 1) {
2727 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2728 strerror(errno));
2729 goto fail;
2732 /* Wait 20 seconds for the lock. */
2733 alarm_cli = cli1;
2734 CatchSignal(SIGALRM, alarm_handler_parent);
2735 alarm(20);
2737 start = timeval_current();
2739 status = cli_lock32(cli1, fnum, 0, 4, -1, WRITE_LOCK);
2740 if (!NT_STATUS_IS_OK(status)) {
2741 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2742 "%s\n", nt_errstr(status));
2743 goto fail_nofd;
2745 alarm(0);
2747 seconds = timeval_elapsed(&start);
2749 printf("Parent got the lock after %.2f seconds.\n",
2750 seconds);
2752 status = cli_close(cli1, fnum);
2753 if (!NT_STATUS_IS_OK(status)) {
2754 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2755 goto fail;
2758 correct = true;
2760 fail:
2761 cli_close(cli1, fnum);
2762 torture_close_connection(cli1);
2764 fail_nofd:
2766 printf("finished locktest9\n");
2767 return correct;
2771 test whether fnums and tids open on one VC are available on another (a major
2772 security hole)
2774 static bool run_fdpasstest(int dummy)
2776 struct cli_state *cli1, *cli2;
2777 const char *fname = "\\fdpass.tst";
2778 uint16_t fnum1;
2779 char buf[1024];
2780 NTSTATUS status;
2782 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2783 return False;
2785 cli_sockopt(cli1, sockops);
2786 cli_sockopt(cli2, sockops);
2788 printf("starting fdpasstest\n");
2790 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2792 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
2793 &fnum1);
2794 if (!NT_STATUS_IS_OK(status)) {
2795 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2796 return False;
2799 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
2800 13, NULL);
2801 if (!NT_STATUS_IS_OK(status)) {
2802 printf("write failed (%s)\n", nt_errstr(status));
2803 return False;
2806 cli_state_set_uid(cli2, cli_state_get_uid(cli1));
2807 cli_state_set_tid(cli2, cli_state_get_tid(cli1));
2808 cli_setpid(cli2, cli_getpid(cli1));
2810 if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
2811 printf("read succeeded! nasty security hole [%s]\n", buf);
2812 return false;
2815 cli_close(cli1, fnum1);
2816 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2818 torture_close_connection(cli1);
2819 torture_close_connection(cli2);
2821 printf("finished fdpasstest\n");
2822 return True;
2825 static bool run_fdsesstest(int dummy)
2827 struct cli_state *cli;
2828 uint16 new_vuid;
2829 uint16 saved_vuid;
2830 uint16 new_cnum;
2831 uint16 saved_cnum;
2832 const char *fname = "\\fdsess.tst";
2833 const char *fname1 = "\\fdsess1.tst";
2834 uint16_t fnum1;
2835 uint16_t fnum2;
2836 char buf[1024];
2837 bool ret = True;
2838 NTSTATUS status;
2840 if (!torture_open_connection(&cli, 0))
2841 return False;
2842 cli_sockopt(cli, sockops);
2844 if (!torture_cli_session_setup2(cli, &new_vuid))
2845 return False;
2847 saved_cnum = cli_state_get_tid(cli);
2848 if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", "", 1)))
2849 return False;
2850 new_cnum = cli_state_get_tid(cli);
2851 cli_state_set_tid(cli, saved_cnum);
2853 printf("starting fdsesstest\n");
2855 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2856 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2858 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2859 if (!NT_STATUS_IS_OK(status)) {
2860 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2861 return False;
2864 status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
2865 NULL);
2866 if (!NT_STATUS_IS_OK(status)) {
2867 printf("write failed (%s)\n", nt_errstr(status));
2868 return False;
2871 saved_vuid = cli_state_get_uid(cli);
2872 cli_state_set_uid(cli, new_vuid);
2874 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2875 printf("read succeeded with different vuid! "
2876 "nasty security hole [%s]\n", buf);
2877 ret = false;
2879 /* Try to open a file with different vuid, samba cnum. */
2880 if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
2881 printf("create with different vuid, same cnum succeeded.\n");
2882 cli_close(cli, fnum2);
2883 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2884 } else {
2885 printf("create with different vuid, same cnum failed.\n");
2886 printf("This will cause problems with service clients.\n");
2887 ret = False;
2890 cli_state_set_uid(cli, saved_vuid);
2892 /* Try with same vuid, different cnum. */
2893 cli_state_set_tid(cli, new_cnum);
2895 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2896 printf("read succeeded with different cnum![%s]\n", buf);
2897 ret = false;
2900 cli_state_set_tid(cli, saved_cnum);
2901 cli_close(cli, fnum1);
2902 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2904 torture_close_connection(cli);
2906 printf("finished fdsesstest\n");
2907 return ret;
2911 This test checks that
2913 1) the server does not allow an unlink on a file that is open
2915 static bool run_unlinktest(int dummy)
2917 struct cli_state *cli;
2918 const char *fname = "\\unlink.tst";
2919 uint16_t fnum;
2920 bool correct = True;
2921 NTSTATUS status;
2923 if (!torture_open_connection(&cli, 0)) {
2924 return False;
2927 cli_sockopt(cli, sockops);
2929 printf("starting unlink test\n");
2931 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2933 cli_setpid(cli, 1);
2935 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2936 if (!NT_STATUS_IS_OK(status)) {
2937 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2938 return False;
2941 status = cli_unlink(cli, fname,
2942 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2943 if (NT_STATUS_IS_OK(status)) {
2944 printf("error: server allowed unlink on an open file\n");
2945 correct = False;
2946 } else {
2947 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
2948 NT_STATUS_SHARING_VIOLATION);
2951 cli_close(cli, fnum);
2952 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2954 if (!torture_close_connection(cli)) {
2955 correct = False;
2958 printf("unlink test finished\n");
2960 return correct;
2965 test how many open files this server supports on the one socket
2967 static bool run_maxfidtest(int dummy)
2969 struct cli_state *cli;
2970 fstring fname;
2971 uint16_t fnums[0x11000];
2972 int i;
2973 int retries=4;
2974 bool correct = True;
2975 NTSTATUS status;
2977 cli = current_cli;
2979 if (retries <= 0) {
2980 printf("failed to connect\n");
2981 return False;
2984 cli_sockopt(cli, sockops);
2986 for (i=0; i<0x11000; i++) {
2987 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2988 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
2989 &fnums[i]);
2990 if (!NT_STATUS_IS_OK(status)) {
2991 printf("open of %s failed (%s)\n",
2992 fname, nt_errstr(status));
2993 printf("maximum fnum is %d\n", i);
2994 break;
2996 printf("%6d\r", i);
2998 printf("%6d\n", i);
2999 i--;
3001 printf("cleaning up\n");
3002 for (;i>=0;i--) {
3003 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3004 cli_close(cli, fnums[i]);
3006 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3007 if (!NT_STATUS_IS_OK(status)) {
3008 printf("unlink of %s failed (%s)\n",
3009 fname, nt_errstr(status));
3010 correct = False;
3012 printf("%6d\r", i);
3014 printf("%6d\n", 0);
3016 printf("maxfid test finished\n");
3017 if (!torture_close_connection(cli)) {
3018 correct = False;
3020 return correct;
3023 /* generate a random buffer */
3024 static void rand_buf(char *buf, int len)
3026 while (len--) {
3027 *buf = (char)sys_random();
3028 buf++;
3032 /* send smb negprot commands, not reading the response */
3033 static bool run_negprot_nowait(int dummy)
3035 struct tevent_context *ev;
3036 int i;
3037 struct cli_state *cli;
3038 bool correct = True;
3040 printf("starting negprot nowait test\n");
3042 ev = tevent_context_init(talloc_tos());
3043 if (ev == NULL) {
3044 return false;
3047 if (!(cli = open_nbt_connection())) {
3048 TALLOC_FREE(ev);
3049 return False;
3052 for (i=0;i<50000;i++) {
3053 struct tevent_req *req;
3055 req = cli_negprot_send(ev, ev, cli, PROTOCOL_NT1);
3056 if (req == NULL) {
3057 TALLOC_FREE(ev);
3058 return false;
3060 if (!tevent_req_poll(req, ev)) {
3061 d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3062 strerror(errno));
3063 TALLOC_FREE(ev);
3064 return false;
3066 TALLOC_FREE(req);
3069 if (torture_close_connection(cli)) {
3070 correct = False;
3073 printf("finished negprot nowait test\n");
3075 return correct;
3078 /* send smb negprot commands, not reading the response */
3079 static bool run_bad_nbt_session(int dummy)
3081 struct nmb_name called, calling;
3082 struct sockaddr_storage ss;
3083 NTSTATUS status;
3084 int fd;
3085 bool ret;
3087 printf("starting bad nbt session test\n");
3089 make_nmb_name(&calling, myname, 0x0);
3090 make_nmb_name(&called , host, 0x20);
3092 if (!resolve_name(host, &ss, 0x20, true)) {
3093 d_fprintf(stderr, "Could not resolve name %s\n", host);
3094 return false;
3097 status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
3098 if (!NT_STATUS_IS_OK(status)) {
3099 d_fprintf(stderr, "open_socket_out failed: %s\n",
3100 nt_errstr(status));
3101 return false;
3104 ret = cli_bad_session_request(fd, &calling, &called);
3105 close(fd);
3106 if (!ret) {
3107 d_fprintf(stderr, "open_socket_out failed: %s\n",
3108 nt_errstr(status));
3109 return false;
3112 printf("finished bad nbt session test\n");
3113 return true;
3116 /* send random IPC commands */
3117 static bool run_randomipc(int dummy)
3119 char *rparam = NULL;
3120 char *rdata = NULL;
3121 unsigned int rdrcnt,rprcnt;
3122 char param[1024];
3123 int api, param_len, i;
3124 struct cli_state *cli;
3125 bool correct = True;
3126 int count = 50000;
3128 printf("starting random ipc test\n");
3130 if (!torture_open_connection(&cli, 0)) {
3131 return False;
3134 for (i=0;i<count;i++) {
3135 api = sys_random() % 500;
3136 param_len = (sys_random() % 64);
3138 rand_buf(param, param_len);
3140 SSVAL(param,0,api);
3142 cli_api(cli,
3143 param, param_len, 8,
3144 NULL, 0, BUFFER_SIZE,
3145 &rparam, &rprcnt,
3146 &rdata, &rdrcnt);
3147 if (i % 100 == 0) {
3148 printf("%d/%d\r", i,count);
3151 printf("%d/%d\n", i, count);
3153 if (!torture_close_connection(cli)) {
3154 correct = False;
3157 printf("finished random ipc test\n");
3159 return correct;
3164 static void browse_callback(const char *sname, uint32 stype,
3165 const char *comment, void *state)
3167 printf("\t%20.20s %08x %s\n", sname, stype, comment);
3173 This test checks the browse list code
3176 static bool run_browsetest(int dummy)
3178 static struct cli_state *cli;
3179 bool correct = True;
3181 printf("starting browse test\n");
3183 if (!torture_open_connection(&cli, 0)) {
3184 return False;
3187 printf("domain list:\n");
3188 cli_NetServerEnum(cli, cli->server_domain,
3189 SV_TYPE_DOMAIN_ENUM,
3190 browse_callback, NULL);
3192 printf("machine list:\n");
3193 cli_NetServerEnum(cli, cli->server_domain,
3194 SV_TYPE_ALL,
3195 browse_callback, NULL);
3197 if (!torture_close_connection(cli)) {
3198 correct = False;
3201 printf("browse test finished\n");
3203 return correct;
3209 This checks how the getatr calls works
3211 static bool run_attrtest(int dummy)
3213 struct cli_state *cli;
3214 uint16_t fnum;
3215 time_t t, t2;
3216 const char *fname = "\\attrib123456789.tst";
3217 bool correct = True;
3218 NTSTATUS status;
3220 printf("starting attrib test\n");
3222 if (!torture_open_connection(&cli, 0)) {
3223 return False;
3226 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3227 cli_openx(cli, fname,
3228 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3229 cli_close(cli, fnum);
3231 status = cli_getatr(cli, fname, NULL, NULL, &t);
3232 if (!NT_STATUS_IS_OK(status)) {
3233 printf("getatr failed (%s)\n", nt_errstr(status));
3234 correct = False;
3237 if (abs(t - time(NULL)) > 60*60*24*10) {
3238 printf("ERROR: SMBgetatr bug. time is %s",
3239 ctime(&t));
3240 t = time(NULL);
3241 correct = True;
3244 t2 = t-60*60*24; /* 1 day ago */
3246 status = cli_setatr(cli, fname, 0, t2);
3247 if (!NT_STATUS_IS_OK(status)) {
3248 printf("setatr failed (%s)\n", nt_errstr(status));
3249 correct = True;
3252 status = cli_getatr(cli, fname, NULL, NULL, &t);
3253 if (!NT_STATUS_IS_OK(status)) {
3254 printf("getatr failed (%s)\n", nt_errstr(status));
3255 correct = True;
3258 if (t != t2) {
3259 printf("ERROR: getatr/setatr bug. times are\n%s",
3260 ctime(&t));
3261 printf("%s", ctime(&t2));
3262 correct = True;
3265 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3267 if (!torture_close_connection(cli)) {
3268 correct = False;
3271 printf("attrib test finished\n");
3273 return correct;
3278 This checks a couple of trans2 calls
3280 static bool run_trans2test(int dummy)
3282 struct cli_state *cli;
3283 uint16_t fnum;
3284 off_t size;
3285 time_t c_time, a_time, m_time;
3286 struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
3287 const char *fname = "\\trans2.tst";
3288 const char *dname = "\\trans2";
3289 const char *fname2 = "\\trans2\\trans2.tst";
3290 char *pname;
3291 bool correct = True;
3292 NTSTATUS status;
3293 uint32_t fs_attr;
3295 printf("starting trans2 test\n");
3297 if (!torture_open_connection(&cli, 0)) {
3298 return False;
3301 status = cli_get_fs_attr_info(cli, &fs_attr);
3302 if (!NT_STATUS_IS_OK(status)) {
3303 printf("ERROR: cli_get_fs_attr_info returned %s\n",
3304 nt_errstr(status));
3305 correct = false;
3308 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3309 cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3310 status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
3311 &a_time_ts, &w_time_ts, &m_time_ts, NULL);
3312 if (!NT_STATUS_IS_OK(status)) {
3313 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
3314 correct = False;
3317 status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
3318 if (!NT_STATUS_IS_OK(status)) {
3319 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
3320 correct = False;
3323 if (strcmp(pname, fname)) {
3324 printf("qfilename gave different name? [%s] [%s]\n",
3325 fname, pname);
3326 correct = False;
3329 cli_close(cli, fnum);
3331 sleep(2);
3333 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3334 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
3335 &fnum);
3336 if (!NT_STATUS_IS_OK(status)) {
3337 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3338 return False;
3340 cli_close(cli, fnum);
3342 status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
3343 NULL);
3344 if (!NT_STATUS_IS_OK(status)) {
3345 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
3346 correct = False;
3347 } else {
3348 time_t t = time(NULL);
3350 if (c_time != m_time) {
3351 printf("create time=%s", ctime(&c_time));
3352 printf("modify time=%s", ctime(&m_time));
3353 printf("This system appears to have sticky create times\n");
3355 if ((abs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
3356 printf("access time=%s", ctime(&a_time));
3357 printf("This system appears to set a midnight access time\n");
3358 correct = False;
3361 if (abs(m_time - t) > 60*60*24*7) {
3362 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
3363 correct = False;
3368 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3369 cli_openx(cli, fname,
3370 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3371 cli_close(cli, fnum);
3372 status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
3373 &m_time_ts, &size, NULL, NULL);
3374 if (!NT_STATUS_IS_OK(status)) {
3375 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3376 correct = False;
3377 } else {
3378 if (w_time_ts.tv_sec < 60*60*24*2) {
3379 printf("write time=%s", ctime(&w_time_ts.tv_sec));
3380 printf("This system appears to set a initial 0 write time\n");
3381 correct = False;
3385 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3388 /* check if the server updates the directory modification time
3389 when creating a new file */
3390 status = cli_mkdir(cli, dname);
3391 if (!NT_STATUS_IS_OK(status)) {
3392 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
3393 correct = False;
3395 sleep(3);
3396 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3397 &w_time_ts, &m_time_ts, &size, NULL, NULL);
3398 if (!NT_STATUS_IS_OK(status)) {
3399 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3400 correct = False;
3403 cli_openx(cli, fname2,
3404 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3405 cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
3406 cli_close(cli, fnum);
3407 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3408 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
3409 if (!NT_STATUS_IS_OK(status)) {
3410 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3411 correct = False;
3412 } else {
3413 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
3414 == 0) {
3415 printf("This system does not update directory modification times\n");
3416 correct = False;
3419 cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3420 cli_rmdir(cli, dname);
3422 if (!torture_close_connection(cli)) {
3423 correct = False;
3426 printf("trans2 test finished\n");
3428 return correct;
3432 This checks new W2K calls.
3435 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
3437 uint8_t *buf = NULL;
3438 uint32 len;
3439 NTSTATUS status;
3441 status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
3442 CLI_BUFFER_SIZE, NULL, &buf, &len);
3443 if (!NT_STATUS_IS_OK(status)) {
3444 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
3445 nt_errstr(status));
3446 } else {
3447 printf("qfileinfo: level %d, len = %u\n", level, len);
3448 dump_data(0, (uint8 *)buf, len);
3449 printf("\n");
3451 TALLOC_FREE(buf);
3452 return status;
3455 static bool run_w2ktest(int dummy)
3457 struct cli_state *cli;
3458 uint16_t fnum;
3459 const char *fname = "\\w2ktest\\w2k.tst";
3460 int level;
3461 bool correct = True;
3463 printf("starting w2k test\n");
3465 if (!torture_open_connection(&cli, 0)) {
3466 return False;
3469 cli_openx(cli, fname,
3470 O_RDWR | O_CREAT , DENY_NONE, &fnum);
3472 for (level = 1004; level < 1040; level++) {
3473 new_trans(cli, fnum, level);
3476 cli_close(cli, fnum);
3478 if (!torture_close_connection(cli)) {
3479 correct = False;
3482 printf("w2k test finished\n");
3484 return correct;
3489 this is a harness for some oplock tests
3491 static bool run_oplock1(int dummy)
3493 struct cli_state *cli1;
3494 const char *fname = "\\lockt1.lck";
3495 uint16_t fnum1;
3496 bool correct = True;
3497 NTSTATUS status;
3499 printf("starting oplock test 1\n");
3501 if (!torture_open_connection(&cli1, 0)) {
3502 return False;
3505 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3507 cli_sockopt(cli1, sockops);
3509 cli1->use_oplocks = True;
3511 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3512 &fnum1);
3513 if (!NT_STATUS_IS_OK(status)) {
3514 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3515 return False;
3518 cli1->use_oplocks = False;
3520 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3521 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3523 status = cli_close(cli1, fnum1);
3524 if (!NT_STATUS_IS_OK(status)) {
3525 printf("close2 failed (%s)\n", nt_errstr(status));
3526 return False;
3529 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3530 if (!NT_STATUS_IS_OK(status)) {
3531 printf("unlink failed (%s)\n", nt_errstr(status));
3532 return False;
3535 if (!torture_close_connection(cli1)) {
3536 correct = False;
3539 printf("finished oplock test 1\n");
3541 return correct;
3544 static bool run_oplock2(int dummy)
3546 struct cli_state *cli1, *cli2;
3547 const char *fname = "\\lockt2.lck";
3548 uint16_t fnum1, fnum2;
3549 int saved_use_oplocks = use_oplocks;
3550 char buf[4];
3551 bool correct = True;
3552 volatile bool *shared_correct;
3553 size_t nread;
3554 NTSTATUS status;
3556 shared_correct = (volatile bool *)shm_setup(sizeof(bool));
3557 *shared_correct = True;
3559 use_level_II_oplocks = True;
3560 use_oplocks = True;
3562 printf("starting oplock test 2\n");
3564 if (!torture_open_connection(&cli1, 0)) {
3565 use_level_II_oplocks = False;
3566 use_oplocks = saved_use_oplocks;
3567 return False;
3570 if (!torture_open_connection(&cli2, 1)) {
3571 use_level_II_oplocks = False;
3572 use_oplocks = saved_use_oplocks;
3573 return False;
3576 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3578 cli_sockopt(cli1, sockops);
3579 cli_sockopt(cli2, sockops);
3581 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3582 &fnum1);
3583 if (!NT_STATUS_IS_OK(status)) {
3584 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3585 return False;
3588 /* Don't need the globals any more. */
3589 use_level_II_oplocks = False;
3590 use_oplocks = saved_use_oplocks;
3592 if (fork() == 0) {
3593 /* Child code */
3594 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
3595 if (!NT_STATUS_IS_OK(status)) {
3596 printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
3597 *shared_correct = False;
3598 exit(0);
3601 sleep(2);
3603 status = cli_close(cli2, fnum2);
3604 if (!NT_STATUS_IS_OK(status)) {
3605 printf("close2 failed (%s)\n", nt_errstr(status));
3606 *shared_correct = False;
3609 exit(0);
3612 sleep(2);
3614 /* Ensure cli1 processes the break. Empty file should always return 0
3615 * bytes. */
3616 status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
3617 if (!NT_STATUS_IS_OK(status)) {
3618 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
3619 correct = false;
3620 } else if (nread != 0) {
3621 printf("read on empty fnum1 failed. recv %ld expected %d\n",
3622 (unsigned long)nread, 0);
3623 correct = false;
3626 /* Should now be at level II. */
3627 /* Test if sending a write locks causes a break to none. */
3628 status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
3629 if (!NT_STATUS_IS_OK(status)) {
3630 printf("lock failed (%s)\n", nt_errstr(status));
3631 correct = False;
3634 cli_unlock(cli1, fnum1, 0, 4);
3636 sleep(2);
3638 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
3639 if (!NT_STATUS_IS_OK(status)) {
3640 printf("lock failed (%s)\n", nt_errstr(status));
3641 correct = False;
3644 cli_unlock(cli1, fnum1, 0, 4);
3646 sleep(2);
3648 cli_read(cli1, fnum1, buf, 0, 4, NULL);
3650 status = cli_close(cli1, fnum1);
3651 if (!NT_STATUS_IS_OK(status)) {
3652 printf("close1 failed (%s)\n", nt_errstr(status));
3653 correct = False;
3656 sleep(4);
3658 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3659 if (!NT_STATUS_IS_OK(status)) {
3660 printf("unlink failed (%s)\n", nt_errstr(status));
3661 correct = False;
3664 if (!torture_close_connection(cli1)) {
3665 correct = False;
3668 if (!*shared_correct) {
3669 correct = False;
3672 printf("finished oplock test 2\n");
3674 return correct;
3677 struct oplock4_state {
3678 struct tevent_context *ev;
3679 struct cli_state *cli;
3680 bool *got_break;
3681 uint16_t *fnum2;
3684 static void oplock4_got_break(struct tevent_req *req);
3685 static void oplock4_got_open(struct tevent_req *req);
3687 static bool run_oplock4(int dummy)
3689 struct tevent_context *ev;
3690 struct cli_state *cli1, *cli2;
3691 struct tevent_req *oplock_req, *open_req;
3692 const char *fname = "\\lockt4.lck";
3693 const char *fname_ln = "\\lockt4_ln.lck";
3694 uint16_t fnum1, fnum2;
3695 int saved_use_oplocks = use_oplocks;
3696 NTSTATUS status;
3697 bool correct = true;
3699 bool got_break;
3701 struct oplock4_state *state;
3703 printf("starting oplock test 4\n");
3705 if (!torture_open_connection(&cli1, 0)) {
3706 use_level_II_oplocks = false;
3707 use_oplocks = saved_use_oplocks;
3708 return false;
3711 if (!torture_open_connection(&cli2, 1)) {
3712 use_level_II_oplocks = false;
3713 use_oplocks = saved_use_oplocks;
3714 return false;
3717 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3718 cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3720 cli_sockopt(cli1, sockops);
3721 cli_sockopt(cli2, sockops);
3723 /* Create the file. */
3724 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3725 &fnum1);
3726 if (!NT_STATUS_IS_OK(status)) {
3727 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3728 return false;
3731 status = cli_close(cli1, fnum1);
3732 if (!NT_STATUS_IS_OK(status)) {
3733 printf("close1 failed (%s)\n", nt_errstr(status));
3734 return false;
3737 /* Now create a hardlink. */
3738 status = cli_nt_hardlink(cli1, fname, fname_ln);
3739 if (!NT_STATUS_IS_OK(status)) {
3740 printf("nt hardlink failed (%s)\n", nt_errstr(status));
3741 return false;
3744 /* Prove that opening hardlinks cause deny modes to conflict. */
3745 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
3746 if (!NT_STATUS_IS_OK(status)) {
3747 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3748 return false;
3751 status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
3752 if (NT_STATUS_IS_OK(status)) {
3753 printf("open of %s succeeded - should fail with sharing violation.\n",
3754 fname_ln);
3755 return false;
3758 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3759 printf("open of %s should fail with sharing violation. Got %s\n",
3760 fname_ln, nt_errstr(status));
3761 return false;
3764 status = cli_close(cli1, fnum1);
3765 if (!NT_STATUS_IS_OK(status)) {
3766 printf("close1 failed (%s)\n", nt_errstr(status));
3767 return false;
3770 cli1->use_oplocks = true;
3771 cli2->use_oplocks = true;
3773 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3774 if (!NT_STATUS_IS_OK(status)) {
3775 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3776 return false;
3779 ev = tevent_context_init(talloc_tos());
3780 if (ev == NULL) {
3781 printf("tevent_context_init failed\n");
3782 return false;
3785 state = talloc(ev, struct oplock4_state);
3786 if (state == NULL) {
3787 printf("talloc failed\n");
3788 return false;
3790 state->ev = ev;
3791 state->cli = cli1;
3792 state->got_break = &got_break;
3793 state->fnum2 = &fnum2;
3795 oplock_req = cli_smb_oplock_break_waiter_send(
3796 talloc_tos(), ev, cli1);
3797 if (oplock_req == NULL) {
3798 printf("cli_smb_oplock_break_waiter_send failed\n");
3799 return false;
3801 tevent_req_set_callback(oplock_req, oplock4_got_break, state);
3803 open_req = cli_openx_send(
3804 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
3805 if (open_req == NULL) {
3806 printf("cli_openx_send failed\n");
3807 return false;
3809 tevent_req_set_callback(open_req, oplock4_got_open, state);
3811 got_break = false;
3812 fnum2 = 0xffff;
3814 while (!got_break || fnum2 == 0xffff) {
3815 int ret;
3816 ret = tevent_loop_once(ev);
3817 if (ret == -1) {
3818 printf("tevent_loop_once failed: %s\n",
3819 strerror(errno));
3820 return false;
3824 status = cli_close(cli2, fnum2);
3825 if (!NT_STATUS_IS_OK(status)) {
3826 printf("close2 failed (%s)\n", nt_errstr(status));
3827 correct = false;
3830 status = cli_close(cli1, fnum1);
3831 if (!NT_STATUS_IS_OK(status)) {
3832 printf("close1 failed (%s)\n", nt_errstr(status));
3833 correct = false;
3836 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3837 if (!NT_STATUS_IS_OK(status)) {
3838 printf("unlink failed (%s)\n", nt_errstr(status));
3839 correct = false;
3842 status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3843 if (!NT_STATUS_IS_OK(status)) {
3844 printf("unlink failed (%s)\n", nt_errstr(status));
3845 correct = false;
3848 if (!torture_close_connection(cli1)) {
3849 correct = false;
3852 if (!got_break) {
3853 correct = false;
3856 printf("finished oplock test 4\n");
3858 return correct;
3861 static void oplock4_got_break(struct tevent_req *req)
3863 struct oplock4_state *state = tevent_req_callback_data(
3864 req, struct oplock4_state);
3865 uint16_t fnum;
3866 uint8_t level;
3867 NTSTATUS status;
3869 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
3870 TALLOC_FREE(req);
3871 if (!NT_STATUS_IS_OK(status)) {
3872 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
3873 nt_errstr(status));
3874 return;
3876 *state->got_break = true;
3878 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
3879 NO_OPLOCK);
3880 if (req == NULL) {
3881 printf("cli_oplock_ack_send failed\n");
3882 return;
3886 static void oplock4_got_open(struct tevent_req *req)
3888 struct oplock4_state *state = tevent_req_callback_data(
3889 req, struct oplock4_state);
3890 NTSTATUS status;
3892 status = cli_openx_recv(req, state->fnum2);
3893 if (!NT_STATUS_IS_OK(status)) {
3894 printf("cli_openx_recv returned %s\n", nt_errstr(status));
3895 *state->fnum2 = 0xffff;
3900 Test delete on close semantics.
3902 static bool run_deletetest(int dummy)
3904 struct cli_state *cli1 = NULL;
3905 struct cli_state *cli2 = NULL;
3906 const char *fname = "\\delete.file";
3907 uint16_t fnum1 = (uint16_t)-1;
3908 uint16_t fnum2 = (uint16_t)-1;
3909 bool correct = True;
3910 NTSTATUS status;
3912 printf("starting delete test\n");
3914 if (!torture_open_connection(&cli1, 0)) {
3915 return False;
3918 cli_sockopt(cli1, sockops);
3920 /* Test 1 - this should delete the file on close. */
3922 cli_setatr(cli1, fname, 0, 0);
3923 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3925 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
3926 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
3927 FILE_DELETE_ON_CLOSE, 0, &fnum1);
3928 if (!NT_STATUS_IS_OK(status)) {
3929 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
3930 correct = False;
3931 goto fail;
3934 status = cli_close(cli1, fnum1);
3935 if (!NT_STATUS_IS_OK(status)) {
3936 printf("[1] close failed (%s)\n", nt_errstr(status));
3937 correct = False;
3938 goto fail;
3941 if (NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1))) {
3942 printf("[1] open of %s succeeded (should fail)\n", fname);
3943 correct = False;
3944 goto fail;
3947 printf("first delete on close test succeeded.\n");
3949 /* Test 2 - this should delete the file on close. */
3951 cli_setatr(cli1, fname, 0, 0);
3952 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3954 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3955 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
3956 FILE_OVERWRITE_IF, 0, 0, &fnum1);
3957 if (!NT_STATUS_IS_OK(status)) {
3958 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
3959 correct = False;
3960 goto fail;
3963 status = cli_nt_delete_on_close(cli1, fnum1, true);
3964 if (!NT_STATUS_IS_OK(status)) {
3965 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
3966 correct = False;
3967 goto fail;
3970 status = cli_close(cli1, fnum1);
3971 if (!NT_STATUS_IS_OK(status)) {
3972 printf("[2] close failed (%s)\n", nt_errstr(status));
3973 correct = False;
3974 goto fail;
3977 if (NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3978 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
3979 status = cli_close(cli1, fnum1);
3980 if (!NT_STATUS_IS_OK(status)) {
3981 printf("[2] close failed (%s)\n", nt_errstr(status));
3982 correct = False;
3983 goto fail;
3985 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3986 } else
3987 printf("second delete on close test succeeded.\n");
3989 /* Test 3 - ... */
3990 cli_setatr(cli1, fname, 0, 0);
3991 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3993 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3994 FILE_ATTRIBUTE_NORMAL,
3995 FILE_SHARE_READ|FILE_SHARE_WRITE,
3996 FILE_OVERWRITE_IF, 0, 0, &fnum1);
3997 if (!NT_STATUS_IS_OK(status)) {
3998 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
3999 correct = False;
4000 goto fail;
4003 /* This should fail with a sharing violation - open for delete is only compatible
4004 with SHARE_DELETE. */
4006 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4007 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, 0, &fnum2))) {
4008 printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
4009 correct = False;
4010 goto fail;
4013 /* This should succeed. */
4014 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4015 FILE_ATTRIBUTE_NORMAL,
4016 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4017 FILE_OPEN, 0, 0, &fnum2);
4018 if (!NT_STATUS_IS_OK(status)) {
4019 printf("[3] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
4020 correct = False;
4021 goto fail;
4024 status = cli_nt_delete_on_close(cli1, fnum1, true);
4025 if (!NT_STATUS_IS_OK(status)) {
4026 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
4027 correct = False;
4028 goto fail;
4031 status = cli_close(cli1, fnum1);
4032 if (!NT_STATUS_IS_OK(status)) {
4033 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
4034 correct = False;
4035 goto fail;
4038 status = cli_close(cli1, fnum2);
4039 if (!NT_STATUS_IS_OK(status)) {
4040 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
4041 correct = False;
4042 goto fail;
4045 /* This should fail - file should no longer be there. */
4047 if (NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
4048 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
4049 status = cli_close(cli1, fnum1);
4050 if (!NT_STATUS_IS_OK(status)) {
4051 printf("[3] close failed (%s)\n", nt_errstr(status));
4053 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4054 correct = False;
4055 goto fail;
4056 } else
4057 printf("third delete on close test succeeded.\n");
4059 /* Test 4 ... */
4060 cli_setatr(cli1, fname, 0, 0);
4061 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4063 status = cli_ntcreate(cli1, fname, 0,
4064 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4065 FILE_ATTRIBUTE_NORMAL,
4066 FILE_SHARE_READ|FILE_SHARE_WRITE,
4067 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4068 if (!NT_STATUS_IS_OK(status)) {
4069 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
4070 correct = False;
4071 goto fail;
4074 /* This should succeed. */
4075 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4076 FILE_ATTRIBUTE_NORMAL,
4077 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4078 FILE_OPEN, 0, 0, &fnum2);
4079 if (!NT_STATUS_IS_OK(status)) {
4080 printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
4081 correct = False;
4082 goto fail;
4085 status = cli_close(cli1, fnum2);
4086 if (!NT_STATUS_IS_OK(status)) {
4087 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
4088 correct = False;
4089 goto fail;
4092 status = cli_nt_delete_on_close(cli1, fnum1, true);
4093 if (!NT_STATUS_IS_OK(status)) {
4094 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
4095 correct = False;
4096 goto fail;
4099 /* This should fail - no more opens once delete on close set. */
4100 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4101 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4102 FILE_OPEN, 0, 0, &fnum2))) {
4103 printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
4104 correct = False;
4105 goto fail;
4106 } else
4107 printf("fourth delete on close test succeeded.\n");
4109 status = cli_close(cli1, fnum1);
4110 if (!NT_STATUS_IS_OK(status)) {
4111 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
4112 correct = False;
4113 goto fail;
4116 /* Test 5 ... */
4117 cli_setatr(cli1, fname, 0, 0);
4118 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4120 status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
4121 if (!NT_STATUS_IS_OK(status)) {
4122 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4123 correct = False;
4124 goto fail;
4127 /* This should fail - only allowed on NT opens with DELETE access. */
4129 if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4130 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
4131 correct = False;
4132 goto fail;
4135 status = cli_close(cli1, fnum1);
4136 if (!NT_STATUS_IS_OK(status)) {
4137 printf("[5] close - 2 failed (%s)\n", nt_errstr(status));
4138 correct = False;
4139 goto fail;
4142 printf("fifth delete on close test succeeded.\n");
4144 /* Test 6 ... */
4145 cli_setatr(cli1, fname, 0, 0);
4146 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4148 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4149 FILE_ATTRIBUTE_NORMAL,
4150 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4151 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4152 if (!NT_STATUS_IS_OK(status)) {
4153 printf("[6] open of %s failed (%s)\n", fname,
4154 nt_errstr(status));
4155 correct = False;
4156 goto fail;
4159 /* This should fail - only allowed on NT opens with DELETE access. */
4161 if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4162 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
4163 correct = False;
4164 goto fail;
4167 status = cli_close(cli1, fnum1);
4168 if (!NT_STATUS_IS_OK(status)) {
4169 printf("[6] close - 2 failed (%s)\n", nt_errstr(status));
4170 correct = False;
4171 goto fail;
4174 printf("sixth delete on close test succeeded.\n");
4176 /* Test 7 ... */
4177 cli_setatr(cli1, fname, 0, 0);
4178 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4180 status = cli_ntcreate(cli1, fname, 0,
4181 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4182 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
4183 0, 0, &fnum1);
4184 if (!NT_STATUS_IS_OK(status)) {
4185 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4186 correct = False;
4187 goto fail;
4190 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4191 printf("[7] setting delete_on_close on file failed !\n");
4192 correct = False;
4193 goto fail;
4196 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, false))) {
4197 printf("[7] unsetting delete_on_close on file failed !\n");
4198 correct = False;
4199 goto fail;
4202 status = cli_close(cli1, fnum1);
4203 if (!NT_STATUS_IS_OK(status)) {
4204 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4205 correct = False;
4206 goto fail;
4209 /* This next open should succeed - we reset the flag. */
4210 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4211 if (!NT_STATUS_IS_OK(status)) {
4212 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4213 correct = False;
4214 goto fail;
4217 status = cli_close(cli1, fnum1);
4218 if (!NT_STATUS_IS_OK(status)) {
4219 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4220 correct = False;
4221 goto fail;
4224 printf("seventh delete on close test succeeded.\n");
4226 /* Test 7 ... */
4227 cli_setatr(cli1, fname, 0, 0);
4228 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4230 if (!torture_open_connection(&cli2, 1)) {
4231 printf("[8] failed to open second connection.\n");
4232 correct = False;
4233 goto fail;
4236 cli_sockopt(cli1, sockops);
4238 status = cli_ntcreate(cli1, fname, 0,
4239 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4240 FILE_ATTRIBUTE_NORMAL,
4241 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4242 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4243 if (!NT_STATUS_IS_OK(status)) {
4244 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4245 correct = False;
4246 goto fail;
4249 status = cli_ntcreate(cli2, fname, 0,
4250 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4251 FILE_ATTRIBUTE_NORMAL,
4252 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4253 FILE_OPEN, 0, 0, &fnum2);
4254 if (!NT_STATUS_IS_OK(status)) {
4255 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4256 correct = False;
4257 goto fail;
4260 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4261 printf("[8] setting delete_on_close on file failed !\n");
4262 correct = False;
4263 goto fail;
4266 status = cli_close(cli1, fnum1);
4267 if (!NT_STATUS_IS_OK(status)) {
4268 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
4269 correct = False;
4270 goto fail;
4273 status = cli_close(cli2, fnum2);
4274 if (!NT_STATUS_IS_OK(status)) {
4275 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
4276 correct = False;
4277 goto fail;
4280 /* This should fail.. */
4281 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4282 if (NT_STATUS_IS_OK(status)) {
4283 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
4284 goto fail;
4285 correct = False;
4286 } else
4287 printf("eighth delete on close test succeeded.\n");
4289 /* This should fail - we need to set DELETE_ACCESS. */
4290 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0,FILE_READ_DATA|FILE_WRITE_DATA,
4291 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE, 0, &fnum1))) {
4292 printf("[9] open of %s succeeded should have failed!\n", fname);
4293 correct = False;
4294 goto fail;
4297 printf("ninth delete on close test succeeded.\n");
4299 status = cli_ntcreate(cli1, fname, 0,
4300 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4301 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4302 FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
4303 0, &fnum1);
4304 if (!NT_STATUS_IS_OK(status)) {
4305 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
4306 correct = False;
4307 goto fail;
4310 /* This should delete the file. */
4311 status = cli_close(cli1, fnum1);
4312 if (!NT_STATUS_IS_OK(status)) {
4313 printf("[10] close failed (%s)\n", nt_errstr(status));
4314 correct = False;
4315 goto fail;
4318 /* This should fail.. */
4319 if (NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
4320 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
4321 goto fail;
4322 correct = False;
4323 } else
4324 printf("tenth delete on close test succeeded.\n");
4326 cli_setatr(cli1, fname, 0, 0);
4327 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4329 /* What error do we get when attempting to open a read-only file with
4330 delete access ? */
4332 /* Create a readonly file. */
4333 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4334 FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
4335 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4336 if (!NT_STATUS_IS_OK(status)) {
4337 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
4338 correct = False;
4339 goto fail;
4342 status = cli_close(cli1, fnum1);
4343 if (!NT_STATUS_IS_OK(status)) {
4344 printf("[11] close failed (%s)\n", nt_errstr(status));
4345 correct = False;
4346 goto fail;
4349 /* Now try open for delete access. */
4350 status = cli_ntcreate(cli1, fname, 0,
4351 FILE_READ_ATTRIBUTES|DELETE_ACCESS,
4353 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4354 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4355 if (NT_STATUS_IS_OK(status)) {
4356 printf("[11] open of %s succeeded should have been denied with ACCESS_DENIED!\n", fname);
4357 cli_close(cli1, fnum1);
4358 goto fail;
4359 correct = False;
4360 } else {
4361 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
4362 printf("[11] open of %s should have been denied with ACCESS_DENIED! Got error %s\n", fname, nt_errstr(status));
4363 goto fail;
4364 correct = False;
4365 } else {
4366 printf("eleventh delete on close test succeeded.\n");
4370 printf("finished delete test\n");
4372 fail:
4373 /* FIXME: This will crash if we aborted before cli2 got
4374 * intialized, because these functions don't handle
4375 * uninitialized connections. */
4377 if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
4378 if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
4379 cli_setatr(cli1, fname, 0, 0);
4380 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4382 if (cli1 && !torture_close_connection(cli1)) {
4383 correct = False;
4385 if (cli2 && !torture_close_connection(cli2)) {
4386 correct = False;
4388 return correct;
4391 static bool run_deletetest_ln(int dummy)
4393 struct cli_state *cli;
4394 const char *fname = "\\delete1";
4395 const char *fname_ln = "\\delete1_ln";
4396 uint16_t fnum;
4397 uint16_t fnum1;
4398 NTSTATUS status;
4399 bool correct = true;
4400 time_t t;
4402 printf("starting deletetest-ln\n");
4404 if (!torture_open_connection(&cli, 0)) {
4405 return false;
4408 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4409 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4411 cli_sockopt(cli, sockops);
4413 /* Create the file. */
4414 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
4415 if (!NT_STATUS_IS_OK(status)) {
4416 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4417 return false;
4420 status = cli_close(cli, fnum);
4421 if (!NT_STATUS_IS_OK(status)) {
4422 printf("close1 failed (%s)\n", nt_errstr(status));
4423 return false;
4426 /* Now create a hardlink. */
4427 status = cli_nt_hardlink(cli, fname, fname_ln);
4428 if (!NT_STATUS_IS_OK(status)) {
4429 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4430 return false;
4433 /* Open the original file. */
4434 status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
4435 FILE_ATTRIBUTE_NORMAL,
4436 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4437 FILE_OPEN_IF, 0, 0, &fnum);
4438 if (!NT_STATUS_IS_OK(status)) {
4439 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
4440 return false;
4443 /* Unlink the hard link path. */
4444 status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
4445 FILE_ATTRIBUTE_NORMAL,
4446 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4447 FILE_OPEN_IF, 0, 0, &fnum1);
4448 if (!NT_STATUS_IS_OK(status)) {
4449 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
4450 return false;
4452 status = cli_nt_delete_on_close(cli, fnum1, true);
4453 if (!NT_STATUS_IS_OK(status)) {
4454 d_printf("(%s) failed to set delete_on_close %s: %s\n",
4455 __location__, fname_ln, nt_errstr(status));
4456 return false;
4459 status = cli_close(cli, fnum1);
4460 if (!NT_STATUS_IS_OK(status)) {
4461 printf("close %s failed (%s)\n",
4462 fname_ln, nt_errstr(status));
4463 return false;
4466 status = cli_close(cli, fnum);
4467 if (!NT_STATUS_IS_OK(status)) {
4468 printf("close %s failed (%s)\n",
4469 fname, nt_errstr(status));
4470 return false;
4473 /* Ensure the original file is still there. */
4474 status = cli_getatr(cli, fname, NULL, NULL, &t);
4475 if (!NT_STATUS_IS_OK(status)) {
4476 printf("%s getatr on file %s failed (%s)\n",
4477 __location__,
4478 fname,
4479 nt_errstr(status));
4480 correct = False;
4483 /* Ensure the link path is gone. */
4484 status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
4485 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4486 printf("%s, getatr for file %s returned wrong error code %s "
4487 "- should have been deleted\n",
4488 __location__,
4489 fname_ln, nt_errstr(status));
4490 correct = False;
4493 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4494 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4496 if (!torture_close_connection(cli)) {
4497 correct = false;
4500 printf("finished deletetest-ln\n");
4502 return correct;
4506 print out server properties
4508 static bool run_properties(int dummy)
4510 struct cli_state *cli;
4511 bool correct = True;
4513 printf("starting properties test\n");
4515 ZERO_STRUCT(cli);
4517 if (!torture_open_connection(&cli, 0)) {
4518 return False;
4521 cli_sockopt(cli, sockops);
4523 d_printf("Capabilities 0x%08x\n", cli_state_capabilities(cli));
4525 if (!torture_close_connection(cli)) {
4526 correct = False;
4529 return correct;
4534 /* FIRST_DESIRED_ACCESS 0xf019f */
4535 #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
4536 FILE_READ_EA| /* 0xf */ \
4537 FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
4538 FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
4539 DELETE_ACCESS|READ_CONTROL_ACCESS|\
4540 WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
4541 /* SECOND_DESIRED_ACCESS 0xe0080 */
4542 #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
4543 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4544 WRITE_OWNER_ACCESS /* 0xe0000 */
4546 #if 0
4547 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
4548 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4549 FILE_READ_DATA|\
4550 WRITE_OWNER_ACCESS /* */
4551 #endif
4554 Test ntcreate calls made by xcopy
4556 static bool run_xcopy(int dummy)
4558 static struct cli_state *cli1;
4559 const char *fname = "\\test.txt";
4560 bool correct = True;
4561 uint16_t fnum1, fnum2;
4562 NTSTATUS status;
4564 printf("starting xcopy test\n");
4566 if (!torture_open_connection(&cli1, 0)) {
4567 return False;
4570 status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
4571 FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
4572 FILE_OVERWRITE_IF, 0x4044, 0, &fnum1);
4573 if (!NT_STATUS_IS_OK(status)) {
4574 printf("First open failed - %s\n", nt_errstr(status));
4575 return False;
4578 status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
4579 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4580 FILE_OPEN, 0x200000, 0, &fnum2);
4581 if (!NT_STATUS_IS_OK(status)) {
4582 printf("second open failed - %s\n", nt_errstr(status));
4583 return False;
4586 if (!torture_close_connection(cli1)) {
4587 correct = False;
4590 return correct;
4594 Test rename on files open with share delete and no share delete.
4596 static bool run_rename(int dummy)
4598 static struct cli_state *cli1;
4599 const char *fname = "\\test.txt";
4600 const char *fname1 = "\\test1.txt";
4601 bool correct = True;
4602 uint16_t fnum1;
4603 uint16_t attr;
4604 NTSTATUS status;
4606 printf("starting rename test\n");
4608 if (!torture_open_connection(&cli1, 0)) {
4609 return False;
4612 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4613 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4615 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4616 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
4617 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4618 if (!NT_STATUS_IS_OK(status)) {
4619 printf("First open failed - %s\n", nt_errstr(status));
4620 return False;
4623 status = cli_rename(cli1, fname, fname1);
4624 if (!NT_STATUS_IS_OK(status)) {
4625 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
4626 } else {
4627 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
4628 correct = False;
4631 status = cli_close(cli1, fnum1);
4632 if (!NT_STATUS_IS_OK(status)) {
4633 printf("close - 1 failed (%s)\n", nt_errstr(status));
4634 return False;
4637 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4638 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4639 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4640 #if 0
4641 FILE_SHARE_DELETE|FILE_SHARE_NONE,
4642 #else
4643 FILE_SHARE_DELETE|FILE_SHARE_READ,
4644 #endif
4645 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4646 if (!NT_STATUS_IS_OK(status)) {
4647 printf("Second open failed - %s\n", nt_errstr(status));
4648 return False;
4651 status = cli_rename(cli1, fname, fname1);
4652 if (!NT_STATUS_IS_OK(status)) {
4653 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
4654 correct = False;
4655 } else {
4656 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
4659 status = cli_close(cli1, fnum1);
4660 if (!NT_STATUS_IS_OK(status)) {
4661 printf("close - 2 failed (%s)\n", nt_errstr(status));
4662 return False;
4665 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4666 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4668 status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
4669 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4670 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4671 if (!NT_STATUS_IS_OK(status)) {
4672 printf("Third open failed - %s\n", nt_errstr(status));
4673 return False;
4677 #if 0
4679 uint16_t fnum2;
4681 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
4682 FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4683 printf("Fourth open failed - %s\n", cli_errstr(cli1));
4684 return False;
4686 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum2, true))) {
4687 printf("[8] setting delete_on_close on file failed !\n");
4688 return False;
4691 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
4692 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
4693 return False;
4696 #endif
4698 status = cli_rename(cli1, fname, fname1);
4699 if (!NT_STATUS_IS_OK(status)) {
4700 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
4701 correct = False;
4702 } else {
4703 printf("Third rename succeeded (SHARE_NONE)\n");
4706 status = cli_close(cli1, fnum1);
4707 if (!NT_STATUS_IS_OK(status)) {
4708 printf("close - 3 failed (%s)\n", nt_errstr(status));
4709 return False;
4712 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4713 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4715 /*----*/
4717 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4718 FILE_ATTRIBUTE_NORMAL,
4719 FILE_SHARE_READ | FILE_SHARE_WRITE,
4720 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4721 if (!NT_STATUS_IS_OK(status)) {
4722 printf("Fourth open failed - %s\n", nt_errstr(status));
4723 return False;
4726 status = cli_rename(cli1, fname, fname1);
4727 if (!NT_STATUS_IS_OK(status)) {
4728 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
4729 } else {
4730 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
4731 correct = False;
4734 status = cli_close(cli1, fnum1);
4735 if (!NT_STATUS_IS_OK(status)) {
4736 printf("close - 4 failed (%s)\n", nt_errstr(status));
4737 return False;
4740 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4741 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4743 /*--*/
4745 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4746 FILE_ATTRIBUTE_NORMAL,
4747 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4748 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4749 if (!NT_STATUS_IS_OK(status)) {
4750 printf("Fifth open failed - %s\n", nt_errstr(status));
4751 return False;
4754 status = cli_rename(cli1, fname, fname1);
4755 if (!NT_STATUS_IS_OK(status)) {
4756 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
4757 correct = False;
4758 } else {
4759 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
4763 * Now check if the first name still exists ...
4766 /* if (!NT_STATUS_OP(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4767 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4768 printf("Opening original file after rename of open file fails: %s\n",
4769 cli_errstr(cli1));
4771 else {
4772 printf("Opening original file after rename of open file works ...\n");
4773 (void)cli_close(cli1, fnum2);
4774 } */
4776 /*--*/
4777 status = cli_close(cli1, fnum1);
4778 if (!NT_STATUS_IS_OK(status)) {
4779 printf("close - 5 failed (%s)\n", nt_errstr(status));
4780 return False;
4783 /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
4784 status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
4785 if (!NT_STATUS_IS_OK(status)) {
4786 printf("getatr on file %s failed - %s ! \n",
4787 fname1, nt_errstr(status));
4788 correct = False;
4789 } else {
4790 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
4791 printf("Renamed file %s has wrong attr 0x%x "
4792 "(should be 0x%x)\n",
4793 fname1,
4794 attr,
4795 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
4796 correct = False;
4797 } else {
4798 printf("Renamed file %s has archive bit set\n", fname1);
4802 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4803 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4805 if (!torture_close_connection(cli1)) {
4806 correct = False;
4809 return correct;
4812 static bool run_pipe_number(int dummy)
4814 struct cli_state *cli1;
4815 const char *pipe_name = "\\SPOOLSS";
4816 uint16_t fnum;
4817 int num_pipes = 0;
4818 NTSTATUS status;
4820 printf("starting pipenumber test\n");
4821 if (!torture_open_connection(&cli1, 0)) {
4822 return False;
4825 cli_sockopt(cli1, sockops);
4826 while(1) {
4827 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
4828 FILE_ATTRIBUTE_NORMAL,
4829 FILE_SHARE_READ|FILE_SHARE_WRITE,
4830 FILE_OPEN_IF, 0, 0, &fnum);
4831 if (!NT_STATUS_IS_OK(status)) {
4832 printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
4833 break;
4835 num_pipes++;
4836 printf("\r%6d", num_pipes);
4839 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
4840 torture_close_connection(cli1);
4841 return True;
4845 Test open mode returns on read-only files.
4847 static bool run_opentest(int dummy)
4849 static struct cli_state *cli1;
4850 static struct cli_state *cli2;
4851 const char *fname = "\\readonly.file";
4852 uint16_t fnum1, fnum2;
4853 char buf[20];
4854 off_t fsize;
4855 bool correct = True;
4856 char *tmp_path;
4857 NTSTATUS status;
4859 printf("starting open test\n");
4861 if (!torture_open_connection(&cli1, 0)) {
4862 return False;
4865 cli_setatr(cli1, fname, 0, 0);
4866 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4868 cli_sockopt(cli1, sockops);
4870 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4871 if (!NT_STATUS_IS_OK(status)) {
4872 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4873 return False;
4876 status = cli_close(cli1, fnum1);
4877 if (!NT_STATUS_IS_OK(status)) {
4878 printf("close2 failed (%s)\n", nt_errstr(status));
4879 return False;
4882 status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
4883 if (!NT_STATUS_IS_OK(status)) {
4884 printf("cli_setatr failed (%s)\n", nt_errstr(status));
4885 return False;
4888 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4889 if (!NT_STATUS_IS_OK(status)) {
4890 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4891 return False;
4894 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
4895 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4897 if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
4898 NT_STATUS_ACCESS_DENIED)) {
4899 printf("correct error code ERRDOS/ERRnoaccess returned\n");
4902 printf("finished open test 1\n");
4904 cli_close(cli1, fnum1);
4906 /* Now try not readonly and ensure ERRbadshare is returned. */
4908 cli_setatr(cli1, fname, 0, 0);
4910 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4911 if (!NT_STATUS_IS_OK(status)) {
4912 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4913 return False;
4916 /* This will fail - but the error should be ERRshare. */
4917 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4919 if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
4920 NT_STATUS_SHARING_VIOLATION)) {
4921 printf("correct error code ERRDOS/ERRbadshare returned\n");
4924 status = cli_close(cli1, fnum1);
4925 if (!NT_STATUS_IS_OK(status)) {
4926 printf("close2 failed (%s)\n", nt_errstr(status));
4927 return False;
4930 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4932 printf("finished open test 2\n");
4934 /* Test truncate open disposition on file opened for read. */
4935 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4936 if (!NT_STATUS_IS_OK(status)) {
4937 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
4938 return False;
4941 /* write 20 bytes. */
4943 memset(buf, '\0', 20);
4945 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
4946 if (!NT_STATUS_IS_OK(status)) {
4947 printf("write failed (%s)\n", nt_errstr(status));
4948 correct = False;
4951 status = cli_close(cli1, fnum1);
4952 if (!NT_STATUS_IS_OK(status)) {
4953 printf("(3) close1 failed (%s)\n", nt_errstr(status));
4954 return False;
4957 /* Ensure size == 20. */
4958 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
4959 if (!NT_STATUS_IS_OK(status)) {
4960 printf("(3) getatr failed (%s)\n", nt_errstr(status));
4961 return False;
4964 if (fsize != 20) {
4965 printf("(3) file size != 20\n");
4966 return False;
4969 /* Now test if we can truncate a file opened for readonly. */
4970 status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
4971 if (!NT_STATUS_IS_OK(status)) {
4972 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
4973 return False;
4976 status = cli_close(cli1, fnum1);
4977 if (!NT_STATUS_IS_OK(status)) {
4978 printf("close2 failed (%s)\n", nt_errstr(status));
4979 return False;
4982 /* Ensure size == 0. */
4983 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
4984 if (!NT_STATUS_IS_OK(status)) {
4985 printf("(3) getatr failed (%s)\n", nt_errstr(status));
4986 return False;
4989 if (fsize != 0) {
4990 printf("(3) file size != 0\n");
4991 return False;
4993 printf("finished open test 3\n");
4995 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4997 printf("Do ctemp tests\n");
4998 status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
4999 if (!NT_STATUS_IS_OK(status)) {
5000 printf("ctemp failed (%s)\n", nt_errstr(status));
5001 return False;
5004 printf("ctemp gave path %s\n", tmp_path);
5005 status = cli_close(cli1, fnum1);
5006 if (!NT_STATUS_IS_OK(status)) {
5007 printf("close of temp failed (%s)\n", nt_errstr(status));
5010 status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5011 if (!NT_STATUS_IS_OK(status)) {
5012 printf("unlink of temp failed (%s)\n", nt_errstr(status));
5015 /* Test the non-io opens... */
5017 if (!torture_open_connection(&cli2, 1)) {
5018 return False;
5021 cli_setatr(cli2, fname, 0, 0);
5022 cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5024 cli_sockopt(cli2, sockops);
5026 printf("TEST #1 testing 2 non-io opens (no delete)\n");
5027 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5028 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5029 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5030 if (!NT_STATUS_IS_OK(status)) {
5031 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5032 return False;
5035 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5036 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5037 FILE_OPEN_IF, 0, 0, &fnum2);
5038 if (!NT_STATUS_IS_OK(status)) {
5039 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5040 return False;
5043 status = cli_close(cli1, fnum1);
5044 if (!NT_STATUS_IS_OK(status)) {
5045 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5046 return False;
5049 status = cli_close(cli2, fnum2);
5050 if (!NT_STATUS_IS_OK(status)) {
5051 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5052 return False;
5055 printf("non-io open test #1 passed.\n");
5057 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5059 printf("TEST #2 testing 2 non-io opens (first with delete)\n");
5061 status = cli_ntcreate(cli1, fname, 0,
5062 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5063 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5064 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5065 if (!NT_STATUS_IS_OK(status)) {
5066 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5067 return False;
5070 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5071 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5072 FILE_OPEN_IF, 0, 0, &fnum2);
5073 if (!NT_STATUS_IS_OK(status)) {
5074 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5075 return False;
5078 status = cli_close(cli1, fnum1);
5079 if (!NT_STATUS_IS_OK(status)) {
5080 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5081 return False;
5084 status = cli_close(cli2, fnum2);
5085 if (!NT_STATUS_IS_OK(status)) {
5086 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5087 return False;
5090 printf("non-io open test #2 passed.\n");
5092 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5094 printf("TEST #3 testing 2 non-io opens (second with delete)\n");
5096 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5097 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5098 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5099 if (!NT_STATUS_IS_OK(status)) {
5100 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5101 return False;
5104 status = cli_ntcreate(cli2, fname, 0,
5105 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5106 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5107 FILE_OPEN_IF, 0, 0, &fnum2);
5108 if (!NT_STATUS_IS_OK(status)) {
5109 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5110 return False;
5113 status = cli_close(cli1, fnum1);
5114 if (!NT_STATUS_IS_OK(status)) {
5115 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5116 return False;
5119 status = cli_close(cli2, fnum2);
5120 if (!NT_STATUS_IS_OK(status)) {
5121 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5122 return False;
5125 printf("non-io open test #3 passed.\n");
5127 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5129 printf("TEST #4 testing 2 non-io opens (both with delete)\n");
5131 status = cli_ntcreate(cli1, fname, 0,
5132 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5133 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5134 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5135 if (!NT_STATUS_IS_OK(status)) {
5136 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5137 return False;
5140 status = cli_ntcreate(cli2, fname, 0,
5141 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5142 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5143 FILE_OPEN_IF, 0, 0, &fnum2);
5144 if (NT_STATUS_IS_OK(status)) {
5145 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5146 return False;
5149 printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5151 status = cli_close(cli1, fnum1);
5152 if (!NT_STATUS_IS_OK(status)) {
5153 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5154 return False;
5157 printf("non-io open test #4 passed.\n");
5159 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5161 printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
5163 status = cli_ntcreate(cli1, fname, 0,
5164 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5165 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5166 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5167 if (!NT_STATUS_IS_OK(status)) {
5168 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5169 return False;
5172 status = cli_ntcreate(cli2, fname, 0,
5173 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5174 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5175 FILE_OPEN_IF, 0, 0, &fnum2);
5176 if (!NT_STATUS_IS_OK(status)) {
5177 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5178 return False;
5181 status = cli_close(cli1, fnum1);
5182 if (!NT_STATUS_IS_OK(status)) {
5183 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5184 return False;
5187 status = cli_close(cli2, fnum2);
5188 if (!NT_STATUS_IS_OK(status)) {
5189 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5190 return False;
5193 printf("non-io open test #5 passed.\n");
5195 printf("TEST #6 testing 1 non-io open, one io open\n");
5197 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5199 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5200 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5201 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5202 if (!NT_STATUS_IS_OK(status)) {
5203 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5204 return False;
5207 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5208 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
5209 FILE_OPEN_IF, 0, 0, &fnum2);
5210 if (!NT_STATUS_IS_OK(status)) {
5211 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5212 return False;
5215 status = cli_close(cli1, fnum1);
5216 if (!NT_STATUS_IS_OK(status)) {
5217 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5218 return False;
5221 status = cli_close(cli2, fnum2);
5222 if (!NT_STATUS_IS_OK(status)) {
5223 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5224 return False;
5227 printf("non-io open test #6 passed.\n");
5229 printf("TEST #7 testing 1 non-io open, one io open with delete\n");
5231 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5233 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5234 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5235 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5236 if (!NT_STATUS_IS_OK(status)) {
5237 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5238 return False;
5241 status = cli_ntcreate(cli2, fname, 0,
5242 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5243 FILE_ATTRIBUTE_NORMAL,
5244 FILE_SHARE_READ|FILE_SHARE_DELETE,
5245 FILE_OPEN_IF, 0, 0, &fnum2);
5246 if (NT_STATUS_IS_OK(status)) {
5247 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5248 return False;
5251 printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5253 status = cli_close(cli1, fnum1);
5254 if (!NT_STATUS_IS_OK(status)) {
5255 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5256 return False;
5259 printf("non-io open test #7 passed.\n");
5261 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5263 printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
5264 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
5265 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5266 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5267 if (!NT_STATUS_IS_OK(status)) {
5268 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
5269 correct = false;
5270 goto out;
5273 /* Write to ensure we have to update the file time. */
5274 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5275 NULL);
5276 if (!NT_STATUS_IS_OK(status)) {
5277 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
5278 correct = false;
5279 goto out;
5282 status = cli_close(cli1, fnum1);
5283 if (!NT_STATUS_IS_OK(status)) {
5284 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
5285 correct = false;
5288 out:
5290 if (!torture_close_connection(cli1)) {
5291 correct = False;
5293 if (!torture_close_connection(cli2)) {
5294 correct = False;
5297 return correct;
5300 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
5302 uint16 major, minor;
5303 uint32 caplow, caphigh;
5304 NTSTATUS status;
5306 if (!SERVER_HAS_UNIX_CIFS(cli)) {
5307 printf("Server doesn't support UNIX CIFS extensions.\n");
5308 return NT_STATUS_NOT_SUPPORTED;
5311 status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
5312 &caphigh);
5313 if (!NT_STATUS_IS_OK(status)) {
5314 printf("Server didn't return UNIX CIFS extensions: %s\n",
5315 nt_errstr(status));
5316 return status;
5319 status = cli_set_unix_extensions_capabilities(cli, major, minor,
5320 caplow, caphigh);
5321 if (!NT_STATUS_IS_OK(status)) {
5322 printf("Server doesn't support setting UNIX CIFS extensions: "
5323 "%s.\n", nt_errstr(status));
5324 return status;
5327 return NT_STATUS_OK;
5331 Test POSIX open /mkdir calls.
5333 static bool run_simple_posix_open_test(int dummy)
5335 static struct cli_state *cli1;
5336 const char *fname = "posix:file";
5337 const char *hname = "posix:hlink";
5338 const char *sname = "posix:symlink";
5339 const char *dname = "posix:dir";
5340 char buf[10];
5341 char namebuf[11];
5342 uint16_t fnum1 = (uint16_t)-1;
5343 SMB_STRUCT_STAT sbuf;
5344 bool correct = false;
5345 NTSTATUS status;
5346 size_t nread;
5348 printf("Starting simple POSIX open test\n");
5350 if (!torture_open_connection(&cli1, 0)) {
5351 return false;
5354 cli_sockopt(cli1, sockops);
5356 status = torture_setup_unix_extensions(cli1);
5357 if (!NT_STATUS_IS_OK(status)) {
5358 return false;
5361 cli_setatr(cli1, fname, 0, 0);
5362 cli_posix_unlink(cli1, fname);
5363 cli_setatr(cli1, dname, 0, 0);
5364 cli_posix_rmdir(cli1, dname);
5365 cli_setatr(cli1, hname, 0, 0);
5366 cli_posix_unlink(cli1, hname);
5367 cli_setatr(cli1, sname, 0, 0);
5368 cli_posix_unlink(cli1, sname);
5370 /* Create a directory. */
5371 status = cli_posix_mkdir(cli1, dname, 0777);
5372 if (!NT_STATUS_IS_OK(status)) {
5373 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
5374 goto out;
5377 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5378 0600, &fnum1);
5379 if (!NT_STATUS_IS_OK(status)) {
5380 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5381 goto out;
5384 /* Test ftruncate - set file size. */
5385 status = cli_ftruncate(cli1, fnum1, 1000);
5386 if (!NT_STATUS_IS_OK(status)) {
5387 printf("ftruncate failed (%s)\n", nt_errstr(status));
5388 goto out;
5391 /* Ensure st_size == 1000 */
5392 status = cli_posix_stat(cli1, fname, &sbuf);
5393 if (!NT_STATUS_IS_OK(status)) {
5394 printf("stat failed (%s)\n", nt_errstr(status));
5395 goto out;
5398 if (sbuf.st_ex_size != 1000) {
5399 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5400 goto out;
5403 /* Test ftruncate - set file size back to zero. */
5404 status = cli_ftruncate(cli1, fnum1, 0);
5405 if (!NT_STATUS_IS_OK(status)) {
5406 printf("ftruncate failed (%s)\n", nt_errstr(status));
5407 goto out;
5410 status = cli_close(cli1, fnum1);
5411 if (!NT_STATUS_IS_OK(status)) {
5412 printf("close failed (%s)\n", nt_errstr(status));
5413 goto out;
5416 /* Now open the file again for read only. */
5417 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5418 if (!NT_STATUS_IS_OK(status)) {
5419 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
5420 goto out;
5423 /* Now unlink while open. */
5424 status = cli_posix_unlink(cli1, fname);
5425 if (!NT_STATUS_IS_OK(status)) {
5426 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5427 goto out;
5430 status = cli_close(cli1, fnum1);
5431 if (!NT_STATUS_IS_OK(status)) {
5432 printf("close(2) failed (%s)\n", nt_errstr(status));
5433 goto out;
5436 /* Ensure the file has gone. */
5437 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5438 if (NT_STATUS_IS_OK(status)) {
5439 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
5440 goto out;
5443 /* Create again to test open with O_TRUNC. */
5444 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
5445 if (!NT_STATUS_IS_OK(status)) {
5446 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5447 goto out;
5450 /* Test ftruncate - set file size. */
5451 status = cli_ftruncate(cli1, fnum1, 1000);
5452 if (!NT_STATUS_IS_OK(status)) {
5453 printf("ftruncate failed (%s)\n", nt_errstr(status));
5454 goto out;
5457 /* Ensure st_size == 1000 */
5458 status = cli_posix_stat(cli1, fname, &sbuf);
5459 if (!NT_STATUS_IS_OK(status)) {
5460 printf("stat failed (%s)\n", nt_errstr(status));
5461 goto out;
5464 if (sbuf.st_ex_size != 1000) {
5465 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5466 goto out;
5469 status = cli_close(cli1, fnum1);
5470 if (!NT_STATUS_IS_OK(status)) {
5471 printf("close(2) failed (%s)\n", nt_errstr(status));
5472 goto out;
5475 /* Re-open with O_TRUNC. */
5476 status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
5477 if (!NT_STATUS_IS_OK(status)) {
5478 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5479 goto out;
5482 /* Ensure st_size == 0 */
5483 status = cli_posix_stat(cli1, fname, &sbuf);
5484 if (!NT_STATUS_IS_OK(status)) {
5485 printf("stat failed (%s)\n", nt_errstr(status));
5486 goto out;
5489 if (sbuf.st_ex_size != 0) {
5490 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
5491 goto out;
5494 status = cli_close(cli1, fnum1);
5495 if (!NT_STATUS_IS_OK(status)) {
5496 printf("close failed (%s)\n", nt_errstr(status));
5497 goto out;
5500 status = cli_posix_unlink(cli1, fname);
5501 if (!NT_STATUS_IS_OK(status)) {
5502 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5503 goto out;
5506 status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
5507 if (!NT_STATUS_IS_OK(status)) {
5508 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
5509 dname, nt_errstr(status));
5510 goto out;
5513 cli_close(cli1, fnum1);
5515 /* What happens when we try and POSIX open a directory for write ? */
5516 status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
5517 if (NT_STATUS_IS_OK(status)) {
5518 printf("POSIX open of directory %s succeeded, should have failed.\n", fname);
5519 goto out;
5520 } else {
5521 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
5522 NT_STATUS_FILE_IS_A_DIRECTORY)) {
5523 goto out;
5527 /* Create the file. */
5528 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5529 0600, &fnum1);
5530 if (!NT_STATUS_IS_OK(status)) {
5531 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5532 goto out;
5535 /* Write some data into it. */
5536 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5537 NULL);
5538 if (!NT_STATUS_IS_OK(status)) {
5539 printf("cli_write failed: %s\n", nt_errstr(status));
5540 goto out;
5543 cli_close(cli1, fnum1);
5545 /* Now create a hardlink. */
5546 status = cli_posix_hardlink(cli1, fname, hname);
5547 if (!NT_STATUS_IS_OK(status)) {
5548 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
5549 goto out;
5552 /* Now create a symlink. */
5553 status = cli_posix_symlink(cli1, fname, sname);
5554 if (!NT_STATUS_IS_OK(status)) {
5555 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
5556 goto out;
5559 /* Open the hardlink for read. */
5560 status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
5561 if (!NT_STATUS_IS_OK(status)) {
5562 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
5563 goto out;
5566 status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
5567 if (!NT_STATUS_IS_OK(status)) {
5568 printf("POSIX read of %s failed (%s)\n", hname,
5569 nt_errstr(status));
5570 goto out;
5571 } else if (nread != 10) {
5572 printf("POSIX read of %s failed. Received %ld, expected %d\n",
5573 hname, (unsigned long)nread, 10);
5574 goto out;
5577 if (memcmp(buf, "TEST DATA\n", 10)) {
5578 printf("invalid data read from hardlink\n");
5579 goto out;
5582 /* Do a POSIX lock/unlock. */
5583 status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
5584 if (!NT_STATUS_IS_OK(status)) {
5585 printf("POSIX lock failed %s\n", nt_errstr(status));
5586 goto out;
5589 /* Punch a hole in the locked area. */
5590 status = cli_posix_unlock(cli1, fnum1, 10, 80);
5591 if (!NT_STATUS_IS_OK(status)) {
5592 printf("POSIX unlock failed %s\n", nt_errstr(status));
5593 goto out;
5596 cli_close(cli1, fnum1);
5598 /* Open the symlink for read - this should fail. A POSIX
5599 client should not be doing opens on a symlink. */
5600 status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
5601 if (NT_STATUS_IS_OK(status)) {
5602 printf("POSIX open of %s succeeded (should have failed)\n", sname);
5603 goto out;
5604 } else {
5605 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
5606 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
5607 printf("POSIX open of %s should have failed "
5608 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
5609 "failed with %s instead.\n",
5610 sname, nt_errstr(status));
5611 goto out;
5615 status = cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf));
5616 if (!NT_STATUS_IS_OK(status)) {
5617 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
5618 goto out;
5621 if (strcmp(namebuf, fname) != 0) {
5622 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
5623 sname, fname, namebuf);
5624 goto out;
5627 status = cli_posix_rmdir(cli1, dname);
5628 if (!NT_STATUS_IS_OK(status)) {
5629 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
5630 goto out;
5633 printf("Simple POSIX open test passed\n");
5634 correct = true;
5636 out:
5638 if (fnum1 != (uint16_t)-1) {
5639 cli_close(cli1, fnum1);
5640 fnum1 = (uint16_t)-1;
5643 cli_setatr(cli1, sname, 0, 0);
5644 cli_posix_unlink(cli1, sname);
5645 cli_setatr(cli1, hname, 0, 0);
5646 cli_posix_unlink(cli1, hname);
5647 cli_setatr(cli1, fname, 0, 0);
5648 cli_posix_unlink(cli1, fname);
5649 cli_setatr(cli1, dname, 0, 0);
5650 cli_posix_rmdir(cli1, dname);
5652 if (!torture_close_connection(cli1)) {
5653 correct = false;
5656 return correct;
5660 static uint32 open_attrs_table[] = {
5661 FILE_ATTRIBUTE_NORMAL,
5662 FILE_ATTRIBUTE_ARCHIVE,
5663 FILE_ATTRIBUTE_READONLY,
5664 FILE_ATTRIBUTE_HIDDEN,
5665 FILE_ATTRIBUTE_SYSTEM,
5667 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
5668 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
5669 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
5670 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5671 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5672 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5674 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5675 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5676 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5677 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
5680 struct trunc_open_results {
5681 unsigned int num;
5682 uint32 init_attr;
5683 uint32 trunc_attr;
5684 uint32 result_attr;
5687 static struct trunc_open_results attr_results[] = {
5688 { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5689 { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5690 { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5691 { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5692 { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5693 { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5694 { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5695 { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5696 { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5697 { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5698 { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5699 { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
5700 { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5701 { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5702 { 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 },
5703 { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5704 { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5705 { 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 },
5706 { 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 },
5707 { 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 },
5708 { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5709 { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5710 { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5711 { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5712 { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5713 { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
5716 static bool run_openattrtest(int dummy)
5718 static struct cli_state *cli1;
5719 const char *fname = "\\openattr.file";
5720 uint16_t fnum1;
5721 bool correct = True;
5722 uint16 attr;
5723 unsigned int i, j, k, l;
5724 NTSTATUS status;
5726 printf("starting open attr test\n");
5728 if (!torture_open_connection(&cli1, 0)) {
5729 return False;
5732 cli_sockopt(cli1, sockops);
5734 for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32); i++) {
5735 cli_setatr(cli1, fname, 0, 0);
5736 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5738 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
5739 open_attrs_table[i], FILE_SHARE_NONE,
5740 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5741 if (!NT_STATUS_IS_OK(status)) {
5742 printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5743 return False;
5746 status = cli_close(cli1, fnum1);
5747 if (!NT_STATUS_IS_OK(status)) {
5748 printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5749 return False;
5752 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32); j++) {
5753 status = cli_ntcreate(cli1, fname, 0,
5754 FILE_READ_DATA|FILE_WRITE_DATA,
5755 open_attrs_table[j],
5756 FILE_SHARE_NONE, FILE_OVERWRITE,
5757 0, 0, &fnum1);
5758 if (!NT_STATUS_IS_OK(status)) {
5759 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5760 if (attr_results[l].num == k) {
5761 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
5762 k, open_attrs_table[i],
5763 open_attrs_table[j],
5764 fname, NT_STATUS_V(status), nt_errstr(status));
5765 correct = False;
5769 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5770 printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
5771 k, open_attrs_table[i], open_attrs_table[j],
5772 nt_errstr(status));
5773 correct = False;
5775 #if 0
5776 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
5777 #endif
5778 k++;
5779 continue;
5782 status = cli_close(cli1, fnum1);
5783 if (!NT_STATUS_IS_OK(status)) {
5784 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
5785 return False;
5788 status = cli_getatr(cli1, fname, &attr, NULL, NULL);
5789 if (!NT_STATUS_IS_OK(status)) {
5790 printf("getatr(2) failed (%s)\n", nt_errstr(status));
5791 return False;
5794 #if 0
5795 printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
5796 k, open_attrs_table[i], open_attrs_table[j], attr );
5797 #endif
5799 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5800 if (attr_results[l].num == k) {
5801 if (attr != attr_results[l].result_attr ||
5802 open_attrs_table[i] != attr_results[l].init_attr ||
5803 open_attrs_table[j] != attr_results[l].trunc_attr) {
5804 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
5805 open_attrs_table[i],
5806 open_attrs_table[j],
5807 (unsigned int)attr,
5808 attr_results[l].result_attr);
5809 correct = False;
5811 break;
5814 k++;
5818 cli_setatr(cli1, fname, 0, 0);
5819 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5821 printf("open attr test %s.\n", correct ? "passed" : "failed");
5823 if (!torture_close_connection(cli1)) {
5824 correct = False;
5826 return correct;
5829 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
5830 const char *name, void *state)
5832 int *matched = (int *)state;
5833 if (matched != NULL) {
5834 *matched += 1;
5836 return NT_STATUS_OK;
5840 test directory listing speed
5842 static bool run_dirtest(int dummy)
5844 int i;
5845 static struct cli_state *cli;
5846 uint16_t fnum;
5847 struct timeval core_start;
5848 bool correct = True;
5849 int matched;
5851 printf("starting directory test\n");
5853 if (!torture_open_connection(&cli, 0)) {
5854 return False;
5857 cli_sockopt(cli, sockops);
5859 srandom(0);
5860 for (i=0;i<torture_numops;i++) {
5861 fstring fname;
5862 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5863 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
5864 fprintf(stderr,"Failed to open %s\n", fname);
5865 return False;
5867 cli_close(cli, fnum);
5870 core_start = timeval_current();
5872 matched = 0;
5873 cli_list(cli, "a*.*", 0, list_fn, &matched);
5874 printf("Matched %d\n", matched);
5876 matched = 0;
5877 cli_list(cli, "b*.*", 0, list_fn, &matched);
5878 printf("Matched %d\n", matched);
5880 matched = 0;
5881 cli_list(cli, "xyzabc", 0, list_fn, &matched);
5882 printf("Matched %d\n", matched);
5884 printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
5886 srandom(0);
5887 for (i=0;i<torture_numops;i++) {
5888 fstring fname;
5889 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5890 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5893 if (!torture_close_connection(cli)) {
5894 correct = False;
5897 printf("finished dirtest\n");
5899 return correct;
5902 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
5903 void *state)
5905 struct cli_state *pcli = (struct cli_state *)state;
5906 fstring fname;
5907 slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
5909 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
5910 return NT_STATUS_OK;
5912 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
5913 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
5914 printf("del_fn: failed to rmdir %s\n,", fname );
5915 } else {
5916 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
5917 printf("del_fn: failed to unlink %s\n,", fname );
5919 return NT_STATUS_OK;
5924 sees what IOCTLs are supported
5926 bool torture_ioctl_test(int dummy)
5928 static struct cli_state *cli;
5929 uint16_t device, function;
5930 uint16_t fnum;
5931 const char *fname = "\\ioctl.dat";
5932 DATA_BLOB blob;
5933 NTSTATUS status;
5935 if (!torture_open_connection(&cli, 0)) {
5936 return False;
5939 printf("starting ioctl test\n");
5941 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5943 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5944 if (!NT_STATUS_IS_OK(status)) {
5945 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5946 return False;
5949 status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
5950 printf("ioctl device info: %s\n", nt_errstr(status));
5952 status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
5953 printf("ioctl job info: %s\n", nt_errstr(status));
5955 for (device=0;device<0x100;device++) {
5956 printf("ioctl test with device = 0x%x\n", device);
5957 for (function=0;function<0x100;function++) {
5958 uint32 code = (device<<16) | function;
5960 status = cli_raw_ioctl(cli, fnum, code, &blob);
5962 if (NT_STATUS_IS_OK(status)) {
5963 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
5964 (int)blob.length);
5965 data_blob_free(&blob);
5970 if (!torture_close_connection(cli)) {
5971 return False;
5974 return True;
5979 tries varients of chkpath
5981 bool torture_chkpath_test(int dummy)
5983 static struct cli_state *cli;
5984 uint16_t fnum;
5985 bool ret;
5986 NTSTATUS status;
5988 if (!torture_open_connection(&cli, 0)) {
5989 return False;
5992 printf("starting chkpath test\n");
5994 /* cleanup from an old run */
5995 cli_rmdir(cli, "\\chkpath.dir\\dir2");
5996 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5997 cli_rmdir(cli, "\\chkpath.dir");
5999 status = cli_mkdir(cli, "\\chkpath.dir");
6000 if (!NT_STATUS_IS_OK(status)) {
6001 printf("mkdir1 failed : %s\n", nt_errstr(status));
6002 return False;
6005 status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
6006 if (!NT_STATUS_IS_OK(status)) {
6007 printf("mkdir2 failed : %s\n", nt_errstr(status));
6008 return False;
6011 status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
6012 DENY_NONE, &fnum);
6013 if (!NT_STATUS_IS_OK(status)) {
6014 printf("open1 failed (%s)\n", nt_errstr(status));
6015 return False;
6017 cli_close(cli, fnum);
6019 status = cli_chkpath(cli, "\\chkpath.dir");
6020 if (!NT_STATUS_IS_OK(status)) {
6021 printf("chkpath1 failed: %s\n", nt_errstr(status));
6022 ret = False;
6025 status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
6026 if (!NT_STATUS_IS_OK(status)) {
6027 printf("chkpath2 failed: %s\n", nt_errstr(status));
6028 ret = False;
6031 status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
6032 if (!NT_STATUS_IS_OK(status)) {
6033 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
6034 NT_STATUS_NOT_A_DIRECTORY);
6035 } else {
6036 printf("* chkpath on a file should fail\n");
6037 ret = False;
6040 status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
6041 if (!NT_STATUS_IS_OK(status)) {
6042 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
6043 NT_STATUS_OBJECT_NAME_NOT_FOUND);
6044 } else {
6045 printf("* chkpath on a non existant file should fail\n");
6046 ret = False;
6049 status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
6050 if (!NT_STATUS_IS_OK(status)) {
6051 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
6052 NT_STATUS_OBJECT_PATH_NOT_FOUND);
6053 } else {
6054 printf("* chkpath on a non existent component should fail\n");
6055 ret = False;
6058 cli_rmdir(cli, "\\chkpath.dir\\dir2");
6059 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6060 cli_rmdir(cli, "\\chkpath.dir");
6062 if (!torture_close_connection(cli)) {
6063 return False;
6066 return ret;
6069 static bool run_eatest(int dummy)
6071 static struct cli_state *cli;
6072 const char *fname = "\\eatest.txt";
6073 bool correct = True;
6074 uint16_t fnum;
6075 int i;
6076 size_t num_eas;
6077 struct ea_struct *ea_list = NULL;
6078 TALLOC_CTX *mem_ctx = talloc_init("eatest");
6079 NTSTATUS status;
6081 printf("starting eatest\n");
6083 if (!torture_open_connection(&cli, 0)) {
6084 talloc_destroy(mem_ctx);
6085 return False;
6088 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6090 status = cli_ntcreate(cli, fname, 0,
6091 FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6092 FILE_SHARE_NONE, FILE_OVERWRITE_IF,
6093 0x4044, 0, &fnum);
6094 if (!NT_STATUS_IS_OK(status)) {
6095 printf("open failed - %s\n", nt_errstr(status));
6096 talloc_destroy(mem_ctx);
6097 return False;
6100 for (i = 0; i < 10; i++) {
6101 fstring ea_name, ea_val;
6103 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
6104 memset(ea_val, (char)i+1, i+1);
6105 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
6106 if (!NT_STATUS_IS_OK(status)) {
6107 printf("ea_set of name %s failed - %s\n", ea_name,
6108 nt_errstr(status));
6109 talloc_destroy(mem_ctx);
6110 return False;
6114 cli_close(cli, fnum);
6115 for (i = 0; i < 10; i++) {
6116 fstring ea_name, ea_val;
6118 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
6119 memset(ea_val, (char)i+1, i+1);
6120 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
6121 if (!NT_STATUS_IS_OK(status)) {
6122 printf("ea_set of name %s failed - %s\n", ea_name,
6123 nt_errstr(status));
6124 talloc_destroy(mem_ctx);
6125 return False;
6129 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6130 if (!NT_STATUS_IS_OK(status)) {
6131 printf("ea_get list failed - %s\n", nt_errstr(status));
6132 correct = False;
6135 printf("num_eas = %d\n", (int)num_eas);
6137 if (num_eas != 20) {
6138 printf("Should be 20 EA's stored... failing.\n");
6139 correct = False;
6142 for (i = 0; i < num_eas; i++) {
6143 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6144 dump_data(0, ea_list[i].value.data,
6145 ea_list[i].value.length);
6148 /* Setting EA's to zero length deletes them. Test this */
6149 printf("Now deleting all EA's - case indepenent....\n");
6151 #if 1
6152 cli_set_ea_path(cli, fname, "", "", 0);
6153 #else
6154 for (i = 0; i < 20; i++) {
6155 fstring ea_name;
6156 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
6157 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
6158 if (!NT_STATUS_IS_OK(status)) {
6159 printf("ea_set of name %s failed - %s\n", ea_name,
6160 nt_errstr(status));
6161 talloc_destroy(mem_ctx);
6162 return False;
6165 #endif
6167 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6168 if (!NT_STATUS_IS_OK(status)) {
6169 printf("ea_get list failed - %s\n", nt_errstr(status));
6170 correct = False;
6173 printf("num_eas = %d\n", (int)num_eas);
6174 for (i = 0; i < num_eas; i++) {
6175 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6176 dump_data(0, ea_list[i].value.data,
6177 ea_list[i].value.length);
6180 if (num_eas != 0) {
6181 printf("deleting EA's failed.\n");
6182 correct = False;
6185 /* Try and delete a non existant EA. */
6186 status = cli_set_ea_path(cli, fname, "foo", "", 0);
6187 if (!NT_STATUS_IS_OK(status)) {
6188 printf("deleting non-existant EA 'foo' should succeed. %s\n",
6189 nt_errstr(status));
6190 correct = False;
6193 talloc_destroy(mem_ctx);
6194 if (!torture_close_connection(cli)) {
6195 correct = False;
6198 return correct;
6201 static bool run_dirtest1(int dummy)
6203 int i;
6204 static struct cli_state *cli;
6205 uint16_t fnum;
6206 int num_seen;
6207 bool correct = True;
6209 printf("starting directory test\n");
6211 if (!torture_open_connection(&cli, 0)) {
6212 return False;
6215 cli_sockopt(cli, sockops);
6217 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6218 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6219 cli_rmdir(cli, "\\LISTDIR");
6220 cli_mkdir(cli, "\\LISTDIR");
6222 /* Create 1000 files and 1000 directories. */
6223 for (i=0;i<1000;i++) {
6224 fstring fname;
6225 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
6226 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6227 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum))) {
6228 fprintf(stderr,"Failed to open %s\n", fname);
6229 return False;
6231 cli_close(cli, fnum);
6233 for (i=0;i<1000;i++) {
6234 fstring fname;
6235 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
6236 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
6237 fprintf(stderr,"Failed to open %s\n", fname);
6238 return False;
6242 /* Now ensure that doing an old list sees both files and directories. */
6243 num_seen = 0;
6244 cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6245 printf("num_seen = %d\n", num_seen );
6246 /* We should see 100 files + 1000 directories + . and .. */
6247 if (num_seen != 2002)
6248 correct = False;
6250 /* Ensure if we have the "must have" bits we only see the
6251 * relevent entries.
6253 num_seen = 0;
6254 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6255 printf("num_seen = %d\n", num_seen );
6256 if (num_seen != 1002)
6257 correct = False;
6259 num_seen = 0;
6260 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6261 printf("num_seen = %d\n", num_seen );
6262 if (num_seen != 1000)
6263 correct = False;
6265 /* Delete everything. */
6266 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6267 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6268 cli_rmdir(cli, "\\LISTDIR");
6270 #if 0
6271 printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
6272 printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
6273 printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
6274 #endif
6276 if (!torture_close_connection(cli)) {
6277 correct = False;
6280 printf("finished dirtest1\n");
6282 return correct;
6285 static bool run_error_map_extract(int dummy) {
6287 static struct cli_state *c_dos;
6288 static struct cli_state *c_nt;
6289 NTSTATUS status;
6291 uint32 error;
6293 uint32 errnum;
6294 uint8 errclass;
6296 NTSTATUS nt_status;
6298 fstring user;
6300 /* NT-Error connection */
6302 disable_spnego = true;
6303 if (!(c_nt = open_nbt_connection())) {
6304 disable_spnego = false;
6305 return False;
6307 disable_spnego = false;
6309 status = cli_negprot(c_nt, PROTOCOL_NT1);
6311 if (!NT_STATUS_IS_OK(status)) {
6312 printf("%s rejected the NT-error negprot (%s)\n", host,
6313 nt_errstr(status));
6314 cli_shutdown(c_nt);
6315 return False;
6318 status = cli_session_setup(c_nt, "", "", 0, "", 0, workgroup);
6319 if (!NT_STATUS_IS_OK(status)) {
6320 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
6321 return False;
6324 /* DOS-Error connection */
6326 disable_spnego = true;
6327 force_dos_errors = true;
6328 if (!(c_dos = open_nbt_connection())) {
6329 disable_spnego = false;
6330 force_dos_errors = false;
6331 return False;
6333 disable_spnego = false;
6334 force_dos_errors = false;
6336 status = cli_negprot(c_dos, PROTOCOL_NT1);
6337 if (!NT_STATUS_IS_OK(status)) {
6338 printf("%s rejected the DOS-error negprot (%s)\n", host,
6339 nt_errstr(status));
6340 cli_shutdown(c_dos);
6341 return False;
6344 status = cli_session_setup(c_dos, "", "", 0, "", 0, workgroup);
6345 if (!NT_STATUS_IS_OK(status)) {
6346 printf("%s rejected the DOS-error initial session setup (%s)\n",
6347 host, nt_errstr(status));
6348 return False;
6351 c_nt->map_dos_errors = false;
6352 c_dos->map_dos_errors = false;
6354 for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
6355 fstr_sprintf(user, "%X", error);
6357 status = cli_session_setup(c_nt, user,
6358 password, strlen(password),
6359 password, strlen(password),
6360 workgroup);
6361 if (NT_STATUS_IS_OK(status)) {
6362 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
6365 /* Case #1: 32-bit NT errors */
6366 if (!NT_STATUS_IS_DOS(status)) {
6367 nt_status = status;
6368 } else {
6369 printf("/** Dos error on NT connection! (%s) */\n",
6370 nt_errstr(status));
6371 nt_status = NT_STATUS(0xc0000000);
6374 status = cli_session_setup(c_dos, user,
6375 password, strlen(password),
6376 password, strlen(password),
6377 workgroup);
6378 if (NT_STATUS_IS_OK(status)) {
6379 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
6382 /* Case #1: 32-bit NT errors */
6383 if (NT_STATUS_IS_DOS(status)) {
6384 printf("/** NT error on DOS connection! (%s) */\n",
6385 nt_errstr(status));
6386 errnum = errclass = 0;
6387 } else {
6388 errclass = NT_STATUS_DOS_CLASS(status);
6389 errnum = NT_STATUS_DOS_CODE(status);
6392 if (NT_STATUS_V(nt_status) != error) {
6393 printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
6394 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
6395 get_nt_error_c_code(talloc_tos(), nt_status));
6398 printf("\t{%s,\t%s,\t%s},\n",
6399 smb_dos_err_class(errclass),
6400 smb_dos_err_name(errclass, errnum),
6401 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
6403 return True;
6406 static bool run_sesssetup_bench(int dummy)
6408 static struct cli_state *c;
6409 const char *fname = "\\file.dat";
6410 uint16_t fnum;
6411 NTSTATUS status;
6412 int i;
6414 if (!torture_open_connection(&c, 0)) {
6415 return false;
6418 status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6419 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6420 FILE_DELETE_ON_CLOSE, 0, &fnum);
6421 if (!NT_STATUS_IS_OK(status)) {
6422 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
6423 return false;
6426 for (i=0; i<torture_numops; i++) {
6427 status = cli_session_setup(
6428 c, username,
6429 password, strlen(password),
6430 password, strlen(password),
6431 workgroup);
6432 if (!NT_STATUS_IS_OK(status)) {
6433 d_printf("(%s) cli_session_setup failed: %s\n",
6434 __location__, nt_errstr(status));
6435 return false;
6438 d_printf("\r%d ", (int)cli_state_get_uid(c));
6440 status = cli_ulogoff(c);
6441 if (!NT_STATUS_IS_OK(status)) {
6442 d_printf("(%s) cli_ulogoff failed: %s\n",
6443 __location__, nt_errstr(status));
6444 return false;
6448 return true;
6451 static bool subst_test(const char *str, const char *user, const char *domain,
6452 uid_t uid, gid_t gid, const char *expected)
6454 char *subst;
6455 bool result = true;
6457 subst = talloc_sub_specified(talloc_tos(), str, user, domain, uid, gid);
6459 if (strcmp(subst, expected) != 0) {
6460 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
6461 "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
6462 expected);
6463 result = false;
6466 TALLOC_FREE(subst);
6467 return result;
6470 static void chain1_open_completion(struct tevent_req *req)
6472 uint16_t fnum;
6473 NTSTATUS status;
6474 status = cli_openx_recv(req, &fnum);
6475 TALLOC_FREE(req);
6477 d_printf("cli_openx_recv returned %s: %d\n",
6478 nt_errstr(status),
6479 NT_STATUS_IS_OK(status) ? fnum : -1);
6482 static void chain1_write_completion(struct tevent_req *req)
6484 size_t written;
6485 NTSTATUS status;
6486 status = cli_write_andx_recv(req, &written);
6487 TALLOC_FREE(req);
6489 d_printf("cli_write_andx_recv returned %s: %d\n",
6490 nt_errstr(status),
6491 NT_STATUS_IS_OK(status) ? (int)written : -1);
6494 static void chain1_close_completion(struct tevent_req *req)
6496 NTSTATUS status;
6497 bool *done = (bool *)tevent_req_callback_data_void(req);
6499 status = cli_close_recv(req);
6500 *done = true;
6502 TALLOC_FREE(req);
6504 d_printf("cli_close returned %s\n", nt_errstr(status));
6507 static bool run_chain1(int dummy)
6509 struct cli_state *cli1;
6510 struct event_context *evt = event_context_init(NULL);
6511 struct tevent_req *reqs[3], *smbreqs[3];
6512 bool done = false;
6513 const char *str = "foobar";
6514 NTSTATUS status;
6516 printf("starting chain1 test\n");
6517 if (!torture_open_connection(&cli1, 0)) {
6518 return False;
6521 cli_sockopt(cli1, sockops);
6523 reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, "\\test",
6524 O_CREAT|O_RDWR, 0, &smbreqs[0]);
6525 if (reqs[0] == NULL) return false;
6526 tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
6529 reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
6530 (const uint8_t *)str, 0, strlen(str)+1,
6531 smbreqs, 1, &smbreqs[1]);
6532 if (reqs[1] == NULL) return false;
6533 tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
6535 reqs[2] = cli_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
6536 if (reqs[2] == NULL) return false;
6537 tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
6539 status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
6540 if (!NT_STATUS_IS_OK(status)) {
6541 return false;
6544 while (!done) {
6545 tevent_loop_once(evt);
6548 torture_close_connection(cli1);
6549 return True;
6552 static void chain2_sesssetup_completion(struct tevent_req *req)
6554 NTSTATUS status;
6555 status = cli_session_setup_guest_recv(req);
6556 d_printf("sesssetup returned %s\n", nt_errstr(status));
6559 static void chain2_tcon_completion(struct tevent_req *req)
6561 bool *done = (bool *)tevent_req_callback_data_void(req);
6562 NTSTATUS status;
6563 status = cli_tcon_andx_recv(req);
6564 d_printf("tcon_and_x returned %s\n", nt_errstr(status));
6565 *done = true;
6568 static bool run_chain2(int dummy)
6570 struct cli_state *cli1;
6571 struct event_context *evt = event_context_init(NULL);
6572 struct tevent_req *reqs[2], *smbreqs[2];
6573 bool done = false;
6574 NTSTATUS status;
6576 printf("starting chain2 test\n");
6577 status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
6578 port_to_use, SMB_SIGNING_DEFAULT, 0);
6579 if (!NT_STATUS_IS_OK(status)) {
6580 return False;
6583 cli_sockopt(cli1, sockops);
6585 reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
6586 &smbreqs[0]);
6587 if (reqs[0] == NULL) return false;
6588 tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
6590 reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
6591 "?????", NULL, 0, &smbreqs[1]);
6592 if (reqs[1] == NULL) return false;
6593 tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
6595 status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
6596 if (!NT_STATUS_IS_OK(status)) {
6597 return false;
6600 while (!done) {
6601 tevent_loop_once(evt);
6604 torture_close_connection(cli1);
6605 return True;
6609 struct torture_createdel_state {
6610 struct tevent_context *ev;
6611 struct cli_state *cli;
6614 static void torture_createdel_created(struct tevent_req *subreq);
6615 static void torture_createdel_closed(struct tevent_req *subreq);
6617 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
6618 struct tevent_context *ev,
6619 struct cli_state *cli,
6620 const char *name)
6622 struct tevent_req *req, *subreq;
6623 struct torture_createdel_state *state;
6625 req = tevent_req_create(mem_ctx, &state,
6626 struct torture_createdel_state);
6627 if (req == NULL) {
6628 return NULL;
6630 state->ev = ev;
6631 state->cli = cli;
6633 subreq = cli_ntcreate_send(
6634 state, ev, cli, name, 0,
6635 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
6636 FILE_ATTRIBUTE_NORMAL,
6637 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6638 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
6640 if (tevent_req_nomem(subreq, req)) {
6641 return tevent_req_post(req, ev);
6643 tevent_req_set_callback(subreq, torture_createdel_created, req);
6644 return req;
6647 static void torture_createdel_created(struct tevent_req *subreq)
6649 struct tevent_req *req = tevent_req_callback_data(
6650 subreq, struct tevent_req);
6651 struct torture_createdel_state *state = tevent_req_data(
6652 req, struct torture_createdel_state);
6653 NTSTATUS status;
6654 uint16_t fnum;
6656 status = cli_ntcreate_recv(subreq, &fnum);
6657 TALLOC_FREE(subreq);
6658 if (!NT_STATUS_IS_OK(status)) {
6659 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
6660 nt_errstr(status)));
6661 tevent_req_nterror(req, status);
6662 return;
6665 subreq = cli_close_send(state, state->ev, state->cli, fnum);
6666 if (tevent_req_nomem(subreq, req)) {
6667 return;
6669 tevent_req_set_callback(subreq, torture_createdel_closed, req);
6672 static void torture_createdel_closed(struct tevent_req *subreq)
6674 struct tevent_req *req = tevent_req_callback_data(
6675 subreq, struct tevent_req);
6676 NTSTATUS status;
6678 status = cli_close_recv(subreq);
6679 if (!NT_STATUS_IS_OK(status)) {
6680 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
6681 tevent_req_nterror(req, status);
6682 return;
6684 tevent_req_done(req);
6687 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
6689 return tevent_req_simple_recv_ntstatus(req);
6692 struct torture_createdels_state {
6693 struct tevent_context *ev;
6694 struct cli_state *cli;
6695 const char *base_name;
6696 int sent;
6697 int received;
6698 int num_files;
6699 struct tevent_req **reqs;
6702 static void torture_createdels_done(struct tevent_req *subreq);
6704 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
6705 struct tevent_context *ev,
6706 struct cli_state *cli,
6707 const char *base_name,
6708 int num_parallel,
6709 int num_files)
6711 struct tevent_req *req;
6712 struct torture_createdels_state *state;
6713 int i;
6715 req = tevent_req_create(mem_ctx, &state,
6716 struct torture_createdels_state);
6717 if (req == NULL) {
6718 return NULL;
6720 state->ev = ev;
6721 state->cli = cli;
6722 state->base_name = talloc_strdup(state, base_name);
6723 if (tevent_req_nomem(state->base_name, req)) {
6724 return tevent_req_post(req, ev);
6726 state->num_files = MAX(num_parallel, num_files);
6727 state->sent = 0;
6728 state->received = 0;
6730 state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
6731 if (tevent_req_nomem(state->reqs, req)) {
6732 return tevent_req_post(req, ev);
6735 for (i=0; i<num_parallel; i++) {
6736 char *name;
6738 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6739 state->sent);
6740 if (tevent_req_nomem(name, req)) {
6741 return tevent_req_post(req, ev);
6743 state->reqs[i] = torture_createdel_send(
6744 state->reqs, state->ev, state->cli, name);
6745 if (tevent_req_nomem(state->reqs[i], req)) {
6746 return tevent_req_post(req, ev);
6748 name = talloc_move(state->reqs[i], &name);
6749 tevent_req_set_callback(state->reqs[i],
6750 torture_createdels_done, req);
6751 state->sent += 1;
6753 return req;
6756 static void torture_createdels_done(struct tevent_req *subreq)
6758 struct tevent_req *req = tevent_req_callback_data(
6759 subreq, struct tevent_req);
6760 struct torture_createdels_state *state = tevent_req_data(
6761 req, struct torture_createdels_state);
6762 size_t num_parallel = talloc_array_length(state->reqs);
6763 NTSTATUS status;
6764 char *name;
6765 int i;
6767 status = torture_createdel_recv(subreq);
6768 if (!NT_STATUS_IS_OK(status)){
6769 DEBUG(10, ("torture_createdel_recv returned %s\n",
6770 nt_errstr(status)));
6771 TALLOC_FREE(subreq);
6772 tevent_req_nterror(req, status);
6773 return;
6776 for (i=0; i<num_parallel; i++) {
6777 if (subreq == state->reqs[i]) {
6778 break;
6781 if (i == num_parallel) {
6782 DEBUG(10, ("received something we did not send\n"));
6783 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
6784 return;
6786 TALLOC_FREE(state->reqs[i]);
6788 if (state->sent >= state->num_files) {
6789 tevent_req_done(req);
6790 return;
6793 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6794 state->sent);
6795 if (tevent_req_nomem(name, req)) {
6796 return;
6798 state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
6799 state->cli, name);
6800 if (tevent_req_nomem(state->reqs[i], req)) {
6801 return;
6803 name = talloc_move(state->reqs[i], &name);
6804 tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
6805 state->sent += 1;
6808 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
6810 return tevent_req_simple_recv_ntstatus(req);
6813 struct swallow_notify_state {
6814 struct tevent_context *ev;
6815 struct cli_state *cli;
6816 uint16_t fnum;
6817 uint32_t completion_filter;
6818 bool recursive;
6819 bool (*fn)(uint32_t action, const char *name, void *priv);
6820 void *priv;
6823 static void swallow_notify_done(struct tevent_req *subreq);
6825 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
6826 struct tevent_context *ev,
6827 struct cli_state *cli,
6828 uint16_t fnum,
6829 uint32_t completion_filter,
6830 bool recursive,
6831 bool (*fn)(uint32_t action,
6832 const char *name,
6833 void *priv),
6834 void *priv)
6836 struct tevent_req *req, *subreq;
6837 struct swallow_notify_state *state;
6839 req = tevent_req_create(mem_ctx, &state,
6840 struct swallow_notify_state);
6841 if (req == NULL) {
6842 return NULL;
6844 state->ev = ev;
6845 state->cli = cli;
6846 state->fnum = fnum;
6847 state->completion_filter = completion_filter;
6848 state->recursive = recursive;
6849 state->fn = fn;
6850 state->priv = priv;
6852 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6853 0xffff, state->completion_filter,
6854 state->recursive);
6855 if (tevent_req_nomem(subreq, req)) {
6856 return tevent_req_post(req, ev);
6858 tevent_req_set_callback(subreq, swallow_notify_done, req);
6859 return req;
6862 static void swallow_notify_done(struct tevent_req *subreq)
6864 struct tevent_req *req = tevent_req_callback_data(
6865 subreq, struct tevent_req);
6866 struct swallow_notify_state *state = tevent_req_data(
6867 req, struct swallow_notify_state);
6868 NTSTATUS status;
6869 uint32_t i, num_changes;
6870 struct notify_change *changes;
6872 status = cli_notify_recv(subreq, state, &num_changes, &changes);
6873 TALLOC_FREE(subreq);
6874 if (!NT_STATUS_IS_OK(status)) {
6875 DEBUG(10, ("cli_notify_recv returned %s\n",
6876 nt_errstr(status)));
6877 tevent_req_nterror(req, status);
6878 return;
6881 for (i=0; i<num_changes; i++) {
6882 state->fn(changes[i].action, changes[i].name, state->priv);
6884 TALLOC_FREE(changes);
6886 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6887 0xffff, state->completion_filter,
6888 state->recursive);
6889 if (tevent_req_nomem(subreq, req)) {
6890 return;
6892 tevent_req_set_callback(subreq, swallow_notify_done, req);
6895 static bool print_notifies(uint32_t action, const char *name, void *priv)
6897 if (DEBUGLEVEL > 5) {
6898 d_printf("%d %s\n", (int)action, name);
6900 return true;
6903 static void notify_bench_done(struct tevent_req *req)
6905 int *num_finished = (int *)tevent_req_callback_data_void(req);
6906 *num_finished += 1;
6909 static bool run_notify_bench(int dummy)
6911 const char *dname = "\\notify-bench";
6912 struct tevent_context *ev;
6913 NTSTATUS status;
6914 uint16_t dnum;
6915 struct tevent_req *req1;
6916 struct tevent_req *req2 = NULL;
6917 int i, num_unc_names;
6918 int num_finished = 0;
6920 printf("starting notify-bench test\n");
6922 if (use_multishare_conn) {
6923 char **unc_list;
6924 unc_list = file_lines_load(multishare_conn_fname,
6925 &num_unc_names, 0, NULL);
6926 if (!unc_list || num_unc_names <= 0) {
6927 d_printf("Failed to load unc names list from '%s'\n",
6928 multishare_conn_fname);
6929 return false;
6931 TALLOC_FREE(unc_list);
6932 } else {
6933 num_unc_names = 1;
6936 ev = tevent_context_init(talloc_tos());
6937 if (ev == NULL) {
6938 d_printf("tevent_context_init failed\n");
6939 return false;
6942 for (i=0; i<num_unc_names; i++) {
6943 struct cli_state *cli;
6944 char *base_fname;
6946 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
6947 dname, i);
6948 if (base_fname == NULL) {
6949 return false;
6952 if (!torture_open_connection(&cli, i)) {
6953 return false;
6956 status = cli_ntcreate(cli, dname, 0,
6957 MAXIMUM_ALLOWED_ACCESS,
6958 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
6959 FILE_SHARE_DELETE,
6960 FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
6961 &dnum);
6963 if (!NT_STATUS_IS_OK(status)) {
6964 d_printf("Could not create %s: %s\n", dname,
6965 nt_errstr(status));
6966 return false;
6969 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
6970 FILE_NOTIFY_CHANGE_FILE_NAME |
6971 FILE_NOTIFY_CHANGE_DIR_NAME |
6972 FILE_NOTIFY_CHANGE_ATTRIBUTES |
6973 FILE_NOTIFY_CHANGE_LAST_WRITE,
6974 false, print_notifies, NULL);
6975 if (req1 == NULL) {
6976 d_printf("Could not create notify request\n");
6977 return false;
6980 req2 = torture_createdels_send(talloc_tos(), ev, cli,
6981 base_fname, 10, torture_numops);
6982 if (req2 == NULL) {
6983 d_printf("Could not create createdels request\n");
6984 return false;
6986 TALLOC_FREE(base_fname);
6988 tevent_req_set_callback(req2, notify_bench_done,
6989 &num_finished);
6992 while (num_finished < num_unc_names) {
6993 int ret;
6994 ret = tevent_loop_once(ev);
6995 if (ret != 0) {
6996 d_printf("tevent_loop_once failed\n");
6997 return false;
7001 if (!tevent_req_poll(req2, ev)) {
7002 d_printf("tevent_req_poll failed\n");
7005 status = torture_createdels_recv(req2);
7006 d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
7008 return true;
7011 static bool run_mangle1(int dummy)
7013 struct cli_state *cli;
7014 const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
7015 uint16_t fnum;
7016 fstring alt_name;
7017 NTSTATUS status;
7018 time_t change_time, access_time, write_time;
7019 off_t size;
7020 uint16_t mode;
7022 printf("starting mangle1 test\n");
7023 if (!torture_open_connection(&cli, 0)) {
7024 return False;
7027 cli_sockopt(cli, sockops);
7029 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
7030 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
7031 0, 0, &fnum);
7032 if (!NT_STATUS_IS_OK(status)) {
7033 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
7034 return false;
7036 cli_close(cli, fnum);
7038 status = cli_qpathinfo_alt_name(cli, fname, alt_name);
7039 if (!NT_STATUS_IS_OK(status)) {
7040 d_printf("cli_qpathinfo_alt_name failed: %s\n",
7041 nt_errstr(status));
7042 return false;
7044 d_printf("alt_name: %s\n", alt_name);
7046 status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
7047 if (!NT_STATUS_IS_OK(status)) {
7048 d_printf("cli_openx(%s) failed: %s\n", alt_name,
7049 nt_errstr(status));
7050 return false;
7052 cli_close(cli, fnum);
7054 status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
7055 &write_time, &size, &mode);
7056 if (!NT_STATUS_IS_OK(status)) {
7057 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
7058 nt_errstr(status));
7059 return false;
7062 return true;
7065 static size_t null_source(uint8_t *buf, size_t n, void *priv)
7067 size_t *to_pull = (size_t *)priv;
7068 size_t thistime = *to_pull;
7070 thistime = MIN(thistime, n);
7071 if (thistime == 0) {
7072 return 0;
7075 memset(buf, 0, thistime);
7076 *to_pull -= thistime;
7077 return thistime;
7080 static bool run_windows_write(int dummy)
7082 struct cli_state *cli1;
7083 uint16_t fnum;
7084 int i;
7085 bool ret = false;
7086 const char *fname = "\\writetest.txt";
7087 struct timeval start_time;
7088 double seconds;
7089 double kbytes;
7090 NTSTATUS status;
7092 printf("starting windows_write test\n");
7093 if (!torture_open_connection(&cli1, 0)) {
7094 return False;
7097 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
7098 if (!NT_STATUS_IS_OK(status)) {
7099 printf("open failed (%s)\n", nt_errstr(status));
7100 return False;
7103 cli_sockopt(cli1, sockops);
7105 start_time = timeval_current();
7107 for (i=0; i<torture_numops; i++) {
7108 uint8_t c = 0;
7109 off_t start = i * torture_blocksize;
7110 size_t to_pull = torture_blocksize - 1;
7112 status = cli_writeall(cli1, fnum, 0, &c,
7113 start + torture_blocksize - 1, 1, NULL);
7114 if (!NT_STATUS_IS_OK(status)) {
7115 printf("cli_write failed: %s\n", nt_errstr(status));
7116 goto fail;
7119 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
7120 null_source, &to_pull);
7121 if (!NT_STATUS_IS_OK(status)) {
7122 printf("cli_push returned: %s\n", nt_errstr(status));
7123 goto fail;
7127 seconds = timeval_elapsed(&start_time);
7128 kbytes = (double)torture_blocksize * torture_numops;
7129 kbytes /= 1024;
7131 printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
7132 (double)seconds, (int)(kbytes/seconds));
7134 ret = true;
7135 fail:
7136 cli_close(cli1, fnum);
7137 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7138 torture_close_connection(cli1);
7139 return ret;
7142 static bool run_cli_echo(int dummy)
7144 struct cli_state *cli;
7145 NTSTATUS status;
7147 printf("starting cli_echo test\n");
7148 if (!torture_open_connection(&cli, 0)) {
7149 return false;
7151 cli_sockopt(cli, sockops);
7153 status = cli_echo(cli, 5, data_blob_const("hello", 5));
7155 d_printf("cli_echo returned %s\n", nt_errstr(status));
7157 torture_close_connection(cli);
7158 return NT_STATUS_IS_OK(status);
7161 static bool run_uid_regression_test(int dummy)
7163 static struct cli_state *cli;
7164 int16_t old_vuid;
7165 int16_t old_cnum;
7166 bool correct = True;
7167 NTSTATUS status;
7169 printf("starting uid regression test\n");
7171 if (!torture_open_connection(&cli, 0)) {
7172 return False;
7175 cli_sockopt(cli, sockops);
7177 /* Ok - now save then logoff our current user. */
7178 old_vuid = cli_state_get_uid(cli);
7180 status = cli_ulogoff(cli);
7181 if (!NT_STATUS_IS_OK(status)) {
7182 d_printf("(%s) cli_ulogoff failed: %s\n",
7183 __location__, nt_errstr(status));
7184 correct = false;
7185 goto out;
7188 cli_state_set_uid(cli, old_vuid);
7190 /* Try an operation. */
7191 status = cli_mkdir(cli, "\\uid_reg_test");
7192 if (NT_STATUS_IS_OK(status)) {
7193 d_printf("(%s) cli_mkdir succeeded\n",
7194 __location__);
7195 correct = false;
7196 goto out;
7197 } else {
7198 /* Should be bad uid. */
7199 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
7200 NT_STATUS_USER_SESSION_DELETED)) {
7201 correct = false;
7202 goto out;
7206 old_cnum = cli_state_get_tid(cli);
7208 /* Now try a SMBtdis with the invald vuid set to zero. */
7209 cli_state_set_uid(cli, 0);
7211 /* This should succeed. */
7212 status = cli_tdis(cli);
7214 if (NT_STATUS_IS_OK(status)) {
7215 d_printf("First tdis with invalid vuid should succeed.\n");
7216 } else {
7217 d_printf("First tdis failed (%s)\n", nt_errstr(status));
7218 correct = false;
7219 goto out;
7222 cli_state_set_uid(cli, old_vuid);
7223 cli_state_set_tid(cli, old_cnum);
7225 /* This should fail. */
7226 status = cli_tdis(cli);
7227 if (NT_STATUS_IS_OK(status)) {
7228 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
7229 correct = false;
7230 goto out;
7231 } else {
7232 /* Should be bad tid. */
7233 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
7234 NT_STATUS_NETWORK_NAME_DELETED)) {
7235 correct = false;
7236 goto out;
7240 cli_rmdir(cli, "\\uid_reg_test");
7242 out:
7244 cli_shutdown(cli);
7245 return correct;
7249 static const char *illegal_chars = "*\\/?<>|\":";
7250 static char force_shortname_chars[] = " +,.[];=\177";
7252 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
7253 const char *mask, void *state)
7255 struct cli_state *pcli = (struct cli_state *)state;
7256 fstring fname;
7257 NTSTATUS status = NT_STATUS_OK;
7259 slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
7261 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
7262 return NT_STATUS_OK;
7264 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
7265 status = cli_rmdir(pcli, fname);
7266 if (!NT_STATUS_IS_OK(status)) {
7267 printf("del_fn: failed to rmdir %s\n,", fname );
7269 } else {
7270 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7271 if (!NT_STATUS_IS_OK(status)) {
7272 printf("del_fn: failed to unlink %s\n,", fname );
7275 return status;
7278 struct sn_state {
7279 int matched;
7280 int i;
7281 bool val;
7284 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
7285 const char *name, void *state)
7287 struct sn_state *s = (struct sn_state *)state;
7288 int i = s->i;
7290 #if 0
7291 printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
7292 i, finfo->name, finfo->short_name);
7293 #endif
7295 if (strchr(force_shortname_chars, i)) {
7296 if (!finfo->short_name) {
7297 /* Shortname not created when it should be. */
7298 d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
7299 __location__, finfo->name, i);
7300 s->val = true;
7302 } else if (finfo->short_name){
7303 /* Shortname created when it should not be. */
7304 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
7305 __location__, finfo->short_name, finfo->name);
7306 s->val = true;
7308 s->matched += 1;
7309 return NT_STATUS_OK;
7312 static bool run_shortname_test(int dummy)
7314 static struct cli_state *cli;
7315 bool correct = True;
7316 int i;
7317 struct sn_state s;
7318 char fname[40];
7319 NTSTATUS status;
7321 printf("starting shortname test\n");
7323 if (!torture_open_connection(&cli, 0)) {
7324 return False;
7327 cli_sockopt(cli, sockops);
7329 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7330 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7331 cli_rmdir(cli, "\\shortname");
7333 status = cli_mkdir(cli, "\\shortname");
7334 if (!NT_STATUS_IS_OK(status)) {
7335 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
7336 __location__, nt_errstr(status));
7337 correct = false;
7338 goto out;
7341 if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
7342 correct = false;
7343 goto out;
7345 if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
7346 correct = false;
7347 goto out;
7350 s.val = false;
7352 for (i = 32; i < 128; i++) {
7353 uint16_t fnum = (uint16_t)-1;
7355 s.i = i;
7357 if (strchr(illegal_chars, i)) {
7358 continue;
7360 fname[15] = i;
7362 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
7363 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum);
7364 if (!NT_STATUS_IS_OK(status)) {
7365 d_printf("(%s) cli_nt_create of %s failed: %s\n",
7366 __location__, fname, nt_errstr(status));
7367 correct = false;
7368 goto out;
7370 cli_close(cli, fnum);
7372 s.matched = 0;
7373 status = cli_list(cli, "\\shortname\\test*.*", 0,
7374 shortname_list_fn, &s);
7375 if (s.matched != 1) {
7376 d_printf("(%s) failed to list %s: %s\n",
7377 __location__, fname, nt_errstr(status));
7378 correct = false;
7379 goto out;
7382 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7383 if (!NT_STATUS_IS_OK(status)) {
7384 d_printf("(%s) failed to delete %s: %s\n",
7385 __location__, fname, nt_errstr(status));
7386 correct = false;
7387 goto out;
7390 if (s.val) {
7391 correct = false;
7392 goto out;
7396 out:
7398 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7399 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7400 cli_rmdir(cli, "\\shortname");
7401 torture_close_connection(cli);
7402 return correct;
7405 static void pagedsearch_cb(struct tevent_req *req)
7407 int rc;
7408 struct tldap_message *msg;
7409 char *dn;
7411 rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
7412 if (rc != TLDAP_SUCCESS) {
7413 d_printf("tldap_search_paged_recv failed: %s\n",
7414 tldap_err2string(rc));
7415 return;
7417 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
7418 TALLOC_FREE(msg);
7419 return;
7421 if (!tldap_entry_dn(msg, &dn)) {
7422 d_printf("tldap_entry_dn failed\n");
7423 return;
7425 d_printf("%s\n", dn);
7426 TALLOC_FREE(msg);
7429 static bool run_tldap(int dummy)
7431 struct tldap_context *ld;
7432 int fd, rc;
7433 NTSTATUS status;
7434 struct sockaddr_storage addr;
7435 struct tevent_context *ev;
7436 struct tevent_req *req;
7437 char *basedn;
7438 const char *filter;
7440 if (!resolve_name(host, &addr, 0, false)) {
7441 d_printf("could not find host %s\n", host);
7442 return false;
7444 status = open_socket_out(&addr, 389, 9999, &fd);
7445 if (!NT_STATUS_IS_OK(status)) {
7446 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
7447 return false;
7450 ld = tldap_context_create(talloc_tos(), fd);
7451 if (ld == NULL) {
7452 close(fd);
7453 d_printf("tldap_context_create failed\n");
7454 return false;
7457 rc = tldap_fetch_rootdse(ld);
7458 if (rc != TLDAP_SUCCESS) {
7459 d_printf("tldap_fetch_rootdse failed: %s\n",
7460 tldap_errstr(talloc_tos(), ld, rc));
7461 return false;
7464 basedn = tldap_talloc_single_attribute(
7465 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
7466 if (basedn == NULL) {
7467 d_printf("no defaultNamingContext\n");
7468 return false;
7470 d_printf("defaultNamingContext: %s\n", basedn);
7472 ev = tevent_context_init(talloc_tos());
7473 if (ev == NULL) {
7474 d_printf("tevent_context_init failed\n");
7475 return false;
7478 req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
7479 TLDAP_SCOPE_SUB, "(objectclass=*)",
7480 NULL, 0, 0,
7481 NULL, 0, NULL, 0, 0, 0, 0, 5);
7482 if (req == NULL) {
7483 d_printf("tldap_search_paged_send failed\n");
7484 return false;
7486 tevent_req_set_callback(req, pagedsearch_cb, NULL);
7488 tevent_req_poll(req, ev);
7490 TALLOC_FREE(req);
7492 /* test search filters against rootDSE */
7493 filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
7494 "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
7496 rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
7497 NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
7498 talloc_tos(), NULL, NULL);
7499 if (rc != TLDAP_SUCCESS) {
7500 d_printf("tldap_search with complex filter failed: %s\n",
7501 tldap_errstr(talloc_tos(), ld, rc));
7502 return false;
7505 TALLOC_FREE(ld);
7506 return true;
7509 /* Torture test to ensure no regression of :
7510 https://bugzilla.samba.org/show_bug.cgi?id=7084
7513 static bool run_dir_createtime(int dummy)
7515 struct cli_state *cli;
7516 const char *dname = "\\testdir";
7517 const char *fname = "\\testdir\\testfile";
7518 NTSTATUS status;
7519 struct timespec create_time;
7520 struct timespec create_time1;
7521 uint16_t fnum;
7522 bool ret = false;
7524 if (!torture_open_connection(&cli, 0)) {
7525 return false;
7528 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7529 cli_rmdir(cli, dname);
7531 status = cli_mkdir(cli, dname);
7532 if (!NT_STATUS_IS_OK(status)) {
7533 printf("mkdir failed: %s\n", nt_errstr(status));
7534 goto out;
7537 status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
7538 NULL, NULL, NULL);
7539 if (!NT_STATUS_IS_OK(status)) {
7540 printf("cli_qpathinfo2 returned %s\n",
7541 nt_errstr(status));
7542 goto out;
7545 /* Sleep 3 seconds, then create a file. */
7546 sleep(3);
7548 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
7549 DENY_NONE, &fnum);
7550 if (!NT_STATUS_IS_OK(status)) {
7551 printf("cli_openx failed: %s\n", nt_errstr(status));
7552 goto out;
7555 status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
7556 NULL, NULL, NULL);
7557 if (!NT_STATUS_IS_OK(status)) {
7558 printf("cli_qpathinfo2 (2) returned %s\n",
7559 nt_errstr(status));
7560 goto out;
7563 if (timespec_compare(&create_time1, &create_time)) {
7564 printf("run_dir_createtime: create time was updated (error)\n");
7565 } else {
7566 printf("run_dir_createtime: create time was not updated (correct)\n");
7567 ret = true;
7570 out:
7572 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7573 cli_rmdir(cli, dname);
7574 if (!torture_close_connection(cli)) {
7575 ret = false;
7577 return ret;
7581 static bool run_streamerror(int dummy)
7583 struct cli_state *cli;
7584 const char *dname = "\\testdir";
7585 const char *streamname =
7586 "testdir:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
7587 NTSTATUS status;
7588 time_t change_time, access_time, write_time;
7589 off_t size;
7590 uint16_t mode, fnum;
7591 bool ret = true;
7593 if (!torture_open_connection(&cli, 0)) {
7594 return false;
7597 cli_unlink(cli, "\\testdir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7598 cli_rmdir(cli, dname);
7600 status = cli_mkdir(cli, dname);
7601 if (!NT_STATUS_IS_OK(status)) {
7602 printf("mkdir failed: %s\n", nt_errstr(status));
7603 return false;
7606 status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
7607 &write_time, &size, &mode);
7608 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7609 printf("pathinfo returned %s, expected "
7610 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
7611 nt_errstr(status));
7612 ret = false;
7615 status = cli_ntcreate(cli, streamname, 0x16,
7616 FILE_READ_DATA|FILE_READ_EA|
7617 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
7618 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7619 FILE_OPEN, 0, 0, &fnum);
7621 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7622 printf("ntcreate returned %s, expected "
7623 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
7624 nt_errstr(status));
7625 ret = false;
7629 cli_rmdir(cli, dname);
7630 return ret;
7633 static bool run_local_substitute(int dummy)
7635 bool ok = true;
7637 ok &= subst_test("%U", "bla", "", -1, -1, "bla");
7638 ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
7639 ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
7640 ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
7641 ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
7642 ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
7643 ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
7644 ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
7646 /* Different captialization rules in sub_basic... */
7648 ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
7649 "blaDOM") == 0);
7651 return ok;
7654 static bool run_local_base64(int dummy)
7656 int i;
7657 bool ret = true;
7659 for (i=1; i<2000; i++) {
7660 DATA_BLOB blob1, blob2;
7661 char *b64;
7663 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
7664 blob1.length = i;
7665 generate_random_buffer(blob1.data, blob1.length);
7667 b64 = base64_encode_data_blob(talloc_tos(), blob1);
7668 if (b64 == NULL) {
7669 d_fprintf(stderr, "base64_encode_data_blob failed "
7670 "for %d bytes\n", i);
7671 ret = false;
7673 blob2 = base64_decode_data_blob(b64);
7674 TALLOC_FREE(b64);
7676 if (data_blob_cmp(&blob1, &blob2)) {
7677 d_fprintf(stderr, "data_blob_cmp failed for %d "
7678 "bytes\n", i);
7679 ret = false;
7681 TALLOC_FREE(blob1.data);
7682 data_blob_free(&blob2);
7684 return ret;
7687 static bool run_local_gencache(int dummy)
7689 char *val;
7690 time_t tm;
7691 DATA_BLOB blob;
7693 if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
7694 d_printf("%s: gencache_set() failed\n", __location__);
7695 return False;
7698 if (!gencache_get("foo", NULL, NULL)) {
7699 d_printf("%s: gencache_get() failed\n", __location__);
7700 return False;
7703 if (!gencache_get("foo", &val, &tm)) {
7704 d_printf("%s: gencache_get() failed\n", __location__);
7705 return False;
7708 if (strcmp(val, "bar") != 0) {
7709 d_printf("%s: gencache_get() returned %s, expected %s\n",
7710 __location__, val, "bar");
7711 SAFE_FREE(val);
7712 return False;
7715 SAFE_FREE(val);
7717 if (!gencache_del("foo")) {
7718 d_printf("%s: gencache_del() failed\n", __location__);
7719 return False;
7721 if (gencache_del("foo")) {
7722 d_printf("%s: second gencache_del() succeeded\n",
7723 __location__);
7724 return False;
7727 if (gencache_get("foo", &val, &tm)) {
7728 d_printf("%s: gencache_get() on deleted entry "
7729 "succeeded\n", __location__);
7730 return False;
7733 blob = data_blob_string_const_null("bar");
7734 tm = time(NULL) + 60;
7736 if (!gencache_set_data_blob("foo", &blob, tm)) {
7737 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
7738 return False;
7741 if (!gencache_get_data_blob("foo", &blob, NULL, NULL)) {
7742 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
7743 return False;
7746 if (strcmp((const char *)blob.data, "bar") != 0) {
7747 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
7748 __location__, (const char *)blob.data, "bar");
7749 data_blob_free(&blob);
7750 return False;
7753 data_blob_free(&blob);
7755 if (!gencache_del("foo")) {
7756 d_printf("%s: gencache_del() failed\n", __location__);
7757 return False;
7759 if (gencache_del("foo")) {
7760 d_printf("%s: second gencache_del() succeeded\n",
7761 __location__);
7762 return False;
7765 if (gencache_get_data_blob("foo", &blob, NULL, NULL)) {
7766 d_printf("%s: gencache_get_data_blob() on deleted entry "
7767 "succeeded\n", __location__);
7768 return False;
7771 return True;
7774 static bool rbt_testval(struct db_context *db, const char *key,
7775 const char *value)
7777 struct db_record *rec;
7778 TDB_DATA data = string_tdb_data(value);
7779 bool ret = false;
7780 NTSTATUS status;
7781 TDB_DATA dbvalue;
7783 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
7784 if (rec == NULL) {
7785 d_fprintf(stderr, "fetch_locked failed\n");
7786 goto done;
7788 status = dbwrap_record_store(rec, data, 0);
7789 if (!NT_STATUS_IS_OK(status)) {
7790 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
7791 goto done;
7793 TALLOC_FREE(rec);
7795 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
7796 if (rec == NULL) {
7797 d_fprintf(stderr, "second fetch_locked failed\n");
7798 goto done;
7801 dbvalue = dbwrap_record_get_value(rec);
7802 if ((dbvalue.dsize != data.dsize)
7803 || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
7804 d_fprintf(stderr, "Got wrong data back\n");
7805 goto done;
7808 ret = true;
7809 done:
7810 TALLOC_FREE(rec);
7811 return ret;
7814 static bool run_local_rbtree(int dummy)
7816 struct db_context *db;
7817 bool ret = false;
7818 int i;
7820 db = db_open_rbt(NULL);
7822 if (db == NULL) {
7823 d_fprintf(stderr, "db_open_rbt failed\n");
7824 return false;
7827 for (i=0; i<1000; i++) {
7828 char *key, *value;
7830 if (asprintf(&key, "key%ld", random()) == -1) {
7831 goto done;
7833 if (asprintf(&value, "value%ld", random()) == -1) {
7834 SAFE_FREE(key);
7835 goto done;
7838 if (!rbt_testval(db, key, value)) {
7839 SAFE_FREE(key);
7840 SAFE_FREE(value);
7841 goto done;
7844 SAFE_FREE(value);
7845 if (asprintf(&value, "value%ld", random()) == -1) {
7846 SAFE_FREE(key);
7847 goto done;
7850 if (!rbt_testval(db, key, value)) {
7851 SAFE_FREE(key);
7852 SAFE_FREE(value);
7853 goto done;
7856 SAFE_FREE(key);
7857 SAFE_FREE(value);
7860 ret = true;
7862 done:
7863 TALLOC_FREE(db);
7864 return ret;
7869 local test for character set functions
7871 This is a very simple test for the functionality in convert_string_error()
7873 static bool run_local_convert_string(int dummy)
7875 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
7876 const char *test_strings[2] = { "March", "M\303\244rz" };
7877 char dst[7];
7878 int i;
7880 for (i=0; i<2; i++) {
7881 const char *str = test_strings[i];
7882 int len = strlen(str);
7883 size_t converted_size;
7884 bool ret;
7886 memset(dst, 'X', sizeof(dst));
7888 /* first try with real source length */
7889 ret = convert_string_error(CH_UNIX, CH_UTF8,
7890 str, len,
7891 dst, sizeof(dst),
7892 &converted_size);
7893 if (ret != true) {
7894 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
7895 goto failed;
7898 if (converted_size != len) {
7899 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
7900 str, len, (int)converted_size);
7901 goto failed;
7904 if (strncmp(str, dst, converted_size) != 0) {
7905 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
7906 goto failed;
7909 if (strlen(str) != converted_size) {
7910 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
7911 (int)strlen(str), (int)converted_size);
7912 goto failed;
7915 if (dst[converted_size] != 'X') {
7916 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
7917 goto failed;
7920 /* now with srclen==-1, this causes the nul to be
7921 * converted too */
7922 ret = convert_string_error(CH_UNIX, CH_UTF8,
7923 str, -1,
7924 dst, sizeof(dst),
7925 &converted_size);
7926 if (ret != true) {
7927 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
7928 goto failed;
7931 if (converted_size != len+1) {
7932 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
7933 str, len, (int)converted_size);
7934 goto failed;
7937 if (strncmp(str, dst, converted_size) != 0) {
7938 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
7939 goto failed;
7942 if (len+1 != converted_size) {
7943 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
7944 len+1, (int)converted_size);
7945 goto failed;
7948 if (dst[converted_size] != 'X') {
7949 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
7950 goto failed;
7956 TALLOC_FREE(tmp_ctx);
7957 return true;
7958 failed:
7959 TALLOC_FREE(tmp_ctx);
7960 return false;
7964 struct talloc_dict_test {
7965 int content;
7968 static int talloc_dict_traverse_fn(DATA_BLOB key, void *data, void *priv)
7970 int *count = (int *)priv;
7971 *count += 1;
7972 return 0;
7975 static bool run_local_talloc_dict(int dummy)
7977 struct talloc_dict *dict;
7978 struct talloc_dict_test *t;
7979 int key, count, res;
7980 bool ok;
7982 dict = talloc_dict_init(talloc_tos());
7983 if (dict == NULL) {
7984 return false;
7987 t = talloc(talloc_tos(), struct talloc_dict_test);
7988 if (t == NULL) {
7989 return false;
7992 key = 1;
7993 t->content = 1;
7994 ok = talloc_dict_set(dict, data_blob_const(&key, sizeof(key)), &t);
7995 if (!ok) {
7996 return false;
7999 count = 0;
8000 res = talloc_dict_traverse(dict, talloc_dict_traverse_fn, &count);
8001 if (res == -1) {
8002 return false;
8005 if (count != 1) {
8006 return false;
8009 if (count != res) {
8010 return false;
8013 TALLOC_FREE(dict);
8015 return true;
8018 static bool run_local_string_to_sid(int dummy) {
8019 struct dom_sid sid;
8021 if (string_to_sid(&sid, "S--1-5-32-545")) {
8022 printf("allowing S--1-5-32-545\n");
8023 return false;
8025 if (string_to_sid(&sid, "S-1-5-32-+545")) {
8026 printf("allowing S-1-5-32-+545\n");
8027 return false;
8029 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")) {
8030 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
8031 return false;
8033 if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
8034 printf("allowing S-1-5-32-545-abc\n");
8035 return false;
8037 if (!string_to_sid(&sid, "S-1-5-32-545")) {
8038 printf("could not parse S-1-5-32-545\n");
8039 return false;
8041 if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
8042 printf("mis-parsed S-1-5-32-545 as %s\n",
8043 sid_string_tos(&sid));
8044 return false;
8046 return true;
8049 static bool run_local_binary_to_sid(int dummy) {
8050 struct dom_sid *sid = talloc(NULL, struct dom_sid);
8051 static const char good_binary_sid[] = {
8052 0x1, /* revision number */
8053 15, /* num auths */
8054 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8055 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8056 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8057 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8058 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8059 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8060 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8061 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8062 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8063 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8064 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8065 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8066 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8067 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8068 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8069 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8072 static const char long_binary_sid[] = {
8073 0x1, /* revision number */
8074 15, /* num auths */
8075 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8076 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8077 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8078 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8079 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8080 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8081 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8082 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8083 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8084 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8085 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8086 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8087 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8088 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8089 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8090 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8091 0x1, 0x1, 0x1, 0x1, /* auth[15] */
8092 0x1, 0x1, 0x1, 0x1, /* auth[16] */
8093 0x1, 0x1, 0x1, 0x1, /* auth[17] */
8096 static const char long_binary_sid2[] = {
8097 0x1, /* revision number */
8098 32, /* num auths */
8099 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8100 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8101 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8102 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8103 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8104 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8105 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8106 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8107 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8108 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8109 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8110 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8111 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8112 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8113 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8114 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8115 0x1, 0x1, 0x1, 0x1, /* auth[15] */
8116 0x1, 0x1, 0x1, 0x1, /* auth[16] */
8117 0x1, 0x1, 0x1, 0x1, /* auth[17] */
8118 0x1, 0x1, 0x1, 0x1, /* auth[18] */
8119 0x1, 0x1, 0x1, 0x1, /* auth[19] */
8120 0x1, 0x1, 0x1, 0x1, /* auth[20] */
8121 0x1, 0x1, 0x1, 0x1, /* auth[21] */
8122 0x1, 0x1, 0x1, 0x1, /* auth[22] */
8123 0x1, 0x1, 0x1, 0x1, /* auth[23] */
8124 0x1, 0x1, 0x1, 0x1, /* auth[24] */
8125 0x1, 0x1, 0x1, 0x1, /* auth[25] */
8126 0x1, 0x1, 0x1, 0x1, /* auth[26] */
8127 0x1, 0x1, 0x1, 0x1, /* auth[27] */
8128 0x1, 0x1, 0x1, 0x1, /* auth[28] */
8129 0x1, 0x1, 0x1, 0x1, /* auth[29] */
8130 0x1, 0x1, 0x1, 0x1, /* auth[30] */
8131 0x1, 0x1, 0x1, 0x1, /* auth[31] */
8134 if (!sid_parse(good_binary_sid, sizeof(good_binary_sid), sid)) {
8135 return false;
8137 if (sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid)) {
8138 return false;
8140 if (sid_parse(long_binary_sid, sizeof(long_binary_sid), sid)) {
8141 return false;
8143 return true;
8146 /* Split a path name into filename and stream name components. Canonicalise
8147 * such that an implicit $DATA token is always explicit.
8149 * The "specification" of this function can be found in the
8150 * run_local_stream_name() function in torture.c, I've tried those
8151 * combinations against a W2k3 server.
8154 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
8155 char **pbase, char **pstream)
8157 char *base = NULL;
8158 char *stream = NULL;
8159 char *sname; /* stream name */
8160 const char *stype; /* stream type */
8162 DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
8164 sname = strchr_m(fname, ':');
8166 if (lp_posix_pathnames() || (sname == NULL)) {
8167 if (pbase != NULL) {
8168 base = talloc_strdup(mem_ctx, fname);
8169 NT_STATUS_HAVE_NO_MEMORY(base);
8171 goto done;
8174 if (pbase != NULL) {
8175 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
8176 NT_STATUS_HAVE_NO_MEMORY(base);
8179 sname += 1;
8181 stype = strchr_m(sname, ':');
8183 if (stype == NULL) {
8184 sname = talloc_strdup(mem_ctx, sname);
8185 stype = "$DATA";
8187 else {
8188 if (strcasecmp_m(stype, ":$DATA") != 0) {
8190 * If there is an explicit stream type, so far we only
8191 * allow $DATA. Is there anything else allowed? -- vl
8193 DEBUG(10, ("[%s] is an invalid stream type\n", stype));
8194 TALLOC_FREE(base);
8195 return NT_STATUS_OBJECT_NAME_INVALID;
8197 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
8198 stype += 1;
8201 if (sname == NULL) {
8202 TALLOC_FREE(base);
8203 return NT_STATUS_NO_MEMORY;
8206 if (sname[0] == '\0') {
8208 * no stream name, so no stream
8210 goto done;
8213 if (pstream != NULL) {
8214 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
8215 if (stream == NULL) {
8216 TALLOC_FREE(sname);
8217 TALLOC_FREE(base);
8218 return NT_STATUS_NO_MEMORY;
8221 * upper-case the type field
8223 strupper_m(strchr_m(stream, ':')+1);
8226 done:
8227 if (pbase != NULL) {
8228 *pbase = base;
8230 if (pstream != NULL) {
8231 *pstream = stream;
8233 return NT_STATUS_OK;
8236 static bool test_stream_name(const char *fname, const char *expected_base,
8237 const char *expected_stream,
8238 NTSTATUS expected_status)
8240 NTSTATUS status;
8241 char *base = NULL;
8242 char *stream = NULL;
8244 status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
8245 if (!NT_STATUS_EQUAL(status, expected_status)) {
8246 goto error;
8249 if (!NT_STATUS_IS_OK(status)) {
8250 return true;
8253 if (base == NULL) goto error;
8255 if (strcmp(expected_base, base) != 0) goto error;
8257 if ((expected_stream != NULL) && (stream == NULL)) goto error;
8258 if ((expected_stream == NULL) && (stream != NULL)) goto error;
8260 if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
8261 goto error;
8263 TALLOC_FREE(base);
8264 TALLOC_FREE(stream);
8265 return true;
8267 error:
8268 d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
8269 fname, expected_base ? expected_base : "<NULL>",
8270 expected_stream ? expected_stream : "<NULL>",
8271 nt_errstr(expected_status));
8272 d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
8273 base ? base : "<NULL>", stream ? stream : "<NULL>",
8274 nt_errstr(status));
8275 TALLOC_FREE(base);
8276 TALLOC_FREE(stream);
8277 return false;
8280 static bool run_local_stream_name(int dummy)
8282 bool ret = true;
8284 ret &= test_stream_name(
8285 "bla", "bla", NULL, NT_STATUS_OK);
8286 ret &= test_stream_name(
8287 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
8288 ret &= test_stream_name(
8289 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8290 ret &= test_stream_name(
8291 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
8292 ret &= test_stream_name(
8293 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8294 ret &= test_stream_name(
8295 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
8296 ret &= test_stream_name(
8297 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
8298 ret &= test_stream_name(
8299 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
8301 return ret;
8304 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
8306 if (a.length != b.length) {
8307 printf("a.length=%d != b.length=%d\n",
8308 (int)a.length, (int)b.length);
8309 return false;
8311 if (memcmp(a.data, b.data, a.length) != 0) {
8312 printf("a.data and b.data differ\n");
8313 return false;
8315 return true;
8318 static bool run_local_memcache(int dummy)
8320 struct memcache *cache;
8321 DATA_BLOB k1, k2;
8322 DATA_BLOB d1, d2, d3;
8323 DATA_BLOB v1, v2, v3;
8325 TALLOC_CTX *mem_ctx;
8326 char *str1, *str2;
8327 size_t size1, size2;
8328 bool ret = false;
8330 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
8332 if (cache == NULL) {
8333 printf("memcache_init failed\n");
8334 return false;
8337 d1 = data_blob_const("d1", 2);
8338 d2 = data_blob_const("d2", 2);
8339 d3 = data_blob_const("d3", 2);
8341 k1 = data_blob_const("d1", 2);
8342 k2 = data_blob_const("d2", 2);
8344 memcache_add(cache, STAT_CACHE, k1, d1);
8345 memcache_add(cache, GETWD_CACHE, k2, d2);
8347 if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
8348 printf("could not find k1\n");
8349 return false;
8351 if (!data_blob_equal(d1, v1)) {
8352 return false;
8355 if (!memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8356 printf("could not find k2\n");
8357 return false;
8359 if (!data_blob_equal(d2, v2)) {
8360 return false;
8363 memcache_add(cache, STAT_CACHE, k1, d3);
8365 if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
8366 printf("could not find replaced k1\n");
8367 return false;
8369 if (!data_blob_equal(d3, v3)) {
8370 return false;
8373 memcache_add(cache, GETWD_CACHE, k1, d1);
8375 if (memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8376 printf("Did find k2, should have been purged\n");
8377 return false;
8380 TALLOC_FREE(cache);
8382 cache = memcache_init(NULL, 0);
8384 mem_ctx = talloc_init("foo");
8386 str1 = talloc_strdup(mem_ctx, "string1");
8387 str2 = talloc_strdup(mem_ctx, "string2");
8389 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8390 data_blob_string_const("torture"), &str1);
8391 size1 = talloc_total_size(cache);
8393 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8394 data_blob_string_const("torture"), &str2);
8395 size2 = talloc_total_size(cache);
8397 printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
8399 if (size2 > size1) {
8400 printf("memcache leaks memory!\n");
8401 goto fail;
8404 ret = true;
8405 fail:
8406 TALLOC_FREE(cache);
8407 return ret;
8410 static void wbclient_done(struct tevent_req *req)
8412 wbcErr wbc_err;
8413 struct winbindd_response *wb_resp;
8414 int *i = (int *)tevent_req_callback_data_void(req);
8416 wbc_err = wb_trans_recv(req, req, &wb_resp);
8417 TALLOC_FREE(req);
8418 *i += 1;
8419 d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
8422 static bool run_local_wbclient(int dummy)
8424 struct event_context *ev;
8425 struct wb_context **wb_ctx;
8426 struct winbindd_request wb_req;
8427 bool result = false;
8428 int i, j;
8430 BlockSignals(True, SIGPIPE);
8432 ev = tevent_context_init_byname(talloc_tos(), "epoll");
8433 if (ev == NULL) {
8434 goto fail;
8437 wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
8438 if (wb_ctx == NULL) {
8439 goto fail;
8442 ZERO_STRUCT(wb_req);
8443 wb_req.cmd = WINBINDD_PING;
8445 d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
8447 for (i=0; i<torture_nprocs; i++) {
8448 wb_ctx[i] = wb_context_init(ev, NULL);
8449 if (wb_ctx[i] == NULL) {
8450 goto fail;
8452 for (j=0; j<torture_numops; j++) {
8453 struct tevent_req *req;
8454 req = wb_trans_send(ev, ev, wb_ctx[i],
8455 (j % 2) == 0, &wb_req);
8456 if (req == NULL) {
8457 goto fail;
8459 tevent_req_set_callback(req, wbclient_done, &i);
8463 i = 0;
8465 while (i < torture_nprocs * torture_numops) {
8466 tevent_loop_once(ev);
8469 result = true;
8470 fail:
8471 TALLOC_FREE(ev);
8472 return result;
8475 static void getaddrinfo_finished(struct tevent_req *req)
8477 char *name = (char *)tevent_req_callback_data_void(req);
8478 struct addrinfo *ainfo;
8479 int res;
8481 res = getaddrinfo_recv(req, &ainfo);
8482 if (res != 0) {
8483 d_printf("gai(%s) returned %s\n", name, gai_strerror(res));
8484 return;
8486 d_printf("gai(%s) succeeded\n", name);
8487 freeaddrinfo(ainfo);
8490 static bool run_getaddrinfo_send(int dummy)
8492 TALLOC_CTX *frame = talloc_stackframe();
8493 struct fncall_context *ctx;
8494 struct tevent_context *ev;
8495 bool result = false;
8496 const char *names[4] = { "www.samba.org", "notfound.samba.org",
8497 "www.slashdot.org", "heise.de" };
8498 struct tevent_req *reqs[4];
8499 int i;
8501 ev = event_context_init(frame);
8502 if (ev == NULL) {
8503 goto fail;
8506 ctx = fncall_context_init(frame, 4);
8508 for (i=0; i<ARRAY_SIZE(names); i++) {
8509 reqs[i] = getaddrinfo_send(frame, ev, ctx, names[i], NULL,
8510 NULL);
8511 if (reqs[i] == NULL) {
8512 goto fail;
8514 tevent_req_set_callback(reqs[i], getaddrinfo_finished,
8515 discard_const_p(void, names[i]));
8518 for (i=0; i<ARRAY_SIZE(reqs); i++) {
8519 tevent_loop_once(ev);
8522 result = true;
8523 fail:
8524 TALLOC_FREE(frame);
8525 return result;
8528 static bool dbtrans_inc(struct db_context *db)
8530 struct db_record *rec;
8531 uint32_t val;
8532 bool ret = false;
8533 NTSTATUS status;
8534 TDB_DATA value;
8536 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
8537 if (rec == NULL) {
8538 printf(__location__ "fetch_lock failed\n");
8539 return false;
8542 value = dbwrap_record_get_value(rec);
8544 if (value.dsize != sizeof(uint32_t)) {
8545 printf(__location__ "value.dsize = %d\n",
8546 (int)value.dsize);
8547 goto fail;
8550 memcpy(&val, value.dptr, sizeof(val));
8551 val += 1;
8553 status = dbwrap_record_store(
8554 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
8555 if (!NT_STATUS_IS_OK(status)) {
8556 printf(__location__ "store failed: %s\n",
8557 nt_errstr(status));
8558 goto fail;
8561 ret = true;
8562 fail:
8563 TALLOC_FREE(rec);
8564 return ret;
8567 static bool run_local_dbtrans(int dummy)
8569 struct db_context *db;
8570 struct db_record *rec;
8571 NTSTATUS status;
8572 uint32_t initial;
8573 int res;
8574 TDB_DATA value;
8576 db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
8577 O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1);
8578 if (db == NULL) {
8579 printf("Could not open transtest.db\n");
8580 return false;
8583 res = dbwrap_transaction_start(db);
8584 if (res != 0) {
8585 printf(__location__ "transaction_start failed\n");
8586 return false;
8589 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
8590 if (rec == NULL) {
8591 printf(__location__ "fetch_lock failed\n");
8592 return false;
8595 value = dbwrap_record_get_value(rec);
8597 if (value.dptr == NULL) {
8598 initial = 0;
8599 status = dbwrap_record_store(
8600 rec, make_tdb_data((uint8_t *)&initial,
8601 sizeof(initial)),
8603 if (!NT_STATUS_IS_OK(status)) {
8604 printf(__location__ "store returned %s\n",
8605 nt_errstr(status));
8606 return false;
8610 TALLOC_FREE(rec);
8612 res = dbwrap_transaction_commit(db);
8613 if (res != 0) {
8614 printf(__location__ "transaction_commit failed\n");
8615 return false;
8618 while (true) {
8619 uint32_t val, val2;
8620 int i;
8622 res = dbwrap_transaction_start(db);
8623 if (res != 0) {
8624 printf(__location__ "transaction_start failed\n");
8625 break;
8628 status = dbwrap_fetch_uint32(db, "transtest", &val);
8629 if (!NT_STATUS_IS_OK(status)) {
8630 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
8631 nt_errstr(status));
8632 break;
8635 for (i=0; i<10; i++) {
8636 if (!dbtrans_inc(db)) {
8637 return false;
8641 status = dbwrap_fetch_uint32(db, "transtest", &val2);
8642 if (!NT_STATUS_IS_OK(status)) {
8643 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
8644 nt_errstr(status));
8645 break;
8648 if (val2 != val + 10) {
8649 printf(__location__ "val=%d, val2=%d\n",
8650 (int)val, (int)val2);
8651 break;
8654 printf("val2=%d\r", val2);
8656 res = dbwrap_transaction_commit(db);
8657 if (res != 0) {
8658 printf(__location__ "transaction_commit failed\n");
8659 break;
8663 TALLOC_FREE(db);
8664 return true;
8668 * Just a dummy test to be run under a debugger. There's no real way
8669 * to inspect the tevent_select specific function from outside of
8670 * tevent_select.c.
8673 static bool run_local_tevent_select(int dummy)
8675 struct tevent_context *ev;
8676 struct tevent_fd *fd1, *fd2;
8677 bool result = false;
8679 ev = tevent_context_init_byname(NULL, "select");
8680 if (ev == NULL) {
8681 d_fprintf(stderr, "tevent_context_init_byname failed\n");
8682 goto fail;
8685 fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
8686 if (fd1 == NULL) {
8687 d_fprintf(stderr, "tevent_add_fd failed\n");
8688 goto fail;
8690 fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
8691 if (fd2 == NULL) {
8692 d_fprintf(stderr, "tevent_add_fd failed\n");
8693 goto fail;
8695 TALLOC_FREE(fd2);
8697 fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
8698 if (fd2 == NULL) {
8699 d_fprintf(stderr, "tevent_add_fd failed\n");
8700 goto fail;
8703 result = true;
8704 fail:
8705 TALLOC_FREE(ev);
8706 return result;
8709 static bool run_local_hex_encode_buf(int dummy)
8711 char buf[17];
8712 uint8_t src[8];
8713 int i;
8715 for (i=0; i<sizeof(src); i++) {
8716 src[i] = i;
8718 hex_encode_buf(buf, src, sizeof(src));
8719 if (strcmp(buf, "0001020304050607") != 0) {
8720 return false;
8722 hex_encode_buf(buf, NULL, 0);
8723 if (buf[0] != '\0') {
8724 return false;
8726 return true;
8729 static double create_procs(bool (*fn)(int), bool *result)
8731 int i, status;
8732 volatile pid_t *child_status;
8733 volatile bool *child_status_out;
8734 int synccount;
8735 int tries = 8;
8736 struct timeval start;
8738 synccount = 0;
8740 child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*torture_nprocs);
8741 if (!child_status) {
8742 printf("Failed to setup shared memory\n");
8743 return -1;
8746 child_status_out = (volatile bool *)shm_setup(sizeof(bool)*torture_nprocs);
8747 if (!child_status_out) {
8748 printf("Failed to setup result status shared memory\n");
8749 return -1;
8752 for (i = 0; i < torture_nprocs; i++) {
8753 child_status[i] = 0;
8754 child_status_out[i] = True;
8757 start = timeval_current();
8759 for (i=0;i<torture_nprocs;i++) {
8760 procnum = i;
8761 if (fork() == 0) {
8762 pid_t mypid = getpid();
8763 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
8765 slprintf(myname,sizeof(myname),"CLIENT%d", i);
8767 while (1) {
8768 if (torture_open_connection(&current_cli, i)) break;
8769 if (tries-- == 0) {
8770 printf("pid %d failed to start\n", (int)getpid());
8771 _exit(1);
8773 smb_msleep(10);
8776 child_status[i] = getpid();
8778 while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
8780 child_status_out[i] = fn(i);
8781 _exit(0);
8785 do {
8786 synccount = 0;
8787 for (i=0;i<torture_nprocs;i++) {
8788 if (child_status[i]) synccount++;
8790 if (synccount == torture_nprocs) break;
8791 smb_msleep(10);
8792 } while (timeval_elapsed(&start) < 30);
8794 if (synccount != torture_nprocs) {
8795 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
8796 *result = False;
8797 return timeval_elapsed(&start);
8800 /* start the client load */
8801 start = timeval_current();
8803 for (i=0;i<torture_nprocs;i++) {
8804 child_status[i] = 0;
8807 printf("%d clients started\n", torture_nprocs);
8809 for (i=0;i<torture_nprocs;i++) {
8810 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
8813 printf("\n");
8815 for (i=0;i<torture_nprocs;i++) {
8816 if (!child_status_out[i]) {
8817 *result = False;
8820 return timeval_elapsed(&start);
8823 #define FLAG_MULTIPROC 1
8825 static struct {
8826 const char *name;
8827 bool (*fn)(int);
8828 unsigned flags;
8829 } torture_ops[] = {
8830 {"FDPASS", run_fdpasstest, 0},
8831 {"LOCK1", run_locktest1, 0},
8832 {"LOCK2", run_locktest2, 0},
8833 {"LOCK3", run_locktest3, 0},
8834 {"LOCK4", run_locktest4, 0},
8835 {"LOCK5", run_locktest5, 0},
8836 {"LOCK6", run_locktest6, 0},
8837 {"LOCK7", run_locktest7, 0},
8838 {"LOCK8", run_locktest8, 0},
8839 {"LOCK9", run_locktest9, 0},
8840 {"UNLINK", run_unlinktest, 0},
8841 {"BROWSE", run_browsetest, 0},
8842 {"ATTR", run_attrtest, 0},
8843 {"TRANS2", run_trans2test, 0},
8844 {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
8845 {"TORTURE",run_torture, FLAG_MULTIPROC},
8846 {"RANDOMIPC", run_randomipc, 0},
8847 {"NEGNOWAIT", run_negprot_nowait, 0},
8848 {"NBENCH", run_nbench, 0},
8849 {"NBENCH2", run_nbench2, 0},
8850 {"OPLOCK1", run_oplock1, 0},
8851 {"OPLOCK2", run_oplock2, 0},
8852 {"OPLOCK4", run_oplock4, 0},
8853 {"DIR", run_dirtest, 0},
8854 {"DIR1", run_dirtest1, 0},
8855 {"DIR-CREATETIME", run_dir_createtime, 0},
8856 {"DENY1", torture_denytest1, 0},
8857 {"DENY2", torture_denytest2, 0},
8858 {"TCON", run_tcon_test, 0},
8859 {"TCONDEV", run_tcon_devtype_test, 0},
8860 {"RW1", run_readwritetest, 0},
8861 {"RW2", run_readwritemulti, FLAG_MULTIPROC},
8862 {"RW3", run_readwritelarge, 0},
8863 {"RW-SIGNING", run_readwritelarge_signtest, 0},
8864 {"OPEN", run_opentest, 0},
8865 {"POSIX", run_simple_posix_open_test, 0},
8866 {"POSIX-APPEND", run_posix_append, 0},
8867 {"CASE-INSENSITIVE-CREATE", run_case_insensitive_create, 0},
8868 {"ASYNC-ECHO", run_async_echo, 0},
8869 { "UID-REGRESSION-TEST", run_uid_regression_test, 0},
8870 { "SHORTNAME-TEST", run_shortname_test, 0},
8871 { "ADDRCHANGE", run_addrchange, 0},
8872 #if 1
8873 {"OPENATTR", run_openattrtest, 0},
8874 #endif
8875 {"XCOPY", run_xcopy, 0},
8876 {"RENAME", run_rename, 0},
8877 {"DELETE", run_deletetest, 0},
8878 {"DELETE-LN", run_deletetest_ln, 0},
8879 {"PROPERTIES", run_properties, 0},
8880 {"MANGLE", torture_mangle, 0},
8881 {"MANGLE1", run_mangle1, 0},
8882 {"W2K", run_w2ktest, 0},
8883 {"TRANS2SCAN", torture_trans2_scan, 0},
8884 {"NTTRANSSCAN", torture_nttrans_scan, 0},
8885 {"UTABLE", torture_utable, 0},
8886 {"CASETABLE", torture_casetable, 0},
8887 {"ERRMAPEXTRACT", run_error_map_extract, 0},
8888 {"PIPE_NUMBER", run_pipe_number, 0},
8889 {"TCON2", run_tcon2_test, 0},
8890 {"IOCTL", torture_ioctl_test, 0},
8891 {"CHKPATH", torture_chkpath_test, 0},
8892 {"FDSESS", run_fdsesstest, 0},
8893 { "EATEST", run_eatest, 0},
8894 { "SESSSETUP_BENCH", run_sesssetup_bench, 0},
8895 { "CHAIN1", run_chain1, 0},
8896 { "CHAIN2", run_chain2, 0},
8897 { "CHAIN3", run_chain3, 0},
8898 { "WINDOWS-WRITE", run_windows_write, 0},
8899 { "NTTRANS-CREATE", run_nttrans_create, 0},
8900 { "NTTRANS-FSCTL", run_nttrans_fsctl, 0},
8901 { "CLI_ECHO", run_cli_echo, 0},
8902 { "GETADDRINFO", run_getaddrinfo_send, 0},
8903 { "TLDAP", run_tldap },
8904 { "STREAMERROR", run_streamerror },
8905 { "NOTIFY-BENCH", run_notify_bench },
8906 { "BAD-NBT-SESSION", run_bad_nbt_session },
8907 { "SMB-ANY-CONNECT", run_smb_any_connect },
8908 { "NOTIFY-ONLINE", run_notify_online },
8909 { "SMB2-BASIC", run_smb2_basic },
8910 { "SMB2-NEGPROT", run_smb2_negprot },
8911 { "SMB2-SESSION-RECONNECT", run_smb2_session_reconnect },
8912 { "SMB2-TCON-DEPENDENCE", run_smb2_tcon_dependence },
8913 { "SMB2-MULTI-CHANNEL", run_smb2_multi_channel },
8914 { "SMB2-SESSION-REAUTH", run_smb2_session_reauth },
8915 { "CLEANUP1", run_cleanup1 },
8916 { "CLEANUP2", run_cleanup2 },
8917 { "LOCAL-SUBSTITUTE", run_local_substitute, 0},
8918 { "LOCAL-GENCACHE", run_local_gencache, 0},
8919 { "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0},
8920 { "LOCAL-CTDB-CONN", run_ctdb_conn, 0},
8921 { "LOCAL-MSG", run_msg_test, 0},
8922 { "LOCAL-BASE64", run_local_base64, 0},
8923 { "LOCAL-RBTREE", run_local_rbtree, 0},
8924 { "LOCAL-MEMCACHE", run_local_memcache, 0},
8925 { "LOCAL-STREAM-NAME", run_local_stream_name, 0},
8926 { "LOCAL-WBCLIENT", run_local_wbclient, 0},
8927 { "LOCAL-string_to_sid", run_local_string_to_sid, 0},
8928 { "LOCAL-binary_to_sid", run_local_binary_to_sid, 0},
8929 { "LOCAL-DBTRANS", run_local_dbtrans, 0},
8930 { "LOCAL-TEVENT-SELECT", run_local_tevent_select, 0},
8931 { "LOCAL-CONVERT-STRING", run_local_convert_string, 0},
8932 { "LOCAL-CONV-AUTH-INFO", run_local_conv_auth_info, 0},
8933 { "LOCAL-sprintf_append", run_local_sprintf_append, 0},
8934 { "LOCAL-hex_encode_buf", run_local_hex_encode_buf, 0},
8935 {NULL, NULL, 0}};
8939 /****************************************************************************
8940 run a specified test or "ALL"
8941 ****************************************************************************/
8942 static bool run_test(const char *name)
8944 bool ret = True;
8945 bool result = True;
8946 bool found = False;
8947 int i;
8948 double t;
8949 if (strequal(name,"ALL")) {
8950 for (i=0;torture_ops[i].name;i++) {
8951 run_test(torture_ops[i].name);
8953 found = True;
8956 for (i=0;torture_ops[i].name;i++) {
8957 fstr_sprintf(randomfname, "\\XX%x",
8958 (unsigned)random());
8960 if (strequal(name, torture_ops[i].name)) {
8961 found = True;
8962 printf("Running %s\n", name);
8963 if (torture_ops[i].flags & FLAG_MULTIPROC) {
8964 t = create_procs(torture_ops[i].fn, &result);
8965 if (!result) {
8966 ret = False;
8967 printf("TEST %s FAILED!\n", name);
8969 } else {
8970 struct timeval start;
8971 start = timeval_current();
8972 if (!torture_ops[i].fn(0)) {
8973 ret = False;
8974 printf("TEST %s FAILED!\n", name);
8976 t = timeval_elapsed(&start);
8978 printf("%s took %g secs\n\n", name, t);
8982 if (!found) {
8983 printf("Did not find a test named %s\n", name);
8984 ret = False;
8987 return ret;
8991 static void usage(void)
8993 int i;
8995 printf("WARNING samba4 test suite is much more complete nowadays.\n");
8996 printf("Please use samba4 torture.\n\n");
8998 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
9000 printf("\t-d debuglevel\n");
9001 printf("\t-U user%%pass\n");
9002 printf("\t-k use kerberos\n");
9003 printf("\t-N numprocs\n");
9004 printf("\t-n my_netbios_name\n");
9005 printf("\t-W workgroup\n");
9006 printf("\t-o num_operations\n");
9007 printf("\t-O socket_options\n");
9008 printf("\t-m maximum protocol\n");
9009 printf("\t-L use oplocks\n");
9010 printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
9011 printf("\t-A showall\n");
9012 printf("\t-p port\n");
9013 printf("\t-s seed\n");
9014 printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
9015 printf("\t-f filename filename to test\n");
9016 printf("\n\n");
9018 printf("tests are:");
9019 for (i=0;torture_ops[i].name;i++) {
9020 printf(" %s", torture_ops[i].name);
9022 printf("\n");
9024 printf("default test is ALL\n");
9026 exit(1);
9029 /****************************************************************************
9030 main program
9031 ****************************************************************************/
9032 int main(int argc,char *argv[])
9034 int opt, i;
9035 char *p;
9036 int gotuser = 0;
9037 int gotpass = 0;
9038 bool correct = True;
9039 TALLOC_CTX *frame = talloc_stackframe();
9040 int seed = time(NULL);
9042 #ifdef HAVE_SETBUFFER
9043 setbuffer(stdout, NULL, 0);
9044 #endif
9046 setup_logging("smbtorture", DEBUG_STDOUT);
9048 load_case_tables();
9050 if (is_default_dyn_CONFIGFILE()) {
9051 if(getenv("SMB_CONF_PATH")) {
9052 set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
9055 lp_load_global(get_dyn_CONFIGFILE());
9056 load_interfaces();
9058 if (argc < 2) {
9059 usage();
9062 for(p = argv[1]; *p; p++)
9063 if(*p == '\\')
9064 *p = '/';
9066 if (strncmp(argv[1], "//", 2)) {
9067 usage();
9070 fstrcpy(host, &argv[1][2]);
9071 p = strchr_m(&host[2],'/');
9072 if (!p) {
9073 usage();
9075 *p = 0;
9076 fstrcpy(share, p+1);
9078 fstrcpy(myname, get_myname(talloc_tos()));
9079 if (!*myname) {
9080 fprintf(stderr, "Failed to get my hostname.\n");
9081 return 1;
9084 if (*username == 0 && getenv("LOGNAME")) {
9085 fstrcpy(username,getenv("LOGNAME"));
9088 argc--;
9089 argv++;
9091 fstrcpy(workgroup, lp_workgroup());
9093 while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
9094 != EOF) {
9095 switch (opt) {
9096 case 'p':
9097 port_to_use = atoi(optarg);
9098 break;
9099 case 's':
9100 seed = atoi(optarg);
9101 break;
9102 case 'W':
9103 fstrcpy(workgroup,optarg);
9104 break;
9105 case 'm':
9106 max_protocol = interpret_protocol(optarg, max_protocol);
9107 break;
9108 case 'N':
9109 torture_nprocs = atoi(optarg);
9110 break;
9111 case 'o':
9112 torture_numops = atoi(optarg);
9113 break;
9114 case 'd':
9115 lp_set_cmdline("log level", optarg);
9116 break;
9117 case 'O':
9118 sockops = optarg;
9119 break;
9120 case 'L':
9121 use_oplocks = True;
9122 break;
9123 case 'l':
9124 local_path = optarg;
9125 break;
9126 case 'A':
9127 torture_showall = True;
9128 break;
9129 case 'n':
9130 fstrcpy(myname, optarg);
9131 break;
9132 case 'c':
9133 client_txt = optarg;
9134 break;
9135 case 'e':
9136 do_encrypt = true;
9137 break;
9138 case 'k':
9139 #ifdef HAVE_KRB5
9140 use_kerberos = True;
9141 #else
9142 d_printf("No kerberos support compiled in\n");
9143 exit(1);
9144 #endif
9145 break;
9146 case 'U':
9147 gotuser = 1;
9148 fstrcpy(username,optarg);
9149 p = strchr_m(username,'%');
9150 if (p) {
9151 *p = 0;
9152 fstrcpy(password, p+1);
9153 gotpass = 1;
9155 break;
9156 case 'b':
9157 fstrcpy(multishare_conn_fname, optarg);
9158 use_multishare_conn = True;
9159 break;
9160 case 'B':
9161 torture_blocksize = atoi(optarg);
9162 break;
9163 case 'f':
9164 test_filename = SMB_STRDUP(optarg);
9165 break;
9166 default:
9167 printf("Unknown option %c (%d)\n", (char)opt, opt);
9168 usage();
9172 d_printf("using seed %d\n", seed);
9174 srandom(seed);
9176 if(use_kerberos && !gotuser) gotpass = True;
9178 while (!gotpass) {
9179 p = getpass("Password:");
9180 if (p) {
9181 fstrcpy(password, p);
9182 gotpass = 1;
9186 printf("host=%s share=%s user=%s myname=%s\n",
9187 host, share, username, myname);
9189 if (argc == optind) {
9190 correct = run_test("ALL");
9191 } else {
9192 for (i=optind;i<argc;i++) {
9193 if (!run_test(argv[i])) {
9194 correct = False;
9199 TALLOC_FREE(frame);
9201 if (correct) {
9202 return(0);
9203 } else {
9204 return(1);