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