s3: Replace cli_qfileinfo_test with a call to cli_qfileinfo
[Samba.git] / source3 / torture / torture.c
blobc416a161e07981536dec7421d7ed05c3174d4b1a
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 "nsswitch/libwbclient/wbc_async.h"
23 #include "torture/proto.h"
24 #include "libcli/security/security.h"
25 #include "tldap.h"
26 #include "tldap_util.h"
27 #include "../librpc/gen_ndr/svcctl.h"
28 #include "memcache.h"
29 #include "nsswitch/winbind_client.h"
30 #include "dbwrap.h"
31 #include "talloc_dict.h"
32 #include "async_smb.h"
34 extern char *optarg;
35 extern int optind;
37 static fstring host, workgroup, share, password, username, myname;
38 static int max_protocol = PROTOCOL_NT1;
39 static const char *sockops="TCP_NODELAY";
40 static int nprocs=1;
41 static int port_to_use=0;
42 int torture_numops=100;
43 int torture_blocksize=1024*1024;
44 static int procnum; /* records process count number when forking */
45 static struct cli_state *current_cli;
46 static fstring randomfname;
47 static bool use_oplocks;
48 static bool use_level_II_oplocks;
49 static const char *client_txt = "client_oplocks.txt";
50 static bool use_kerberos;
51 static fstring multishare_conn_fname;
52 static bool use_multishare_conn = False;
53 static bool do_encrypt;
54 static const char *local_path = NULL;
56 bool torture_showall = False;
58 static double create_procs(bool (*fn)(int), bool *result);
61 /* return a pointer to a anonymous shared memory segment of size "size"
62 which will persist across fork() but will disappear when all processes
63 exit
65 The memory is not zeroed
67 This function uses system5 shared memory. It takes advantage of a property
68 that the memory is not destroyed if it is attached when the id is removed
70 void *shm_setup(int size)
72 int shmid;
73 void *ret;
75 #ifdef __QNXNTO__
76 shmid = shm_open("private", O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
77 if (shmid == -1) {
78 printf("can't get shared memory\n");
79 exit(1);
81 shm_unlink("private");
82 if (ftruncate(shmid, size) == -1) {
83 printf("can't set shared memory size\n");
84 exit(1);
86 ret = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, shmid, 0);
87 if (ret == MAP_FAILED) {
88 printf("can't map shared memory\n");
89 exit(1);
91 #else
92 shmid = shmget(IPC_PRIVATE, size, S_IRUSR | S_IWUSR);
93 if (shmid == -1) {
94 printf("can't get shared memory\n");
95 exit(1);
97 ret = (void *)shmat(shmid, 0, 0);
98 if (!ret || ret == (void *)-1) {
99 printf("can't attach to shared memory\n");
100 return NULL;
102 /* the following releases the ipc, but note that this process
103 and all its children will still have access to the memory, its
104 just that the shmid is no longer valid for other shm calls. This
105 means we don't leave behind lots of shm segments after we exit
107 See Stevens "advanced programming in unix env" for details
109 shmctl(shmid, IPC_RMID, 0);
110 #endif
112 return ret;
115 /********************************************************************
116 Ensure a connection is encrypted.
117 ********************************************************************/
119 static bool force_cli_encryption(struct cli_state *c,
120 const char *sharename)
122 uint16 major, minor;
123 uint32 caplow, caphigh;
124 NTSTATUS status;
126 if (!SERVER_HAS_UNIX_CIFS(c)) {
127 d_printf("Encryption required and "
128 "server that doesn't support "
129 "UNIX extensions - failing connect\n");
130 return false;
133 status = cli_unix_extensions_version(c, &major, &minor, &caplow,
134 &caphigh);
135 if (!NT_STATUS_IS_OK(status)) {
136 d_printf("Encryption required and "
137 "can't get UNIX CIFS extensions "
138 "version from server: %s\n", nt_errstr(status));
139 return false;
142 if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
143 d_printf("Encryption required and "
144 "share %s doesn't support "
145 "encryption.\n", sharename);
146 return false;
149 if (c->use_kerberos) {
150 status = cli_gss_smb_encryption_start(c);
151 } else {
152 status = cli_raw_ntlm_smb_encryption_start(c,
153 username,
154 password,
155 workgroup);
158 if (!NT_STATUS_IS_OK(status)) {
159 d_printf("Encryption required and "
160 "setup failed with error %s.\n",
161 nt_errstr(status));
162 return false;
165 return true;
169 static struct cli_state *open_nbt_connection(void)
171 struct nmb_name called, calling;
172 struct sockaddr_storage ss;
173 struct cli_state *c;
174 NTSTATUS status;
176 make_nmb_name(&calling, myname, 0x0);
177 make_nmb_name(&called , host, 0x20);
179 zero_sockaddr(&ss);
181 if (!(c = cli_initialise())) {
182 printf("Failed initialize cli_struct to connect with %s\n", host);
183 return NULL;
186 c->port = port_to_use;
188 status = cli_connect(c, host, &ss);
189 if (!NT_STATUS_IS_OK(status)) {
190 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
191 return NULL;
194 c->use_kerberos = use_kerberos;
196 c->timeout = 120000; /* set a really long timeout (2 minutes) */
197 if (use_oplocks) c->use_oplocks = True;
198 if (use_level_II_oplocks) c->use_level_II_oplocks = True;
200 if (!cli_session_request(c, &calling, &called)) {
202 * Well, that failed, try *SMBSERVER ...
203 * However, we must reconnect as well ...
205 status = cli_connect(c, host, &ss);
206 if (!NT_STATUS_IS_OK(status)) {
207 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
208 return NULL;
211 make_nmb_name(&called, "*SMBSERVER", 0x20);
212 if (!cli_session_request(c, &calling, &called)) {
213 printf("%s rejected the session\n",host);
214 printf("We tried with a called name of %s & %s\n",
215 host, "*SMBSERVER");
216 cli_shutdown(c);
217 return NULL;
221 return c;
224 /****************************************************************************
225 Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
226 ****************************************************************************/
228 static bool cli_bad_session_request(struct cli_state *cli,
229 struct nmb_name *calling, struct nmb_name *called)
231 char *p;
232 int len = 4;
233 int namelen = 0;
234 char *tmp;
236 memcpy(&(cli->calling), calling, sizeof(*calling));
237 memcpy(&(cli->called ), called , sizeof(*called ));
239 /* put in the destination name */
241 tmp = name_mangle(talloc_tos(), cli->called.name,
242 cli->called.name_type);
243 if (tmp == NULL) {
244 return false;
247 p = cli->outbuf+len;
248 namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp));
249 if (namelen > 0) {
250 memcpy(p, tmp, namelen);
251 len += namelen;
253 TALLOC_FREE(tmp);
255 /* Deliberately corrupt the name len (first byte) */
256 *p = 100;
258 /* and my name */
260 tmp = name_mangle(talloc_tos(), cli->calling.name,
261 cli->calling.name_type);
262 if (tmp == NULL) {
263 return false;
266 p = cli->outbuf+len;
267 namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp));
268 if (namelen > 0) {
269 memcpy(p, tmp, namelen);
270 len += namelen;
272 TALLOC_FREE(tmp);
273 /* Deliberately corrupt the name len (first byte) */
274 *p = 100;
276 /* send a session request (RFC 1002) */
277 /* setup the packet length
278 * Remove four bytes from the length count, since the length
279 * field in the NBT Session Service header counts the number
280 * of bytes which follow. The cli_send_smb() function knows
281 * about this and accounts for those four bytes.
282 * CRH.
284 len -= 4;
285 _smb_setlen(cli->outbuf,len);
286 SCVAL(cli->outbuf,0,0x81);
288 cli_send_smb(cli);
289 DEBUG(5,("Sent session request\n"));
291 if (!cli_receive_smb(cli))
292 return False;
294 if (CVAL(cli->inbuf,0) != 0x82) {
295 /* This is the wrong place to put the error... JRA. */
296 cli->rap_error = CVAL(cli->inbuf,4);
297 return False;
299 return(True);
302 static struct cli_state *open_bad_nbt_connection(void)
304 struct nmb_name called, calling;
305 struct sockaddr_storage ss;
306 struct cli_state *c;
307 NTSTATUS status;
309 make_nmb_name(&calling, myname, 0x0);
310 make_nmb_name(&called , host, 0x20);
312 zero_sockaddr(&ss);
314 if (!(c = cli_initialise())) {
315 printf("Failed initialize cli_struct to connect with %s\n", host);
316 return NULL;
319 c->port = 139;
321 status = cli_connect(c, host, &ss);
322 if (!NT_STATUS_IS_OK(status)) {
323 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
324 return NULL;
327 c->timeout = 4000; /* set a short timeout (4 seconds) */
329 if (!cli_bad_session_request(c, &calling, &called)) {
330 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
331 return NULL;
334 return c;
338 /* Insert a NULL at the first separator of the given path and return a pointer
339 * to the remainder of the string.
341 static char *
342 terminate_path_at_separator(char * path)
344 char * p;
346 if (!path) {
347 return NULL;
350 if ((p = strchr_m(path, '/'))) {
351 *p = '\0';
352 return p + 1;
355 if ((p = strchr_m(path, '\\'))) {
356 *p = '\0';
357 return p + 1;
360 /* No separator. */
361 return NULL;
365 parse a //server/share type UNC name
367 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
368 char **hostname, char **sharename)
370 char *p;
372 *hostname = *sharename = NULL;
374 if (strncmp(unc_name, "\\\\", 2) &&
375 strncmp(unc_name, "//", 2)) {
376 return False;
379 *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
380 p = terminate_path_at_separator(*hostname);
382 if (p && *p) {
383 *sharename = talloc_strdup(mem_ctx, p);
384 terminate_path_at_separator(*sharename);
387 if (*hostname && *sharename) {
388 return True;
391 TALLOC_FREE(*hostname);
392 TALLOC_FREE(*sharename);
393 return False;
396 static bool torture_open_connection_share(struct cli_state **c,
397 const char *hostname,
398 const char *sharename)
400 bool retry;
401 int flags = 0;
402 NTSTATUS status;
404 if (use_kerberos)
405 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
406 if (use_oplocks)
407 flags |= CLI_FULL_CONNECTION_OPLOCKS;
408 if (use_level_II_oplocks)
409 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
411 status = cli_full_connection(c, myname,
412 hostname, NULL, port_to_use,
413 sharename, "?????",
414 username, workgroup,
415 password, flags, Undefined, &retry);
416 if (!NT_STATUS_IS_OK(status)) {
417 printf("failed to open share connection: //%s/%s port:%d - %s\n",
418 hostname, sharename, port_to_use, nt_errstr(status));
419 return False;
422 (*c)->timeout = 120000; /* set a really long timeout (2 minutes) */
424 if (do_encrypt) {
425 return force_cli_encryption(*c,
426 sharename);
428 return True;
431 bool torture_open_connection(struct cli_state **c, int conn_index)
433 char **unc_list = NULL;
434 int num_unc_names = 0;
435 bool result;
437 if (use_multishare_conn==True) {
438 char *h, *s;
439 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
440 if (!unc_list || num_unc_names <= 0) {
441 printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
442 exit(1);
445 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
446 NULL, &h, &s)) {
447 printf("Failed to parse UNC name %s\n",
448 unc_list[conn_index % num_unc_names]);
449 TALLOC_FREE(unc_list);
450 exit(1);
453 result = torture_open_connection_share(c, h, s);
455 /* h, s were copied earlier */
456 TALLOC_FREE(unc_list);
457 return result;
460 return torture_open_connection_share(c, host, share);
463 bool torture_cli_session_setup2(struct cli_state *cli, uint16 *new_vuid)
465 uint16 old_vuid = cli->vuid;
466 fstring old_user_name;
467 size_t passlen = strlen(password);
468 NTSTATUS status;
469 bool ret;
471 fstrcpy(old_user_name, cli->user_name);
472 cli->vuid = 0;
473 ret = NT_STATUS_IS_OK(cli_session_setup(cli, username,
474 password, passlen,
475 password, passlen,
476 workgroup));
477 *new_vuid = cli->vuid;
478 cli->vuid = old_vuid;
479 status = cli_set_username(cli, old_user_name);
480 if (!NT_STATUS_IS_OK(status)) {
481 return false;
483 return ret;
487 bool torture_close_connection(struct cli_state *c)
489 bool ret = True;
490 NTSTATUS status;
492 status = cli_tdis(c);
493 if (!NT_STATUS_IS_OK(status)) {
494 printf("tdis failed (%s)\n", nt_errstr(status));
495 ret = False;
498 cli_shutdown(c);
500 return ret;
504 /* check if the server produced the expected error code */
505 static bool check_error(int line, struct cli_state *c,
506 uint8 eclass, uint32 ecode, NTSTATUS nterr)
508 if (cli_is_dos_error(c)) {
509 uint8 cclass;
510 uint32 num;
512 /* Check DOS error */
514 cli_dos_error(c, &cclass, &num);
516 if (eclass != cclass || ecode != num) {
517 printf("unexpected error code class=%d code=%d\n",
518 (int)cclass, (int)num);
519 printf(" expected %d/%d %s (line=%d)\n",
520 (int)eclass, (int)ecode, nt_errstr(nterr), line);
521 return False;
524 } else {
525 NTSTATUS status;
527 /* Check NT error */
529 status = cli_nt_error(c);
531 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
532 printf("unexpected error code %s\n", nt_errstr(status));
533 printf(" expected %s (line=%d)\n", nt_errstr(nterr), line);
534 return False;
538 return True;
542 static bool wait_lock(struct cli_state *c, int fnum, uint32 offset, uint32 len)
544 while (!cli_lock(c, fnum, offset, len, -1, WRITE_LOCK)) {
545 if (!check_error(__LINE__, c, ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) return False;
547 return True;
551 static bool rw_torture(struct cli_state *c)
553 const char *lockfname = "\\torture.lck";
554 fstring fname;
555 uint16_t fnum;
556 uint16_t fnum2;
557 pid_t pid2, pid = getpid();
558 int i, j;
559 char buf[1024];
560 bool correct = True;
561 NTSTATUS status;
563 memset(buf, '\0', sizeof(buf));
565 status = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
566 DENY_NONE, &fnum2);
567 if (!NT_STATUS_IS_OK(status)) {
568 status = cli_open(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
570 if (!NT_STATUS_IS_OK(status)) {
571 printf("open of %s failed (%s)\n", lockfname, cli_errstr(c));
572 return False;
575 for (i=0;i<torture_numops;i++) {
576 unsigned n = (unsigned)sys_random()%10;
577 if (i % 10 == 0) {
578 printf("%d\r", i); fflush(stdout);
580 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
582 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
583 return False;
586 if (!NT_STATUS_IS_OK(cli_open(c, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL, &fnum))) {
587 printf("open failed (%s)\n", cli_errstr(c));
588 correct = False;
589 break;
592 if (cli_write(c, fnum, 0, (char *)&pid, 0, sizeof(pid)) != sizeof(pid)) {
593 printf("write failed (%s)\n", cli_errstr(c));
594 correct = False;
597 for (j=0;j<50;j++) {
598 if (cli_write(c, fnum, 0, (char *)buf,
599 sizeof(pid)+(j*sizeof(buf)),
600 sizeof(buf)) != sizeof(buf)) {
601 printf("write failed (%s)\n", cli_errstr(c));
602 correct = False;
606 pid2 = 0;
608 if (cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid)) != sizeof(pid)) {
609 printf("read failed (%s)\n", cli_errstr(c));
610 correct = False;
613 if (pid2 != pid) {
614 printf("data corruption!\n");
615 correct = False;
618 if (!NT_STATUS_IS_OK(cli_close(c, fnum))) {
619 printf("close failed (%s)\n", cli_errstr(c));
620 correct = False;
623 if (!NT_STATUS_IS_OK(cli_unlink(c, fname, aSYSTEM | aHIDDEN))) {
624 printf("unlink failed (%s)\n", cli_errstr(c));
625 correct = False;
628 if (!NT_STATUS_IS_OK(cli_unlock(c, fnum2, n*sizeof(int), sizeof(int)))) {
629 printf("unlock failed (%s)\n", cli_errstr(c));
630 correct = False;
634 cli_close(c, fnum2);
635 cli_unlink(c, lockfname, aSYSTEM | aHIDDEN);
637 printf("%d\n", i);
639 return correct;
642 static bool run_torture(int dummy)
644 struct cli_state *cli;
645 bool ret;
647 cli = current_cli;
649 cli_sockopt(cli, sockops);
651 ret = rw_torture(cli);
653 if (!torture_close_connection(cli)) {
654 ret = False;
657 return ret;
660 static bool rw_torture3(struct cli_state *c, char *lockfname)
662 uint16_t fnum = (uint16_t)-1;
663 unsigned int i = 0;
664 char buf[131072];
665 char buf_rd[131072];
666 unsigned count;
667 unsigned countprev = 0;
668 ssize_t sent = 0;
669 bool correct = True;
670 NTSTATUS status;
672 srandom(1);
673 for (i = 0; i < sizeof(buf); i += sizeof(uint32))
675 SIVAL(buf, i, sys_random());
678 if (procnum == 0)
680 if (!NT_STATUS_IS_OK(cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
681 DENY_NONE, &fnum))) {
682 printf("first open read/write of %s failed (%s)\n",
683 lockfname, cli_errstr(c));
684 return False;
687 else
689 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
691 status = cli_open(c, lockfname, O_RDONLY,
692 DENY_NONE, &fnum);
693 if (!NT_STATUS_IS_OK(status)) {
694 break;
696 smb_msleep(10);
698 if (!NT_STATUS_IS_OK(status)) {
699 printf("second open read-only of %s failed (%s)\n",
700 lockfname, cli_errstr(c));
701 return False;
705 i = 0;
706 for (count = 0; count < sizeof(buf); count += sent)
708 if (count >= countprev) {
709 printf("%d %8d\r", i, count);
710 fflush(stdout);
711 i++;
712 countprev += (sizeof(buf) / 20);
715 if (procnum == 0)
717 sent = ((unsigned)sys_random()%(20))+ 1;
718 if (sent > sizeof(buf) - count)
720 sent = sizeof(buf) - count;
723 if (cli_write(c, fnum, 0, buf+count, count, (size_t)sent) != sent) {
724 printf("write failed (%s)\n", cli_errstr(c));
725 correct = False;
728 else
730 sent = cli_read(c, fnum, buf_rd+count, count,
731 sizeof(buf)-count);
732 if (sent < 0)
734 printf("read failed offset:%d size:%ld (%s)\n",
735 count, (unsigned long)sizeof(buf)-count,
736 cli_errstr(c));
737 correct = False;
738 sent = 0;
740 if (sent > 0)
742 if (memcmp(buf_rd+count, buf+count, sent) != 0)
744 printf("read/write compare failed\n");
745 printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
746 correct = False;
747 break;
754 if (!NT_STATUS_IS_OK(cli_close(c, fnum))) {
755 printf("close failed (%s)\n", cli_errstr(c));
756 correct = False;
759 return correct;
762 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
764 const char *lockfname = "\\torture2.lck";
765 uint16_t fnum1;
766 uint16_t fnum2;
767 int i;
768 char buf[131072];
769 char buf_rd[131072];
770 bool correct = True;
771 ssize_t bytes_read;
773 if (!NT_STATUS_IS_OK(cli_unlink(c1, lockfname, aSYSTEM | aHIDDEN))) {
774 printf("unlink failed (%s) (normal, this file should not exist)\n", cli_errstr(c1));
777 if (!NT_STATUS_IS_OK(cli_open(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
778 DENY_NONE, &fnum1))) {
779 printf("first open read/write of %s failed (%s)\n",
780 lockfname, cli_errstr(c1));
781 return False;
783 if (!NT_STATUS_IS_OK(cli_open(c2, lockfname, O_RDONLY,
784 DENY_NONE, &fnum2))) {
785 printf("second open read-only of %s failed (%s)\n",
786 lockfname, cli_errstr(c2));
787 cli_close(c1, fnum1);
788 return False;
791 for (i=0;i<torture_numops;i++)
793 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
794 if (i % 10 == 0) {
795 printf("%d\r", i); fflush(stdout);
798 generate_random_buffer((unsigned char *)buf, buf_size);
800 if (cli_write(c1, fnum1, 0, buf, 0, buf_size) != buf_size) {
801 printf("write failed (%s)\n", cli_errstr(c1));
802 correct = False;
803 break;
806 if ((bytes_read = cli_read(c2, fnum2, buf_rd, 0, buf_size)) != buf_size) {
807 printf("read failed (%s)\n", cli_errstr(c2));
808 printf("read %d, expected %ld\n", (int)bytes_read,
809 (unsigned long)buf_size);
810 correct = False;
811 break;
814 if (memcmp(buf_rd, buf, buf_size) != 0)
816 printf("read/write compare failed\n");
817 correct = False;
818 break;
822 if (!NT_STATUS_IS_OK(cli_close(c2, fnum2))) {
823 printf("close failed (%s)\n", cli_errstr(c2));
824 correct = False;
826 if (!NT_STATUS_IS_OK(cli_close(c1, fnum1))) {
827 printf("close failed (%s)\n", cli_errstr(c1));
828 correct = False;
831 if (!NT_STATUS_IS_OK(cli_unlink(c1, lockfname, aSYSTEM | aHIDDEN))) {
832 printf("unlink failed (%s)\n", cli_errstr(c1));
833 correct = False;
836 return correct;
839 static bool run_readwritetest(int dummy)
841 struct cli_state *cli1, *cli2;
842 bool test1, test2 = False;
844 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
845 return False;
847 cli_sockopt(cli1, sockops);
848 cli_sockopt(cli2, sockops);
850 printf("starting readwritetest\n");
852 test1 = rw_torture2(cli1, cli2);
853 printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
855 if (test1) {
856 test2 = rw_torture2(cli1, cli1);
857 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
860 if (!torture_close_connection(cli1)) {
861 test1 = False;
864 if (!torture_close_connection(cli2)) {
865 test2 = False;
868 return (test1 && test2);
871 static bool run_readwritemulti(int dummy)
873 struct cli_state *cli;
874 bool test;
876 cli = current_cli;
878 cli_sockopt(cli, sockops);
880 printf("run_readwritemulti: fname %s\n", randomfname);
881 test = rw_torture3(cli, randomfname);
883 if (!torture_close_connection(cli)) {
884 test = False;
887 return test;
890 static bool run_readwritelarge(int dummy)
892 static struct cli_state *cli1;
893 uint16_t fnum1;
894 const char *lockfname = "\\large.dat";
895 SMB_OFF_T fsize;
896 char buf[126*1024];
897 bool correct = True;
899 if (!torture_open_connection(&cli1, 0)) {
900 return False;
902 cli_sockopt(cli1, sockops);
903 memset(buf,'\0',sizeof(buf));
905 cli1->max_xmit = 128*1024;
907 printf("starting readwritelarge\n");
909 cli_unlink(cli1, lockfname, aSYSTEM | aHIDDEN);
911 if (!NT_STATUS_IS_OK(cli_open(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL, DENY_NONE, &fnum1))) {
912 printf("open read/write of %s failed (%s)\n", lockfname, cli_errstr(cli1));
913 return False;
916 cli_write(cli1, fnum1, 0, buf, 0, sizeof(buf));
918 if (!NT_STATUS_IS_OK(cli_qfileinfo_basic(
919 cli1, fnum1, NULL, &fsize, NULL, NULL,
920 NULL, NULL, NULL))) {
921 printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
922 correct = False;
925 if (fsize == sizeof(buf))
926 printf("readwritelarge test 1 succeeded (size = %lx)\n",
927 (unsigned long)fsize);
928 else {
929 printf("readwritelarge test 1 failed (size = %lx)\n",
930 (unsigned long)fsize);
931 correct = False;
934 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
935 printf("close failed (%s)\n", cli_errstr(cli1));
936 correct = False;
939 if (!NT_STATUS_IS_OK(cli_unlink(cli1, lockfname, aSYSTEM | aHIDDEN))) {
940 printf("unlink failed (%s)\n", cli_errstr(cli1));
941 correct = False;
944 if (!NT_STATUS_IS_OK(cli_open(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL, DENY_NONE, &fnum1))) {
945 printf("open read/write of %s failed (%s)\n", lockfname, cli_errstr(cli1));
946 return False;
949 cli1->max_xmit = 4*1024;
951 cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf));
953 if (!NT_STATUS_IS_OK(cli_qfileinfo_basic(
954 cli1, fnum1, NULL, &fsize, NULL, NULL,
955 NULL, NULL, NULL))) {
956 printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
957 correct = False;
960 if (fsize == sizeof(buf))
961 printf("readwritelarge test 2 succeeded (size = %lx)\n",
962 (unsigned long)fsize);
963 else {
964 printf("readwritelarge test 2 failed (size = %lx)\n",
965 (unsigned long)fsize);
966 correct = False;
969 #if 0
970 /* ToDo - set allocation. JRA */
971 if(!cli_set_allocation_size(cli1, fnum1, 0)) {
972 printf("set allocation size to zero failed (%s)\n", cli_errstr(&cli1));
973 return False;
975 if (!cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL, NULL,
976 NULL, NULL)) {
977 printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
978 correct = False;
980 if (fsize != 0)
981 printf("readwritelarge test 3 (truncate test) succeeded (size = %x)\n", fsize);
982 #endif
984 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
985 printf("close failed (%s)\n", cli_errstr(cli1));
986 correct = False;
989 if (!torture_close_connection(cli1)) {
990 correct = False;
992 return correct;
995 int line_count = 0;
996 int nbio_id;
998 #define ival(s) strtol(s, NULL, 0)
1000 /* run a test that simulates an approximate netbench client load */
1001 static bool run_netbench(int client)
1003 struct cli_state *cli;
1004 int i;
1005 char line[1024];
1006 char cname[20];
1007 FILE *f;
1008 const char *params[20];
1009 bool correct = True;
1011 cli = current_cli;
1013 nbio_id = client;
1015 cli_sockopt(cli, sockops);
1017 nb_setup(cli);
1019 slprintf(cname,sizeof(cname)-1, "client%d", client);
1021 f = fopen(client_txt, "r");
1023 if (!f) {
1024 perror(client_txt);
1025 return False;
1028 while (fgets(line, sizeof(line)-1, f)) {
1029 char *saveptr;
1030 line_count++;
1032 line[strlen(line)-1] = 0;
1034 /* printf("[%d] %s\n", line_count, line); */
1036 all_string_sub(line,"client1", cname, sizeof(line));
1038 /* parse the command parameters */
1039 params[0] = strtok_r(line, " ", &saveptr);
1040 i = 0;
1041 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1043 params[i] = "";
1045 if (i < 2) continue;
1047 if (!strncmp(params[0],"SMB", 3)) {
1048 printf("ERROR: You are using a dbench 1 load file\n");
1049 exit(1);
1052 if (!strcmp(params[0],"NTCreateX")) {
1053 nb_createx(params[1], ival(params[2]), ival(params[3]),
1054 ival(params[4]));
1055 } else if (!strcmp(params[0],"Close")) {
1056 nb_close(ival(params[1]));
1057 } else if (!strcmp(params[0],"Rename")) {
1058 nb_rename(params[1], params[2]);
1059 } else if (!strcmp(params[0],"Unlink")) {
1060 nb_unlink(params[1]);
1061 } else if (!strcmp(params[0],"Deltree")) {
1062 nb_deltree(params[1]);
1063 } else if (!strcmp(params[0],"Rmdir")) {
1064 nb_rmdir(params[1]);
1065 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1066 nb_qpathinfo(params[1]);
1067 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1068 nb_qfileinfo(ival(params[1]));
1069 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1070 nb_qfsinfo(ival(params[1]));
1071 } else if (!strcmp(params[0],"FIND_FIRST")) {
1072 nb_findfirst(params[1]);
1073 } else if (!strcmp(params[0],"WriteX")) {
1074 nb_writex(ival(params[1]),
1075 ival(params[2]), ival(params[3]), ival(params[4]));
1076 } else if (!strcmp(params[0],"ReadX")) {
1077 nb_readx(ival(params[1]),
1078 ival(params[2]), ival(params[3]), ival(params[4]));
1079 } else if (!strcmp(params[0],"Flush")) {
1080 nb_flush(ival(params[1]));
1081 } else {
1082 printf("Unknown operation %s\n", params[0]);
1083 exit(1);
1086 fclose(f);
1088 nb_cleanup();
1090 if (!torture_close_connection(cli)) {
1091 correct = False;
1094 return correct;
1098 /* run a test that simulates an approximate netbench client load */
1099 static bool run_nbench(int dummy)
1101 double t;
1102 bool correct = True;
1104 nbio_shmem(nprocs);
1106 nbio_id = -1;
1108 signal(SIGALRM, nb_alarm);
1109 alarm(1);
1110 t = create_procs(run_netbench, &correct);
1111 alarm(0);
1113 printf("\nThroughput %g MB/sec\n",
1114 1.0e-6 * nbio_total() / t);
1115 return correct;
1120 This test checks for two things:
1122 1) correct support for retaining locks over a close (ie. the server
1123 must not use posix semantics)
1124 2) support for lock timeouts
1126 static bool run_locktest1(int dummy)
1128 struct cli_state *cli1, *cli2;
1129 const char *fname = "\\lockt1.lck";
1130 uint16_t fnum1, fnum2, fnum3;
1131 time_t t1, t2;
1132 unsigned lock_timeout;
1134 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1135 return False;
1137 cli_sockopt(cli1, sockops);
1138 cli_sockopt(cli2, sockops);
1140 printf("starting locktest1\n");
1142 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
1144 if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1))) {
1145 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1));
1146 return False;
1148 if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum2))) {
1149 printf("open2 of %s failed (%s)\n", fname, cli_errstr(cli1));
1150 return False;
1152 if (!NT_STATUS_IS_OK(cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum3))) {
1153 printf("open3 of %s failed (%s)\n", fname, cli_errstr(cli2));
1154 return False;
1157 if (!cli_lock(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) {
1158 printf("lock1 failed (%s)\n", cli_errstr(cli1));
1159 return False;
1163 if (cli_lock(cli2, fnum3, 0, 4, 0, WRITE_LOCK)) {
1164 printf("lock2 succeeded! This is a locking bug\n");
1165 return False;
1166 } else {
1167 if (!check_error(__LINE__, cli2, ERRDOS, ERRlock,
1168 NT_STATUS_LOCK_NOT_GRANTED)) return False;
1172 lock_timeout = (1 + (random() % 20));
1173 printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1174 t1 = time(NULL);
1175 if (cli_lock(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK)) {
1176 printf("lock3 succeeded! This is a locking bug\n");
1177 return False;
1178 } else {
1179 if (!check_error(__LINE__, cli2, ERRDOS, ERRlock,
1180 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
1182 t2 = time(NULL);
1184 if (ABS(t2 - t1) < lock_timeout-1) {
1185 printf("error: This server appears not to support timed lock requests\n");
1188 printf("server slept for %u seconds for a %u second timeout\n",
1189 (unsigned int)(t2-t1), lock_timeout);
1191 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
1192 printf("close1 failed (%s)\n", cli_errstr(cli1));
1193 return False;
1196 if (cli_lock(cli2, fnum3, 0, 4, 0, WRITE_LOCK)) {
1197 printf("lock4 succeeded! This is a locking bug\n");
1198 return False;
1199 } else {
1200 if (!check_error(__LINE__, cli2, ERRDOS, ERRlock,
1201 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
1204 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
1205 printf("close2 failed (%s)\n", cli_errstr(cli1));
1206 return False;
1209 if (!NT_STATUS_IS_OK(cli_close(cli2, fnum3))) {
1210 printf("close3 failed (%s)\n", cli_errstr(cli2));
1211 return False;
1214 if (!NT_STATUS_IS_OK(cli_unlink(cli1, fname, aSYSTEM | aHIDDEN))) {
1215 printf("unlink failed (%s)\n", cli_errstr(cli1));
1216 return False;
1220 if (!torture_close_connection(cli1)) {
1221 return False;
1224 if (!torture_close_connection(cli2)) {
1225 return False;
1228 printf("Passed locktest1\n");
1229 return True;
1233 this checks to see if a secondary tconx can use open files from an
1234 earlier tconx
1236 static bool run_tcon_test(int dummy)
1238 static struct cli_state *cli;
1239 const char *fname = "\\tcontest.tmp";
1240 uint16 fnum1;
1241 uint16 cnum1, cnum2, cnum3;
1242 uint16 vuid1, vuid2;
1243 char buf[4];
1244 bool ret = True;
1245 NTSTATUS status;
1247 memset(buf, '\0', sizeof(buf));
1249 if (!torture_open_connection(&cli, 0)) {
1250 return False;
1252 cli_sockopt(cli, sockops);
1254 printf("starting tcontest\n");
1256 cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
1258 if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1))) {
1259 printf("open of %s failed (%s)\n", fname, cli_errstr(cli));
1260 return False;
1263 cnum1 = cli->cnum;
1264 vuid1 = cli->vuid;
1266 if (cli_write(cli, fnum1, 0, buf, 130, 4) != 4) {
1267 printf("initial write failed (%s)", cli_errstr(cli));
1268 return False;
1271 status = cli_tcon_andx(cli, share, "?????",
1272 password, strlen(password)+1);
1273 if (!NT_STATUS_IS_OK(status)) {
1274 printf("%s refused 2nd tree connect (%s)\n", host,
1275 nt_errstr(status));
1276 cli_shutdown(cli);
1277 return False;
1280 cnum2 = cli->cnum;
1281 cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1282 vuid2 = cli->vuid + 1;
1284 /* try a write with the wrong tid */
1285 cli->cnum = cnum2;
1287 if (cli_write(cli, fnum1, 0, buf, 130, 4) == 4) {
1288 printf("* server allows write with wrong TID\n");
1289 ret = False;
1290 } else {
1291 printf("server fails write with wrong TID : %s\n", cli_errstr(cli));
1295 /* try a write with an invalid tid */
1296 cli->cnum = cnum3;
1298 if (cli_write(cli, fnum1, 0, buf, 130, 4) == 4) {
1299 printf("* server allows write with invalid TID\n");
1300 ret = False;
1301 } else {
1302 printf("server fails write with invalid TID : %s\n", cli_errstr(cli));
1305 /* try a write with an invalid vuid */
1306 cli->vuid = vuid2;
1307 cli->cnum = cnum1;
1309 if (cli_write(cli, fnum1, 0, buf, 130, 4) == 4) {
1310 printf("* server allows write with invalid VUID\n");
1311 ret = False;
1312 } else {
1313 printf("server fails write with invalid VUID : %s\n", cli_errstr(cli));
1316 cli->cnum = cnum1;
1317 cli->vuid = vuid1;
1319 if (!NT_STATUS_IS_OK(cli_close(cli, fnum1))) {
1320 printf("close failed (%s)\n", cli_errstr(cli));
1321 return False;
1324 cli->cnum = cnum2;
1326 status = cli_tdis(cli);
1327 if (!NT_STATUS_IS_OK(status)) {
1328 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1329 return False;
1332 cli->cnum = cnum1;
1334 if (!torture_close_connection(cli)) {
1335 return False;
1338 return ret;
1343 checks for old style tcon support
1345 static bool run_tcon2_test(int dummy)
1347 static struct cli_state *cli;
1348 uint16 cnum, max_xmit;
1349 char *service;
1350 NTSTATUS status;
1352 if (!torture_open_connection(&cli, 0)) {
1353 return False;
1355 cli_sockopt(cli, sockops);
1357 printf("starting tcon2 test\n");
1359 if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1360 return false;
1363 status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1365 if (!NT_STATUS_IS_OK(status)) {
1366 printf("tcon2 failed : %s\n", cli_errstr(cli));
1367 } else {
1368 printf("tcon OK : max_xmit=%d cnum=%d tid=%d\n",
1369 (int)max_xmit, (int)cnum, SVAL(cli->inbuf, smb_tid));
1372 if (!torture_close_connection(cli)) {
1373 return False;
1376 printf("Passed tcon2 test\n");
1377 return True;
1380 static bool tcon_devtest(struct cli_state *cli,
1381 const char *myshare, const char *devtype,
1382 const char *return_devtype,
1383 NTSTATUS expected_error)
1385 NTSTATUS status;
1386 bool ret;
1388 status = cli_tcon_andx(cli, myshare, devtype,
1389 password, strlen(password)+1);
1391 if (NT_STATUS_IS_OK(expected_error)) {
1392 if (NT_STATUS_IS_OK(status)) {
1393 if (strcmp(cli->dev, return_devtype) == 0) {
1394 ret = True;
1395 } else {
1396 printf("tconX to share %s with type %s "
1397 "succeeded but returned the wrong "
1398 "device type (got [%s] but should have got [%s])\n",
1399 myshare, devtype, cli->dev, return_devtype);
1400 ret = False;
1402 } else {
1403 printf("tconX to share %s with type %s "
1404 "should have succeeded but failed\n",
1405 myshare, devtype);
1406 ret = False;
1408 cli_tdis(cli);
1409 } else {
1410 if (NT_STATUS_IS_OK(status)) {
1411 printf("tconx to share %s with type %s "
1412 "should have failed but succeeded\n",
1413 myshare, devtype);
1414 ret = False;
1415 } else {
1416 if (NT_STATUS_EQUAL(cli_nt_error(cli),
1417 expected_error)) {
1418 ret = True;
1419 } else {
1420 printf("Returned unexpected error\n");
1421 ret = False;
1425 return ret;
1429 checks for correct tconX support
1431 static bool run_tcon_devtype_test(int dummy)
1433 static struct cli_state *cli1 = NULL;
1434 bool retry;
1435 int flags = 0;
1436 NTSTATUS status;
1437 bool ret = True;
1439 status = cli_full_connection(&cli1, myname,
1440 host, NULL, port_to_use,
1441 NULL, NULL,
1442 username, workgroup,
1443 password, flags, Undefined, &retry);
1445 if (!NT_STATUS_IS_OK(status)) {
1446 printf("could not open connection\n");
1447 return False;
1450 if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1451 ret = False;
1453 if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1454 ret = False;
1456 if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1457 ret = False;
1459 if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1460 ret = False;
1462 if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1463 ret = False;
1465 if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1466 ret = False;
1468 if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1469 ret = False;
1471 if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1472 ret = False;
1474 if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1475 ret = False;
1477 if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1478 ret = False;
1480 cli_shutdown(cli1);
1482 if (ret)
1483 printf("Passed tcondevtest\n");
1485 return ret;
1490 This test checks that
1492 1) the server supports multiple locking contexts on the one SMB
1493 connection, distinguished by PID.
1495 2) the server correctly fails overlapping locks made by the same PID (this
1496 goes against POSIX behaviour, which is why it is tricky to implement)
1498 3) the server denies unlock requests by an incorrect client PID
1500 static bool run_locktest2(int dummy)
1502 static struct cli_state *cli;
1503 const char *fname = "\\lockt2.lck";
1504 uint16_t fnum1, fnum2, fnum3;
1505 bool correct = True;
1507 if (!torture_open_connection(&cli, 0)) {
1508 return False;
1511 cli_sockopt(cli, sockops);
1513 printf("starting locktest2\n");
1515 cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
1517 cli_setpid(cli, 1);
1519 if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1))) {
1520 printf("open of %s failed (%s)\n", fname, cli_errstr(cli));
1521 return False;
1524 if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum2))) {
1525 printf("open2 of %s failed (%s)\n", fname, cli_errstr(cli));
1526 return False;
1529 cli_setpid(cli, 2);
1531 if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum3))) {
1532 printf("open3 of %s failed (%s)\n", fname, cli_errstr(cli));
1533 return False;
1536 cli_setpid(cli, 1);
1538 if (!cli_lock(cli, fnum1, 0, 4, 0, WRITE_LOCK)) {
1539 printf("lock1 failed (%s)\n", cli_errstr(cli));
1540 return False;
1543 if (cli_lock(cli, fnum1, 0, 4, 0, WRITE_LOCK)) {
1544 printf("WRITE lock1 succeeded! This is a locking bug\n");
1545 correct = False;
1546 } else {
1547 if (!check_error(__LINE__, cli, ERRDOS, ERRlock,
1548 NT_STATUS_LOCK_NOT_GRANTED)) return False;
1551 if (cli_lock(cli, fnum2, 0, 4, 0, WRITE_LOCK)) {
1552 printf("WRITE lock2 succeeded! This is a locking bug\n");
1553 correct = False;
1554 } else {
1555 if (!check_error(__LINE__, cli, ERRDOS, ERRlock,
1556 NT_STATUS_LOCK_NOT_GRANTED)) return False;
1559 if (cli_lock(cli, fnum2, 0, 4, 0, READ_LOCK)) {
1560 printf("READ lock2 succeeded! This is a locking bug\n");
1561 correct = False;
1562 } else {
1563 if (!check_error(__LINE__, cli, ERRDOS, ERRlock,
1564 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
1567 if (!cli_lock(cli, fnum1, 100, 4, 0, WRITE_LOCK)) {
1568 printf("lock at 100 failed (%s)\n", cli_errstr(cli));
1570 cli_setpid(cli, 2);
1571 if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1572 printf("unlock at 100 succeeded! This is a locking bug\n");
1573 correct = False;
1576 if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 0, 4))) {
1577 printf("unlock1 succeeded! This is a locking bug\n");
1578 correct = False;
1579 } else {
1580 if (!check_error(__LINE__, cli,
1581 ERRDOS, ERRlock,
1582 NT_STATUS_RANGE_NOT_LOCKED)) return False;
1585 if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 0, 8))) {
1586 printf("unlock2 succeeded! This is a locking bug\n");
1587 correct = False;
1588 } else {
1589 if (!check_error(__LINE__, cli,
1590 ERRDOS, ERRlock,
1591 NT_STATUS_RANGE_NOT_LOCKED)) return False;
1594 if (cli_lock(cli, fnum3, 0, 4, 0, WRITE_LOCK)) {
1595 printf("lock3 succeeded! This is a locking bug\n");
1596 correct = False;
1597 } else {
1598 if (!check_error(__LINE__, cli, ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) return False;
1601 cli_setpid(cli, 1);
1603 if (!NT_STATUS_IS_OK(cli_close(cli, fnum1))) {
1604 printf("close1 failed (%s)\n", cli_errstr(cli));
1605 return False;
1608 if (!NT_STATUS_IS_OK(cli_close(cli, fnum2))) {
1609 printf("close2 failed (%s)\n", cli_errstr(cli));
1610 return False;
1613 if (!NT_STATUS_IS_OK(cli_close(cli, fnum3))) {
1614 printf("close3 failed (%s)\n", cli_errstr(cli));
1615 return False;
1618 if (!torture_close_connection(cli)) {
1619 correct = False;
1622 printf("locktest2 finished\n");
1624 return correct;
1629 This test checks that
1631 1) the server supports the full offset range in lock requests
1633 static bool run_locktest3(int dummy)
1635 static struct cli_state *cli1, *cli2;
1636 const char *fname = "\\lockt3.lck";
1637 uint16_t fnum1, fnum2;
1638 int i;
1639 uint32 offset;
1640 bool correct = True;
1642 #define NEXT_OFFSET offset += (~(uint32)0) / torture_numops
1644 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1645 return False;
1647 cli_sockopt(cli1, sockops);
1648 cli_sockopt(cli2, sockops);
1650 printf("starting locktest3\n");
1652 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
1654 if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1))) {
1655 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1));
1656 return False;
1658 if (!NT_STATUS_IS_OK(cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2))) {
1659 printf("open2 of %s failed (%s)\n", fname, cli_errstr(cli2));
1660 return False;
1663 for (offset=i=0;i<torture_numops;i++) {
1664 NEXT_OFFSET;
1665 if (!cli_lock(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
1666 printf("lock1 %d failed (%s)\n",
1668 cli_errstr(cli1));
1669 return False;
1672 if (!cli_lock(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK)) {
1673 printf("lock2 %d failed (%s)\n",
1675 cli_errstr(cli1));
1676 return False;
1680 for (offset=i=0;i<torture_numops;i++) {
1681 NEXT_OFFSET;
1683 if (cli_lock(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK)) {
1684 printf("error: lock1 %d succeeded!\n", i);
1685 return False;
1688 if (cli_lock(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK)) {
1689 printf("error: lock2 %d succeeded!\n", i);
1690 return False;
1693 if (cli_lock(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
1694 printf("error: lock3 %d succeeded!\n", i);
1695 return False;
1698 if (cli_lock(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK)) {
1699 printf("error: lock4 %d succeeded!\n", i);
1700 return False;
1704 for (offset=i=0;i<torture_numops;i++) {
1705 NEXT_OFFSET;
1707 if (!NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, offset-1, 1))) {
1708 printf("unlock1 %d failed (%s)\n",
1710 cli_errstr(cli1));
1711 return False;
1714 if (!NT_STATUS_IS_OK(cli_unlock(cli2, fnum2, offset-2, 1))) {
1715 printf("unlock2 %d failed (%s)\n",
1717 cli_errstr(cli1));
1718 return False;
1722 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
1723 printf("close1 failed (%s)\n", cli_errstr(cli1));
1724 return False;
1727 if (!NT_STATUS_IS_OK(cli_close(cli2, fnum2))) {
1728 printf("close2 failed (%s)\n", cli_errstr(cli2));
1729 return False;
1732 if (!NT_STATUS_IS_OK(cli_unlink(cli1, fname, aSYSTEM | aHIDDEN))) {
1733 printf("unlink failed (%s)\n", cli_errstr(cli1));
1734 return False;
1737 if (!torture_close_connection(cli1)) {
1738 correct = False;
1741 if (!torture_close_connection(cli2)) {
1742 correct = False;
1745 printf("finished locktest3\n");
1747 return correct;
1750 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1751 printf("** "); correct = False; \
1755 looks at overlapping locks
1757 static bool run_locktest4(int dummy)
1759 static struct cli_state *cli1, *cli2;
1760 const char *fname = "\\lockt4.lck";
1761 uint16_t fnum1, fnum2, f;
1762 bool ret;
1763 char buf[1000];
1764 bool correct = True;
1766 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1767 return False;
1770 cli_sockopt(cli1, sockops);
1771 cli_sockopt(cli2, sockops);
1773 printf("starting locktest4\n");
1775 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
1777 cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1778 cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1780 memset(buf, 0, sizeof(buf));
1782 if (cli_write(cli1, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
1783 printf("Failed to create file\n");
1784 correct = False;
1785 goto fail;
1788 ret = cli_lock(cli1, fnum1, 0, 4, 0, WRITE_LOCK) &&
1789 cli_lock(cli1, fnum1, 2, 4, 0, WRITE_LOCK);
1790 EXPECTED(ret, False);
1791 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1793 ret = cli_lock(cli1, fnum1, 10, 4, 0, READ_LOCK) &&
1794 cli_lock(cli1, fnum1, 12, 4, 0, READ_LOCK);
1795 EXPECTED(ret, True);
1796 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1798 ret = cli_lock(cli1, fnum1, 20, 4, 0, WRITE_LOCK) &&
1799 cli_lock(cli2, fnum2, 22, 4, 0, WRITE_LOCK);
1800 EXPECTED(ret, False);
1801 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1803 ret = cli_lock(cli1, fnum1, 30, 4, 0, READ_LOCK) &&
1804 cli_lock(cli2, fnum2, 32, 4, 0, READ_LOCK);
1805 EXPECTED(ret, True);
1806 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1808 ret = (cli_setpid(cli1, 1), cli_lock(cli1, fnum1, 40, 4, 0, WRITE_LOCK)) &&
1809 (cli_setpid(cli1, 2), cli_lock(cli1, fnum1, 42, 4, 0, WRITE_LOCK));
1810 EXPECTED(ret, False);
1811 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1813 ret = (cli_setpid(cli1, 1), cli_lock(cli1, fnum1, 50, 4, 0, READ_LOCK)) &&
1814 (cli_setpid(cli1, 2), cli_lock(cli1, fnum1, 52, 4, 0, READ_LOCK));
1815 EXPECTED(ret, True);
1816 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1818 ret = cli_lock(cli1, fnum1, 60, 4, 0, READ_LOCK) &&
1819 cli_lock(cli1, fnum1, 60, 4, 0, READ_LOCK);
1820 EXPECTED(ret, True);
1821 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1823 ret = cli_lock(cli1, fnum1, 70, 4, 0, WRITE_LOCK) &&
1824 cli_lock(cli1, fnum1, 70, 4, 0, WRITE_LOCK);
1825 EXPECTED(ret, False);
1826 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1828 ret = cli_lock(cli1, fnum1, 80, 4, 0, READ_LOCK) &&
1829 cli_lock(cli1, fnum1, 80, 4, 0, WRITE_LOCK);
1830 EXPECTED(ret, False);
1831 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
1833 ret = cli_lock(cli1, fnum1, 90, 4, 0, WRITE_LOCK) &&
1834 cli_lock(cli1, fnum1, 90, 4, 0, READ_LOCK);
1835 EXPECTED(ret, True);
1836 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1838 ret = (cli_setpid(cli1, 1), cli_lock(cli1, fnum1, 100, 4, 0, WRITE_LOCK)) &&
1839 (cli_setpid(cli1, 2), cli_lock(cli1, fnum1, 100, 4, 0, READ_LOCK));
1840 EXPECTED(ret, False);
1841 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1843 ret = cli_lock(cli1, fnum1, 110, 4, 0, READ_LOCK) &&
1844 cli_lock(cli1, fnum1, 112, 4, 0, READ_LOCK) &&
1845 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
1846 EXPECTED(ret, False);
1847 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
1850 ret = cli_lock(cli1, fnum1, 120, 4, 0, WRITE_LOCK) &&
1851 (cli_read(cli2, fnum2, buf, 120, 4) == 4);
1852 EXPECTED(ret, False);
1853 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
1855 ret = cli_lock(cli1, fnum1, 130, 4, 0, READ_LOCK) &&
1856 (cli_write(cli2, fnum2, 0, buf, 130, 4) == 4);
1857 EXPECTED(ret, False);
1858 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
1861 ret = cli_lock(cli1, fnum1, 140, 4, 0, READ_LOCK) &&
1862 cli_lock(cli1, fnum1, 140, 4, 0, READ_LOCK) &&
1863 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
1864 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
1865 EXPECTED(ret, True);
1866 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
1869 ret = cli_lock(cli1, fnum1, 150, 4, 0, WRITE_LOCK) &&
1870 cli_lock(cli1, fnum1, 150, 4, 0, READ_LOCK) &&
1871 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
1872 (cli_read(cli2, fnum2, buf, 150, 4) == 4) &&
1873 !(cli_write(cli2, fnum2, 0, buf, 150, 4) == 4) &&
1874 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
1875 EXPECTED(ret, True);
1876 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
1878 ret = cli_lock(cli1, fnum1, 160, 4, 0, READ_LOCK) &&
1879 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
1880 (cli_write(cli2, fnum2, 0, buf, 160, 4) == 4) &&
1881 (cli_read(cli2, fnum2, buf, 160, 4) == 4);
1882 EXPECTED(ret, True);
1883 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
1885 ret = cli_lock(cli1, fnum1, 170, 4, 0, WRITE_LOCK) &&
1886 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
1887 (cli_write(cli2, fnum2, 0, buf, 170, 4) == 4) &&
1888 (cli_read(cli2, fnum2, buf, 170, 4) == 4);
1889 EXPECTED(ret, True);
1890 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
1892 ret = cli_lock(cli1, fnum1, 190, 4, 0, WRITE_LOCK) &&
1893 cli_lock(cli1, fnum1, 190, 4, 0, READ_LOCK) &&
1894 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
1895 !(cli_write(cli2, fnum2, 0, buf, 190, 4) == 4) &&
1896 (cli_read(cli2, fnum2, buf, 190, 4) == 4);
1897 EXPECTED(ret, True);
1898 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
1900 cli_close(cli1, fnum1);
1901 cli_close(cli2, fnum2);
1902 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
1903 cli_open(cli1, fname, O_RDWR, DENY_NONE, &f);
1904 ret = cli_lock(cli1, fnum1, 0, 8, 0, READ_LOCK) &&
1905 cli_lock(cli1, f, 0, 1, 0, READ_LOCK) &&
1906 NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
1907 NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
1908 cli_lock(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
1909 cli_close(cli1, f);
1910 cli_close(cli1, fnum1);
1911 EXPECTED(ret, True);
1912 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
1914 fail:
1915 cli_close(cli1, fnum1);
1916 cli_close(cli2, fnum2);
1917 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
1918 torture_close_connection(cli1);
1919 torture_close_connection(cli2);
1921 printf("finished locktest4\n");
1922 return correct;
1926 looks at lock upgrade/downgrade.
1928 static bool run_locktest5(int dummy)
1930 static struct cli_state *cli1, *cli2;
1931 const char *fname = "\\lockt5.lck";
1932 uint16_t fnum1, fnum2, fnum3;
1933 bool ret;
1934 char buf[1000];
1935 bool correct = True;
1937 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1938 return False;
1941 cli_sockopt(cli1, sockops);
1942 cli_sockopt(cli2, sockops);
1944 printf("starting locktest5\n");
1946 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
1948 cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1949 cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1950 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
1952 memset(buf, 0, sizeof(buf));
1954 if (cli_write(cli1, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
1955 printf("Failed to create file\n");
1956 correct = False;
1957 goto fail;
1960 /* Check for NT bug... */
1961 ret = cli_lock(cli1, fnum1, 0, 8, 0, READ_LOCK) &&
1962 cli_lock(cli1, fnum3, 0, 1, 0, READ_LOCK);
1963 cli_close(cli1, fnum1);
1964 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
1965 ret = cli_lock(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
1966 EXPECTED(ret, True);
1967 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
1968 cli_close(cli1, fnum1);
1969 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
1970 cli_unlock(cli1, fnum3, 0, 1);
1972 ret = cli_lock(cli1, fnum1, 0, 4, 0, WRITE_LOCK) &&
1973 cli_lock(cli1, fnum1, 1, 1, 0, READ_LOCK);
1974 EXPECTED(ret, True);
1975 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
1977 ret = cli_lock(cli2, fnum2, 0, 4, 0, READ_LOCK);
1978 EXPECTED(ret, False);
1980 printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
1982 /* Unlock the process 2 lock. */
1983 cli_unlock(cli2, fnum2, 0, 4);
1985 ret = cli_lock(cli1, fnum3, 0, 4, 0, READ_LOCK);
1986 EXPECTED(ret, False);
1988 printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
1990 /* Unlock the process 1 fnum3 lock. */
1991 cli_unlock(cli1, fnum3, 0, 4);
1993 /* Stack 2 more locks here. */
1994 ret = cli_lock(cli1, fnum1, 0, 4, 0, READ_LOCK) &&
1995 cli_lock(cli1, fnum1, 0, 4, 0, READ_LOCK);
1997 EXPECTED(ret, True);
1998 printf("the same process %s stack read locks\n", ret?"can":"cannot");
2000 /* Unlock the first process lock, then check this was the WRITE lock that was
2001 removed. */
2003 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2004 cli_lock(cli2, fnum2, 0, 4, 0, READ_LOCK);
2006 EXPECTED(ret, True);
2007 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2009 /* Unlock the process 2 lock. */
2010 cli_unlock(cli2, fnum2, 0, 4);
2012 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2014 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2015 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2016 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2018 EXPECTED(ret, True);
2019 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2021 /* Ensure the next unlock fails. */
2022 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2023 EXPECTED(ret, False);
2024 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2026 /* Ensure connection 2 can get a write lock. */
2027 ret = cli_lock(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2028 EXPECTED(ret, True);
2030 printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2033 fail:
2034 cli_close(cli1, fnum1);
2035 cli_close(cli2, fnum2);
2036 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
2037 if (!torture_close_connection(cli1)) {
2038 correct = False;
2040 if (!torture_close_connection(cli2)) {
2041 correct = False;
2044 printf("finished locktest5\n");
2046 return correct;
2050 tries the unusual lockingX locktype bits
2052 static bool run_locktest6(int dummy)
2054 static struct cli_state *cli;
2055 const char *fname[1] = { "\\lock6.txt" };
2056 int i;
2057 uint16_t fnum;
2058 NTSTATUS status;
2060 if (!torture_open_connection(&cli, 0)) {
2061 return False;
2064 cli_sockopt(cli, sockops);
2066 printf("starting locktest6\n");
2068 for (i=0;i<1;i++) {
2069 printf("Testing %s\n", fname[i]);
2071 cli_unlink(cli, fname[i], aSYSTEM | aHIDDEN);
2073 cli_open(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2074 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2075 cli_close(cli, fnum);
2076 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2078 cli_open(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2079 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2080 cli_close(cli, fnum);
2081 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2083 cli_unlink(cli, fname[i], aSYSTEM | aHIDDEN);
2086 torture_close_connection(cli);
2088 printf("finished locktest6\n");
2089 return True;
2092 static bool run_locktest7(int dummy)
2094 struct cli_state *cli1;
2095 const char *fname = "\\lockt7.lck";
2096 uint16_t fnum1;
2097 char buf[200];
2098 bool correct = False;
2100 if (!torture_open_connection(&cli1, 0)) {
2101 return False;
2104 cli_sockopt(cli1, sockops);
2106 printf("starting locktest7\n");
2108 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
2110 cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2112 memset(buf, 0, sizeof(buf));
2114 if (cli_write(cli1, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
2115 printf("Failed to create file\n");
2116 goto fail;
2119 cli_setpid(cli1, 1);
2121 if (!cli_lock(cli1, fnum1, 130, 4, 0, READ_LOCK)) {
2122 printf("Unable to apply read lock on range 130:4, error was %s\n", cli_errstr(cli1));
2123 goto fail;
2124 } else {
2125 printf("pid1 successfully locked range 130:4 for READ\n");
2128 if (cli_read(cli1, fnum1, buf, 130, 4) != 4) {
2129 printf("pid1 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2130 goto fail;
2131 } else {
2132 printf("pid1 successfully read the range 130:4\n");
2135 if (cli_write(cli1, fnum1, 0, buf, 130, 4) != 4) {
2136 printf("pid1 unable to write to the range 130:4, error was %s\n", cli_errstr(cli1));
2137 if (NT_STATUS_V(cli_nt_error(cli1)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
2138 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2139 goto fail;
2141 } else {
2142 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2143 goto fail;
2146 cli_setpid(cli1, 2);
2148 if (cli_read(cli1, fnum1, buf, 130, 4) != 4) {
2149 printf("pid2 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2150 } else {
2151 printf("pid2 successfully read the range 130:4\n");
2154 if (cli_write(cli1, fnum1, 0, buf, 130, 4) != 4) {
2155 printf("pid2 unable to write to the range 130:4, error was %s\n", cli_errstr(cli1));
2156 if (NT_STATUS_V(cli_nt_error(cli1)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
2157 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2158 goto fail;
2160 } else {
2161 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2162 goto fail;
2165 cli_setpid(cli1, 1);
2166 cli_unlock(cli1, fnum1, 130, 4);
2168 if (!cli_lock(cli1, fnum1, 130, 4, 0, WRITE_LOCK)) {
2169 printf("Unable to apply write lock on range 130:4, error was %s\n", cli_errstr(cli1));
2170 goto fail;
2171 } else {
2172 printf("pid1 successfully locked range 130:4 for WRITE\n");
2175 if (cli_read(cli1, fnum1, buf, 130, 4) != 4) {
2176 printf("pid1 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2177 goto fail;
2178 } else {
2179 printf("pid1 successfully read the range 130:4\n");
2182 if (cli_write(cli1, fnum1, 0, buf, 130, 4) != 4) {
2183 printf("pid1 unable to write to the range 130:4, error was %s\n", cli_errstr(cli1));
2184 goto fail;
2185 } else {
2186 printf("pid1 successfully wrote to the range 130:4\n");
2189 cli_setpid(cli1, 2);
2191 if (cli_read(cli1, fnum1, buf, 130, 4) != 4) {
2192 printf("pid2 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2193 if (NT_STATUS_V(cli_nt_error(cli1)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
2194 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2195 goto fail;
2197 } else {
2198 printf("pid2 successfully read the range 130:4 (should be denied)\n");
2199 goto fail;
2202 if (cli_write(cli1, fnum1, 0, buf, 130, 4) != 4) {
2203 printf("pid2 unable to write to the range 130:4, error was %s\n", cli_errstr(cli1));
2204 if (NT_STATUS_V(cli_nt_error(cli1)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
2205 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2206 goto fail;
2208 } else {
2209 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2210 goto fail;
2213 cli_unlock(cli1, fnum1, 130, 0);
2214 correct = True;
2216 fail:
2217 cli_close(cli1, fnum1);
2218 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
2219 torture_close_connection(cli1);
2221 printf("finished locktest7\n");
2222 return correct;
2226 * This demonstrates a problem with our use of GPFS share modes: A file
2227 * descriptor sitting in the pending close queue holding a GPFS share mode
2228 * blocks opening a file another time. Happens with Word 2007 temp files.
2229 * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2230 * open is denied with NT_STATUS_SHARING_VIOLATION.
2233 static bool run_locktest8(int dummy)
2235 struct cli_state *cli1;
2236 const char *fname = "\\lockt8.lck";
2237 uint16_t fnum1, fnum2;
2238 char buf[200];
2239 bool correct = False;
2240 NTSTATUS status;
2242 if (!torture_open_connection(&cli1, 0)) {
2243 return False;
2246 cli_sockopt(cli1, sockops);
2248 printf("starting locktest8\n");
2250 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
2252 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2253 &fnum1);
2254 if (!NT_STATUS_IS_OK(status)) {
2255 d_fprintf(stderr, "cli_open returned %s\n", cli_errstr(cli1));
2256 return false;
2259 memset(buf, 0, sizeof(buf));
2261 status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2262 if (!NT_STATUS_IS_OK(status)) {
2263 d_fprintf(stderr, "cli_open second time returned %s\n",
2264 cli_errstr(cli1));
2265 goto fail;
2268 if (!cli_lock(cli1, fnum2, 1, 1, 0, READ_LOCK)) {
2269 printf("Unable to apply read lock on range 1:1, error was "
2270 "%s\n", cli_errstr(cli1));
2271 goto fail;
2274 status = cli_close(cli1, fnum1);
2275 if (!NT_STATUS_IS_OK(status)) {
2276 d_fprintf(stderr, "cli_close(fnum1) %s\n", cli_errstr(cli1));
2277 goto fail;
2280 status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2281 if (!NT_STATUS_IS_OK(status)) {
2282 d_fprintf(stderr, "cli_open third time returned %s\n",
2283 cli_errstr(cli1));
2284 goto fail;
2287 correct = true;
2289 fail:
2290 cli_close(cli1, fnum1);
2291 cli_close(cli1, fnum2);
2292 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
2293 torture_close_connection(cli1);
2295 printf("finished locktest8\n");
2296 return correct;
2300 * This test is designed to be run in conjunction with
2301 * external NFS or POSIX locks taken in the filesystem.
2302 * It checks that the smbd server will block until the
2303 * lock is released and then acquire it. JRA.
2306 static bool got_alarm;
2307 static int alarm_fd;
2309 static void alarm_handler(int dummy)
2311 got_alarm = True;
2314 static void alarm_handler_parent(int dummy)
2316 close(alarm_fd);
2319 static void do_local_lock(int read_fd, int write_fd)
2321 int fd;
2322 char c = '\0';
2323 struct flock lock;
2324 const char *local_pathname = NULL;
2325 int ret;
2327 local_pathname = talloc_asprintf(talloc_tos(),
2328 "%s/lockt9.lck", local_path);
2329 if (!local_pathname) {
2330 printf("child: alloc fail\n");
2331 exit(1);
2334 unlink(local_pathname);
2335 fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2336 if (fd == -1) {
2337 printf("child: open of %s failed %s.\n",
2338 local_pathname, strerror(errno));
2339 exit(1);
2342 /* Now take a fcntl lock. */
2343 lock.l_type = F_WRLCK;
2344 lock.l_whence = SEEK_SET;
2345 lock.l_start = 0;
2346 lock.l_len = 4;
2347 lock.l_pid = getpid();
2349 ret = fcntl(fd,F_SETLK,&lock);
2350 if (ret == -1) {
2351 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2352 local_pathname, strerror(errno));
2353 exit(1);
2354 } else {
2355 printf("child: got lock 0:4 on file %s.\n",
2356 local_pathname );
2357 fflush(stdout);
2360 CatchSignal(SIGALRM, alarm_handler);
2361 alarm(5);
2362 /* Signal the parent. */
2363 if (write(write_fd, &c, 1) != 1) {
2364 printf("child: start signal fail %s.\n",
2365 strerror(errno));
2366 exit(1);
2368 alarm(0);
2370 alarm(10);
2371 /* Wait for the parent to be ready. */
2372 if (read(read_fd, &c, 1) != 1) {
2373 printf("child: reply signal fail %s.\n",
2374 strerror(errno));
2375 exit(1);
2377 alarm(0);
2379 sleep(5);
2380 close(fd);
2381 printf("child: released lock 0:4 on file %s.\n",
2382 local_pathname );
2383 fflush(stdout);
2384 exit(0);
2387 static bool run_locktest9(int dummy)
2389 struct cli_state *cli1;
2390 const char *fname = "\\lockt9.lck";
2391 uint16_t fnum;
2392 bool correct = False;
2393 int pipe_in[2], pipe_out[2];
2394 pid_t child_pid;
2395 char c = '\0';
2396 int ret;
2397 struct timeval start;
2398 double seconds;
2399 NTSTATUS status;
2401 printf("starting locktest9\n");
2403 if (local_path == NULL) {
2404 d_fprintf(stderr, "locktest9 must be given a local path via -l <localpath>\n");
2405 return false;
2408 if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2409 return false;
2412 child_pid = fork();
2413 if (child_pid == -1) {
2414 return false;
2417 if (child_pid == 0) {
2418 /* Child. */
2419 do_local_lock(pipe_out[0], pipe_in[1]);
2420 exit(0);
2423 close(pipe_out[0]);
2424 close(pipe_in[1]);
2425 pipe_out[0] = -1;
2426 pipe_in[1] = -1;
2428 /* Parent. */
2429 ret = read(pipe_in[0], &c, 1);
2430 if (ret != 1) {
2431 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2432 strerror(errno));
2433 return false;
2436 if (!torture_open_connection(&cli1, 0)) {
2437 return false;
2440 cli_sockopt(cli1, sockops);
2442 status = cli_open(cli1, fname, O_RDWR, DENY_NONE,
2443 &fnum);
2444 if (!NT_STATUS_IS_OK(status)) {
2445 d_fprintf(stderr, "cli_open returned %s\n", cli_errstr(cli1));
2446 return false;
2449 /* Ensure the child has the lock. */
2450 if (cli_lock(cli1, fnum, 0, 4, 0, WRITE_LOCK)) {
2451 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2452 goto fail;
2453 } else {
2454 d_printf("Child has the lock.\n");
2457 /* Tell the child to wait 5 seconds then exit. */
2458 ret = write(pipe_out[1], &c, 1);
2459 if (ret != 1) {
2460 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2461 strerror(errno));
2462 goto fail;
2465 /* Wait 20 seconds for the lock. */
2466 alarm_fd = cli1->fd;
2467 CatchSignal(SIGALRM, alarm_handler_parent);
2468 alarm(20);
2470 start = timeval_current();
2472 if (!cli_lock(cli1, fnum, 0, 4, -1, WRITE_LOCK)) {
2473 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2474 "%s\n", cli_errstr(cli1));
2475 goto fail_nofd;
2477 alarm(0);
2479 seconds = timeval_elapsed(&start);
2481 printf("Parent got the lock after %.2f seconds.\n",
2482 seconds);
2484 status = cli_close(cli1, fnum);
2485 if (!NT_STATUS_IS_OK(status)) {
2486 d_fprintf(stderr, "cli_close(fnum1) %s\n", cli_errstr(cli1));
2487 goto fail;
2490 correct = true;
2492 fail:
2493 cli_close(cli1, fnum);
2494 torture_close_connection(cli1);
2496 fail_nofd:
2498 printf("finished locktest9\n");
2499 return correct;
2503 test whether fnums and tids open on one VC are available on another (a major
2504 security hole)
2506 static bool run_fdpasstest(int dummy)
2508 struct cli_state *cli1, *cli2;
2509 const char *fname = "\\fdpass.tst";
2510 uint16_t fnum1;
2511 char buf[1024];
2513 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2514 return False;
2516 cli_sockopt(cli1, sockops);
2517 cli_sockopt(cli2, sockops);
2519 printf("starting fdpasstest\n");
2521 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
2523 if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1))) {
2524 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1));
2525 return False;
2528 if (cli_write(cli1, fnum1, 0, "hello world\n", 0, 13) != 13) {
2529 printf("write failed (%s)\n", cli_errstr(cli1));
2530 return False;
2533 cli2->vuid = cli1->vuid;
2534 cli2->cnum = cli1->cnum;
2535 cli2->pid = cli1->pid;
2537 if (cli_read(cli2, fnum1, buf, 0, 13) == 13) {
2538 printf("read succeeded! nasty security hole [%s]\n",
2539 buf);
2540 return False;
2543 cli_close(cli1, fnum1);
2544 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
2546 torture_close_connection(cli1);
2547 torture_close_connection(cli2);
2549 printf("finished fdpasstest\n");
2550 return True;
2553 static bool run_fdsesstest(int dummy)
2555 struct cli_state *cli;
2556 uint16 new_vuid;
2557 uint16 saved_vuid;
2558 uint16 new_cnum;
2559 uint16 saved_cnum;
2560 const char *fname = "\\fdsess.tst";
2561 const char *fname1 = "\\fdsess1.tst";
2562 uint16_t fnum1;
2563 uint16_t fnum2;
2564 char buf[1024];
2565 bool ret = True;
2567 if (!torture_open_connection(&cli, 0))
2568 return False;
2569 cli_sockopt(cli, sockops);
2571 if (!torture_cli_session_setup2(cli, &new_vuid))
2572 return False;
2574 saved_cnum = cli->cnum;
2575 if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, share, "?????", "", 1)))
2576 return False;
2577 new_cnum = cli->cnum;
2578 cli->cnum = saved_cnum;
2580 printf("starting fdsesstest\n");
2582 cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
2583 cli_unlink(cli, fname1, aSYSTEM | aHIDDEN);
2585 if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1))) {
2586 printf("open of %s failed (%s)\n", fname, cli_errstr(cli));
2587 return False;
2590 if (cli_write(cli, fnum1, 0, "hello world\n", 0, 13) != 13) {
2591 printf("write failed (%s)\n", cli_errstr(cli));
2592 return False;
2595 saved_vuid = cli->vuid;
2596 cli->vuid = new_vuid;
2598 if (cli_read(cli, fnum1, buf, 0, 13) == 13) {
2599 printf("read succeeded with different vuid! nasty security hole [%s]\n",
2600 buf);
2601 ret = False;
2603 /* Try to open a file with different vuid, samba cnum. */
2604 if (NT_STATUS_IS_OK(cli_open(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
2605 printf("create with different vuid, same cnum succeeded.\n");
2606 cli_close(cli, fnum2);
2607 cli_unlink(cli, fname1, aSYSTEM | aHIDDEN);
2608 } else {
2609 printf("create with different vuid, same cnum failed.\n");
2610 printf("This will cause problems with service clients.\n");
2611 ret = False;
2614 cli->vuid = saved_vuid;
2616 /* Try with same vuid, different cnum. */
2617 cli->cnum = new_cnum;
2619 if (cli_read(cli, fnum1, buf, 0, 13) == 13) {
2620 printf("read succeeded with different cnum![%s]\n",
2621 buf);
2622 ret = False;
2625 cli->cnum = saved_cnum;
2626 cli_close(cli, fnum1);
2627 cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
2629 torture_close_connection(cli);
2631 printf("finished fdsesstest\n");
2632 return ret;
2636 This test checks that
2638 1) the server does not allow an unlink on a file that is open
2640 static bool run_unlinktest(int dummy)
2642 struct cli_state *cli;
2643 const char *fname = "\\unlink.tst";
2644 uint16_t fnum;
2645 bool correct = True;
2647 if (!torture_open_connection(&cli, 0)) {
2648 return False;
2651 cli_sockopt(cli, sockops);
2653 printf("starting unlink test\n");
2655 cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
2657 cli_setpid(cli, 1);
2659 if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum))) {
2660 printf("open of %s failed (%s)\n", fname, cli_errstr(cli));
2661 return False;
2664 if (NT_STATUS_IS_OK(cli_unlink(cli, fname, aSYSTEM | aHIDDEN))) {
2665 printf("error: server allowed unlink on an open file\n");
2666 correct = False;
2667 } else {
2668 correct = check_error(__LINE__, cli, ERRDOS, ERRbadshare,
2669 NT_STATUS_SHARING_VIOLATION);
2672 cli_close(cli, fnum);
2673 cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
2675 if (!torture_close_connection(cli)) {
2676 correct = False;
2679 printf("unlink test finished\n");
2681 return correct;
2686 test how many open files this server supports on the one socket
2688 static bool run_maxfidtest(int dummy)
2690 struct cli_state *cli;
2691 const char *ftemplate = "\\maxfid.%d.%d";
2692 fstring fname;
2693 uint16_t fnums[0x11000];
2694 int i;
2695 int retries=4;
2696 bool correct = True;
2698 cli = current_cli;
2700 if (retries <= 0) {
2701 printf("failed to connect\n");
2702 return False;
2705 cli_sockopt(cli, sockops);
2707 for (i=0; i<0x11000; i++) {
2708 slprintf(fname,sizeof(fname)-1,ftemplate, i,(int)getpid());
2709 if (!NT_STATUS_IS_OK(cli_open(cli, fname,
2710 O_RDWR|O_CREAT|O_TRUNC, DENY_NONE, &fnums[i]))) {
2711 printf("open of %s failed (%s)\n",
2712 fname, cli_errstr(cli));
2713 printf("maximum fnum is %d\n", i);
2714 break;
2716 printf("%6d\r", i);
2718 printf("%6d\n", i);
2719 i--;
2721 printf("cleaning up\n");
2722 for (;i>=0;i--) {
2723 slprintf(fname,sizeof(fname)-1,ftemplate, i,(int)getpid());
2724 cli_close(cli, fnums[i]);
2725 if (!NT_STATUS_IS_OK(cli_unlink(cli, fname, aSYSTEM | aHIDDEN))) {
2726 printf("unlink of %s failed (%s)\n",
2727 fname, cli_errstr(cli));
2728 correct = False;
2730 printf("%6d\r", i);
2732 printf("%6d\n", 0);
2734 printf("maxfid test finished\n");
2735 if (!torture_close_connection(cli)) {
2736 correct = False;
2738 return correct;
2741 /* generate a random buffer */
2742 static void rand_buf(char *buf, int len)
2744 while (len--) {
2745 *buf = (char)sys_random();
2746 buf++;
2750 /* send smb negprot commands, not reading the response */
2751 static bool run_negprot_nowait(int dummy)
2753 int i;
2754 static struct cli_state *cli;
2755 bool correct = True;
2757 printf("starting negprot nowait test\n");
2759 if (!(cli = open_nbt_connection())) {
2760 return False;
2763 for (i=0;i<50000;i++) {
2764 cli_negprot_sendsync(cli);
2767 if (!torture_close_connection(cli)) {
2768 correct = False;
2771 printf("finished negprot nowait test\n");
2773 return correct;
2776 /* send smb negprot commands, not reading the response */
2777 static bool run_bad_nbt_session(int dummy)
2779 static struct cli_state *cli;
2781 printf("starting bad nbt session test\n");
2783 if (!(cli = open_bad_nbt_connection())) {
2784 return False;
2787 cli_shutdown(cli);
2788 printf("finished bad nbt session test\n");
2789 return true;
2792 /* send random IPC commands */
2793 static bool run_randomipc(int dummy)
2795 char *rparam = NULL;
2796 char *rdata = NULL;
2797 unsigned int rdrcnt,rprcnt;
2798 char param[1024];
2799 int api, param_len, i;
2800 struct cli_state *cli;
2801 bool correct = True;
2802 int count = 50000;
2804 printf("starting random ipc test\n");
2806 if (!torture_open_connection(&cli, 0)) {
2807 return False;
2810 for (i=0;i<count;i++) {
2811 api = sys_random() % 500;
2812 param_len = (sys_random() % 64);
2814 rand_buf(param, param_len);
2816 SSVAL(param,0,api);
2818 cli_api(cli,
2819 param, param_len, 8,
2820 NULL, 0, BUFFER_SIZE,
2821 &rparam, &rprcnt,
2822 &rdata, &rdrcnt);
2823 if (i % 100 == 0) {
2824 printf("%d/%d\r", i,count);
2827 printf("%d/%d\n", i, count);
2829 if (!torture_close_connection(cli)) {
2830 correct = False;
2833 printf("finished random ipc test\n");
2835 return correct;
2840 static void browse_callback(const char *sname, uint32 stype,
2841 const char *comment, void *state)
2843 printf("\t%20.20s %08x %s\n", sname, stype, comment);
2849 This test checks the browse list code
2852 static bool run_browsetest(int dummy)
2854 static struct cli_state *cli;
2855 bool correct = True;
2857 printf("starting browse test\n");
2859 if (!torture_open_connection(&cli, 0)) {
2860 return False;
2863 printf("domain list:\n");
2864 cli_NetServerEnum(cli, cli->server_domain,
2865 SV_TYPE_DOMAIN_ENUM,
2866 browse_callback, NULL);
2868 printf("machine list:\n");
2869 cli_NetServerEnum(cli, cli->server_domain,
2870 SV_TYPE_ALL,
2871 browse_callback, NULL);
2873 if (!torture_close_connection(cli)) {
2874 correct = False;
2877 printf("browse test finished\n");
2879 return correct;
2885 This checks how the getatr calls works
2887 static bool run_attrtest(int dummy)
2889 struct cli_state *cli;
2890 uint16_t fnum;
2891 time_t t, t2;
2892 const char *fname = "\\attrib123456789.tst";
2893 bool correct = True;
2895 printf("starting attrib test\n");
2897 if (!torture_open_connection(&cli, 0)) {
2898 return False;
2901 cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
2902 cli_open(cli, fname,
2903 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
2904 cli_close(cli, fnum);
2905 if (!NT_STATUS_IS_OK(cli_getatr(cli, fname, NULL, NULL, &t))) {
2906 printf("getatr failed (%s)\n", cli_errstr(cli));
2907 correct = False;
2910 if (abs(t - time(NULL)) > 60*60*24*10) {
2911 printf("ERROR: SMBgetatr bug. time is %s",
2912 ctime(&t));
2913 t = time(NULL);
2914 correct = True;
2917 t2 = t-60*60*24; /* 1 day ago */
2919 if (!NT_STATUS_IS_OK(cli_setatr(cli, fname, 0, t2))) {
2920 printf("setatr failed (%s)\n", cli_errstr(cli));
2921 correct = True;
2924 if (!NT_STATUS_IS_OK(cli_getatr(cli, fname, NULL, NULL, &t))) {
2925 printf("getatr failed (%s)\n", cli_errstr(cli));
2926 correct = True;
2929 if (t != t2) {
2930 printf("ERROR: getatr/setatr bug. times are\n%s",
2931 ctime(&t));
2932 printf("%s", ctime(&t2));
2933 correct = True;
2936 cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
2938 if (!torture_close_connection(cli)) {
2939 correct = False;
2942 printf("attrib test finished\n");
2944 return correct;
2949 This checks a couple of trans2 calls
2951 static bool run_trans2test(int dummy)
2953 struct cli_state *cli;
2954 uint16_t fnum;
2955 SMB_OFF_T size;
2956 time_t c_time, a_time, m_time;
2957 struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
2958 const char *fname = "\\trans2.tst";
2959 const char *dname = "\\trans2";
2960 const char *fname2 = "\\trans2\\trans2.tst";
2961 char pname[1024];
2962 bool correct = True;
2963 NTSTATUS status;
2964 uint32_t fs_attr;
2966 printf("starting trans2 test\n");
2968 if (!torture_open_connection(&cli, 0)) {
2969 return False;
2972 status = cli_get_fs_attr_info(cli, &fs_attr);
2973 if (!NT_STATUS_IS_OK(status)) {
2974 printf("ERROR: cli_get_fs_attr_info returned %s\n",
2975 nt_errstr(status));
2976 correct = false;
2979 cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
2980 cli_open(cli, fname,
2981 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
2982 if (!NT_STATUS_IS_OK(cli_qfileinfo_basic(
2983 cli, fnum, NULL, &size, &c_time_ts,
2984 &a_time_ts, &w_time_ts,
2985 &m_time_ts, NULL))) {
2986 printf("ERROR: qfileinfo failed (%s)\n", cli_errstr(cli));
2987 correct = False;
2990 if (!NT_STATUS_IS_OK(cli_qfilename(cli, fnum, pname, sizeof(pname)))) {
2991 printf("ERROR: qfilename failed (%s)\n", cli_errstr(cli));
2992 correct = False;
2995 if (strcmp(pname, fname)) {
2996 printf("qfilename gave different name? [%s] [%s]\n",
2997 fname, pname);
2998 correct = False;
3001 cli_close(cli, fnum);
3003 sleep(2);
3005 cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
3006 if (!NT_STATUS_IS_OK(cli_open(cli, fname,
3007 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum))) {
3008 printf("open of %s failed (%s)\n", fname, cli_errstr(cli));
3009 return False;
3011 cli_close(cli, fnum);
3013 status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
3014 NULL);
3015 if (!NT_STATUS_IS_OK(status)) {
3016 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
3017 correct = False;
3018 } else {
3019 if (c_time != m_time) {
3020 printf("create time=%s", ctime(&c_time));
3021 printf("modify time=%s", ctime(&m_time));
3022 printf("This system appears to have sticky create times\n");
3024 if (a_time % (60*60) == 0) {
3025 printf("access time=%s", ctime(&a_time));
3026 printf("This system appears to set a midnight access time\n");
3027 correct = False;
3030 if (abs(m_time - time(NULL)) > 60*60*24*7) {
3031 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
3032 correct = False;
3037 cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
3038 cli_open(cli, fname,
3039 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3040 cli_close(cli, fnum);
3041 status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
3042 &m_time_ts, &size, NULL, NULL);
3043 if (!NT_STATUS_IS_OK(status)) {
3044 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3045 correct = False;
3046 } else {
3047 if (w_time_ts.tv_sec < 60*60*24*2) {
3048 printf("write time=%s", ctime(&w_time_ts.tv_sec));
3049 printf("This system appears to set a initial 0 write time\n");
3050 correct = False;
3054 cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
3057 /* check if the server updates the directory modification time
3058 when creating a new file */
3059 if (!NT_STATUS_IS_OK(cli_mkdir(cli, dname))) {
3060 printf("ERROR: mkdir failed (%s)\n", cli_errstr(cli));
3061 correct = False;
3063 sleep(3);
3064 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3065 &w_time_ts, &m_time_ts, &size, NULL, NULL);
3066 if (!NT_STATUS_IS_OK(status)) {
3067 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3068 correct = False;
3071 cli_open(cli, fname2,
3072 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3073 cli_write(cli, fnum, 0, (char *)&fnum, 0, sizeof(fnum));
3074 cli_close(cli, fnum);
3075 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3076 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
3077 if (!NT_STATUS_IS_OK(status)) {
3078 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3079 correct = False;
3080 } else {
3081 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
3082 == 0) {
3083 printf("This system does not update directory modification times\n");
3084 correct = False;
3087 cli_unlink(cli, fname2, aSYSTEM | aHIDDEN);
3088 cli_rmdir(cli, dname);
3090 if (!torture_close_connection(cli)) {
3091 correct = False;
3094 printf("trans2 test finished\n");
3096 return correct;
3100 This checks new W2K calls.
3103 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
3105 uint8_t *buf = NULL;
3106 uint32 len;
3107 NTSTATUS status;
3109 status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
3110 pcli->max_xmit, &buf, &len);
3111 if (!NT_STATUS_IS_OK(status)) {
3112 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
3113 nt_errstr(status));
3114 } else {
3115 printf("qfileinfo: level %d, len = %u\n", level, len);
3116 dump_data(0, (uint8 *)buf, len);
3117 printf("\n");
3119 TALLOC_FREE(buf);
3120 return status;
3123 static bool run_w2ktest(int dummy)
3125 struct cli_state *cli;
3126 uint16_t fnum;
3127 const char *fname = "\\w2ktest\\w2k.tst";
3128 int level;
3129 bool correct = True;
3131 printf("starting w2k test\n");
3133 if (!torture_open_connection(&cli, 0)) {
3134 return False;
3137 cli_open(cli, fname,
3138 O_RDWR | O_CREAT , DENY_NONE, &fnum);
3140 for (level = 1004; level < 1040; level++) {
3141 new_trans(cli, fnum, level);
3144 cli_close(cli, fnum);
3146 if (!torture_close_connection(cli)) {
3147 correct = False;
3150 printf("w2k test finished\n");
3152 return correct;
3157 this is a harness for some oplock tests
3159 static bool run_oplock1(int dummy)
3161 struct cli_state *cli1;
3162 const char *fname = "\\lockt1.lck";
3163 uint16_t fnum1;
3164 bool correct = True;
3166 printf("starting oplock test 1\n");
3168 if (!torture_open_connection(&cli1, 0)) {
3169 return False;
3172 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3174 cli_sockopt(cli1, sockops);
3176 cli1->use_oplocks = True;
3178 if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1))) {
3179 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1));
3180 return False;
3183 cli1->use_oplocks = False;
3185 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3186 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3188 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3189 printf("close2 failed (%s)\n", cli_errstr(cli1));
3190 return False;
3193 if (!NT_STATUS_IS_OK(cli_unlink(cli1, fname, aSYSTEM | aHIDDEN))) {
3194 printf("unlink failed (%s)\n", cli_errstr(cli1));
3195 return False;
3198 if (!torture_close_connection(cli1)) {
3199 correct = False;
3202 printf("finished oplock test 1\n");
3204 return correct;
3207 static bool run_oplock2(int dummy)
3209 struct cli_state *cli1, *cli2;
3210 const char *fname = "\\lockt2.lck";
3211 uint16_t fnum1, fnum2;
3212 int saved_use_oplocks = use_oplocks;
3213 char buf[4];
3214 bool correct = True;
3215 volatile bool *shared_correct;
3217 shared_correct = (volatile bool *)shm_setup(sizeof(bool));
3218 *shared_correct = True;
3220 use_level_II_oplocks = True;
3221 use_oplocks = True;
3223 printf("starting oplock test 2\n");
3225 if (!torture_open_connection(&cli1, 0)) {
3226 use_level_II_oplocks = False;
3227 use_oplocks = saved_use_oplocks;
3228 return False;
3231 cli1->use_oplocks = True;
3232 cli1->use_level_II_oplocks = True;
3234 if (!torture_open_connection(&cli2, 1)) {
3235 use_level_II_oplocks = False;
3236 use_oplocks = saved_use_oplocks;
3237 return False;
3240 cli2->use_oplocks = True;
3241 cli2->use_level_II_oplocks = True;
3243 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3245 cli_sockopt(cli1, sockops);
3246 cli_sockopt(cli2, sockops);
3248 if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1))) {
3249 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1));
3250 return False;
3253 /* Don't need the globals any more. */
3254 use_level_II_oplocks = False;
3255 use_oplocks = saved_use_oplocks;
3257 if (fork() == 0) {
3258 /* Child code */
3259 if (!NT_STATUS_IS_OK(cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2))) {
3260 printf("second open of %s failed (%s)\n", fname, cli_errstr(cli1));
3261 *shared_correct = False;
3262 exit(0);
3265 sleep(2);
3267 if (!NT_STATUS_IS_OK(cli_close(cli2, fnum2))) {
3268 printf("close2 failed (%s)\n", cli_errstr(cli1));
3269 *shared_correct = False;
3272 exit(0);
3275 sleep(2);
3277 /* Ensure cli1 processes the break. Empty file should always return 0
3278 * bytes. */
3280 if (cli_read(cli1, fnum1, buf, 0, 4) != 0) {
3281 printf("read on fnum1 failed (%s)\n", cli_errstr(cli1));
3282 correct = False;
3285 /* Should now be at level II. */
3286 /* Test if sending a write locks causes a break to none. */
3288 if (!cli_lock(cli1, fnum1, 0, 4, 0, READ_LOCK)) {
3289 printf("lock failed (%s)\n", cli_errstr(cli1));
3290 correct = False;
3293 cli_unlock(cli1, fnum1, 0, 4);
3295 sleep(2);
3297 if (!cli_lock(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) {
3298 printf("lock failed (%s)\n", cli_errstr(cli1));
3299 correct = False;
3302 cli_unlock(cli1, fnum1, 0, 4);
3304 sleep(2);
3306 cli_read(cli1, fnum1, buf, 0, 4);
3308 #if 0
3309 if (cli_write(cli1, fnum1, 0, buf, 0, 4) != 4) {
3310 printf("write on fnum1 failed (%s)\n", cli_errstr(cli1));
3311 correct = False;
3313 #endif
3315 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3316 printf("close1 failed (%s)\n", cli_errstr(cli1));
3317 correct = False;
3320 sleep(4);
3322 if (!NT_STATUS_IS_OK(cli_unlink(cli1, fname, aSYSTEM | aHIDDEN))) {
3323 printf("unlink failed (%s)\n", cli_errstr(cli1));
3324 correct = False;
3327 if (!torture_close_connection(cli1)) {
3328 correct = False;
3331 if (!*shared_correct) {
3332 correct = False;
3335 printf("finished oplock test 2\n");
3337 return correct;
3340 /* handler for oplock 3 tests */
3341 static NTSTATUS oplock3_handler(struct cli_state *cli, uint16_t fnum, unsigned char level)
3343 printf("got oplock break fnum=%d level=%d\n",
3344 fnum, level);
3345 return cli_oplock_ack(cli, fnum, level);
3348 static bool run_oplock3(int dummy)
3350 struct cli_state *cli;
3351 const char *fname = "\\oplockt3.dat";
3352 uint16_t fnum;
3353 char buf[4] = "abcd";
3354 bool correct = True;
3355 volatile bool *shared_correct;
3357 shared_correct = (volatile bool *)shm_setup(sizeof(bool));
3358 *shared_correct = True;
3360 printf("starting oplock test 3\n");
3362 if (fork() == 0) {
3363 /* Child code */
3364 use_oplocks = True;
3365 use_level_II_oplocks = True;
3366 if (!torture_open_connection(&cli, 0)) {
3367 *shared_correct = False;
3368 exit(0);
3370 sleep(2);
3371 /* try to trigger a oplock break in parent */
3372 cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum);
3373 cli_write(cli, fnum, 0, buf, 0, 4);
3374 exit(0);
3377 /* parent code */
3378 use_oplocks = True;
3379 use_level_II_oplocks = True;
3380 if (!torture_open_connection(&cli, 1)) { /* other is forked */
3381 return False;
3383 cli_oplock_handler(cli, oplock3_handler);
3384 cli_open(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum);
3385 cli_write(cli, fnum, 0, buf, 0, 4);
3386 cli_close(cli, fnum);
3387 cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum);
3388 cli->timeout = 20000;
3389 cli_receive_smb(cli);
3390 printf("finished oplock test 3\n");
3392 return (correct && *shared_correct);
3394 /* What are we looking for here? What's sucess and what's FAILURE? */
3400 Test delete on close semantics.
3402 static bool run_deletetest(int dummy)
3404 struct cli_state *cli1 = NULL;
3405 struct cli_state *cli2 = NULL;
3406 const char *fname = "\\delete.file";
3407 uint16_t fnum1 = (uint16_t)-1;
3408 uint16_t fnum2 = (uint16_t)-1;
3409 bool correct = True;
3411 printf("starting delete test\n");
3413 if (!torture_open_connection(&cli1, 0)) {
3414 return False;
3417 cli_sockopt(cli1, sockops);
3419 /* Test 1 - this should delete the file on close. */
3421 cli_setatr(cli1, fname, 0, 0);
3422 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3424 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
3425 0, FILE_OVERWRITE_IF,
3426 FILE_DELETE_ON_CLOSE, 0, &fnum1))) {
3427 printf("[1] open of %s failed (%s)\n", fname, cli_errstr(cli1));
3428 correct = False;
3429 goto fail;
3432 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3433 printf("[1] close failed (%s)\n", cli_errstr(cli1));
3434 correct = False;
3435 goto fail;
3438 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1))) {
3439 printf("[1] open of %s succeeded (should fail)\n", fname);
3440 correct = False;
3441 goto fail;
3444 printf("first delete on close test succeeded.\n");
3446 /* Test 2 - this should delete the file on close. */
3448 cli_setatr(cli1, fname, 0, 0);
3449 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3451 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3452 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
3453 FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
3454 printf("[2] open of %s failed (%s)\n", fname, cli_errstr(cli1));
3455 correct = False;
3456 goto fail;
3459 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
3460 printf("[2] setting delete_on_close failed (%s)\n", cli_errstr(cli1));
3461 correct = False;
3462 goto fail;
3465 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3466 printf("[2] close failed (%s)\n", cli_errstr(cli1));
3467 correct = False;
3468 goto fail;
3471 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3472 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
3473 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3474 printf("[2] close failed (%s)\n", cli_errstr(cli1));
3475 correct = False;
3476 goto fail;
3478 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3479 } else
3480 printf("second delete on close test succeeded.\n");
3482 /* Test 3 - ... */
3483 cli_setatr(cli1, fname, 0, 0);
3484 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3486 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
3487 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
3488 printf("[3] open - 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
3489 correct = False;
3490 goto fail;
3493 /* This should fail with a sharing violation - open for delete is only compatible
3494 with SHARE_DELETE. */
3496 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
3497 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, 0, &fnum2))) {
3498 printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
3499 correct = False;
3500 goto fail;
3503 /* This should succeed. */
3505 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
3506 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0, 0, &fnum2))) {
3507 printf("[3] open - 2 of %s failed (%s)\n", fname, cli_errstr(cli1));
3508 correct = False;
3509 goto fail;
3512 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
3513 printf("[3] setting delete_on_close failed (%s)\n", cli_errstr(cli1));
3514 correct = False;
3515 goto fail;
3518 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3519 printf("[3] close 1 failed (%s)\n", cli_errstr(cli1));
3520 correct = False;
3521 goto fail;
3524 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
3525 printf("[3] close 2 failed (%s)\n", cli_errstr(cli1));
3526 correct = False;
3527 goto fail;
3530 /* This should fail - file should no longer be there. */
3532 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3533 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
3534 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3535 printf("[3] close failed (%s)\n", cli_errstr(cli1));
3537 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3538 correct = False;
3539 goto fail;
3540 } else
3541 printf("third delete on close test succeeded.\n");
3543 /* Test 4 ... */
3544 cli_setatr(cli1, fname, 0, 0);
3545 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3547 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
3548 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
3549 printf("[4] open of %s failed (%s)\n", fname, cli_errstr(cli1));
3550 correct = False;
3551 goto fail;
3554 /* This should succeed. */
3555 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3556 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0, 0, &fnum2))) {
3557 printf("[4] open - 2 of %s failed (%s)\n", fname, cli_errstr(cli1));
3558 correct = False;
3559 goto fail;
3562 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
3563 printf("[4] close - 1 failed (%s)\n", cli_errstr(cli1));
3564 correct = False;
3565 goto fail;
3568 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
3569 printf("[4] setting delete_on_close failed (%s)\n", cli_errstr(cli1));
3570 correct = False;
3571 goto fail;
3574 /* This should fail - no more opens once delete on close set. */
3575 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3576 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3577 FILE_OPEN, 0, 0, &fnum2))) {
3578 printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
3579 correct = False;
3580 goto fail;
3581 } else
3582 printf("fourth delete on close test succeeded.\n");
3584 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3585 printf("[4] close - 2 failed (%s)\n", cli_errstr(cli1));
3586 correct = False;
3587 goto fail;
3590 /* Test 5 ... */
3591 cli_setatr(cli1, fname, 0, 0);
3592 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3594 if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1))) {
3595 printf("[5] open of %s failed (%s)\n", fname, cli_errstr(cli1));
3596 correct = False;
3597 goto fail;
3600 /* This should fail - only allowed on NT opens with DELETE access. */
3602 if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
3603 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
3604 correct = False;
3605 goto fail;
3608 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3609 printf("[5] close - 2 failed (%s)\n", cli_errstr(cli1));
3610 correct = False;
3611 goto fail;
3614 printf("fifth delete on close test succeeded.\n");
3616 /* Test 6 ... */
3617 cli_setatr(cli1, fname, 0, 0);
3618 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3620 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
3621 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3622 FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
3623 printf("[6] open of %s failed (%s)\n", fname, cli_errstr(cli1));
3624 correct = False;
3625 goto fail;
3628 /* This should fail - only allowed on NT opens with DELETE access. */
3630 if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
3631 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
3632 correct = False;
3633 goto fail;
3636 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3637 printf("[6] close - 2 failed (%s)\n", cli_errstr(cli1));
3638 correct = False;
3639 goto fail;
3642 printf("sixth delete on close test succeeded.\n");
3644 /* Test 7 ... */
3645 cli_setatr(cli1, fname, 0, 0);
3646 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3648 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
3649 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
3650 printf("[7] open of %s failed (%s)\n", fname, cli_errstr(cli1));
3651 correct = False;
3652 goto fail;
3655 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
3656 printf("[7] setting delete_on_close on file failed !\n");
3657 correct = False;
3658 goto fail;
3661 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, false))) {
3662 printf("[7] unsetting delete_on_close on file failed !\n");
3663 correct = False;
3664 goto fail;
3667 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3668 printf("[7] close - 2 failed (%s)\n", cli_errstr(cli1));
3669 correct = False;
3670 goto fail;
3673 /* This next open should succeed - we reset the flag. */
3675 if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3676 printf("[5] open of %s failed (%s)\n", fname, cli_errstr(cli1));
3677 correct = False;
3678 goto fail;
3681 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3682 printf("[7] close - 2 failed (%s)\n", cli_errstr(cli1));
3683 correct = False;
3684 goto fail;
3687 printf("seventh delete on close test succeeded.\n");
3689 /* Test 7 ... */
3690 cli_setatr(cli1, fname, 0, 0);
3691 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3693 if (!torture_open_connection(&cli2, 1)) {
3694 printf("[8] failed to open second connection.\n");
3695 correct = False;
3696 goto fail;
3699 cli_sockopt(cli1, sockops);
3701 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
3702 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3703 FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
3704 printf("[8] open 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
3705 correct = False;
3706 goto fail;
3709 if (!NT_STATUS_IS_OK(cli_ntcreate(cli2, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
3710 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3711 FILE_OPEN, 0, 0, &fnum2))) {
3712 printf("[8] open 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
3713 correct = False;
3714 goto fail;
3717 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
3718 printf("[8] setting delete_on_close on file failed !\n");
3719 correct = False;
3720 goto fail;
3723 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3724 printf("[8] close - 1 failed (%s)\n", cli_errstr(cli1));
3725 correct = False;
3726 goto fail;
3729 if (!NT_STATUS_IS_OK(cli_close(cli2, fnum2))) {
3730 printf("[8] close - 2 failed (%s)\n", cli_errstr(cli2));
3731 correct = False;
3732 goto fail;
3735 /* This should fail.. */
3736 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3737 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
3738 goto fail;
3739 correct = False;
3740 } else
3741 printf("eighth delete on close test succeeded.\n");
3743 /* This should fail - we need to set DELETE_ACCESS. */
3744 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0,FILE_READ_DATA|FILE_WRITE_DATA,
3745 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE, 0, &fnum1))) {
3746 printf("[9] open of %s succeeded should have failed!\n", fname);
3747 correct = False;
3748 goto fail;
3751 printf("ninth delete on close test succeeded.\n");
3753 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
3754 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE, 0, &fnum1))) {
3755 printf("[10] open of %s failed (%s)\n", fname, cli_errstr(cli1));
3756 correct = False;
3757 goto fail;
3760 /* This should delete the file. */
3761 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3762 printf("[10] close failed (%s)\n", cli_errstr(cli1));
3763 correct = False;
3764 goto fail;
3767 /* This should fail.. */
3768 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3769 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
3770 goto fail;
3771 correct = False;
3772 } else
3773 printf("tenth delete on close test succeeded.\n");
3775 cli_setatr(cli1, fname, 0, 0);
3776 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3778 /* What error do we get when attempting to open a read-only file with
3779 delete access ? */
3781 /* Create a readonly file. */
3782 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
3783 FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
3784 printf("[11] open of %s failed (%s)\n", fname, cli_errstr(cli1));
3785 correct = False;
3786 goto fail;
3789 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3790 printf("[11] close failed (%s)\n", cli_errstr(cli1));
3791 correct = False;
3792 goto fail;
3795 /* Now try open for delete access. */
3796 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES|DELETE_ACCESS,
3797 0, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3798 FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
3799 printf("[11] open of %s succeeded should have been denied with ACCESS_DENIED!\n", fname);
3800 cli_close(cli1, fnum1);
3801 goto fail;
3802 correct = False;
3803 } else {
3804 NTSTATUS nterr = cli_nt_error(cli1);
3805 if (!NT_STATUS_EQUAL(nterr,NT_STATUS_ACCESS_DENIED)) {
3806 printf("[11] open of %s should have been denied with ACCESS_DENIED! Got error %s\n", fname, nt_errstr(nterr));
3807 goto fail;
3808 correct = False;
3809 } else {
3810 printf("eleventh delete on close test succeeded.\n");
3814 printf("finished delete test\n");
3816 fail:
3817 /* FIXME: This will crash if we aborted before cli2 got
3818 * intialized, because these functions don't handle
3819 * uninitialized connections. */
3821 if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
3822 if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
3823 cli_setatr(cli1, fname, 0, 0);
3824 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3826 if (cli1 && !torture_close_connection(cli1)) {
3827 correct = False;
3829 if (cli2 && !torture_close_connection(cli2)) {
3830 correct = False;
3832 return correct;
3837 print out server properties
3839 static bool run_properties(int dummy)
3841 struct cli_state *cli;
3842 bool correct = True;
3844 printf("starting properties test\n");
3846 ZERO_STRUCT(cli);
3848 if (!torture_open_connection(&cli, 0)) {
3849 return False;
3852 cli_sockopt(cli, sockops);
3854 d_printf("Capabilities 0x%08x\n", cli->capabilities);
3856 if (!torture_close_connection(cli)) {
3857 correct = False;
3860 return correct;
3865 /* FIRST_DESIRED_ACCESS 0xf019f */
3866 #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
3867 FILE_READ_EA| /* 0xf */ \
3868 FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
3869 FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
3870 DELETE_ACCESS|READ_CONTROL_ACCESS|\
3871 WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
3872 /* SECOND_DESIRED_ACCESS 0xe0080 */
3873 #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
3874 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
3875 WRITE_OWNER_ACCESS /* 0xe0000 */
3877 #if 0
3878 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
3879 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
3880 FILE_READ_DATA|\
3881 WRITE_OWNER_ACCESS /* */
3882 #endif
3885 Test ntcreate calls made by xcopy
3887 static bool run_xcopy(int dummy)
3889 static struct cli_state *cli1;
3890 const char *fname = "\\test.txt";
3891 bool correct = True;
3892 uint16_t fnum1, fnum2;
3894 printf("starting xcopy test\n");
3896 if (!torture_open_connection(&cli1, 0)) {
3897 return False;
3900 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0,
3901 FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
3902 FILE_SHARE_NONE, FILE_OVERWRITE_IF,
3903 0x4044, 0, &fnum1))) {
3904 printf("First open failed - %s\n", cli_errstr(cli1));
3905 return False;
3908 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0,
3909 SECOND_DESIRED_ACCESS, 0,
3910 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN,
3911 0x200000, 0, &fnum2))) {
3912 printf("second open failed - %s\n", cli_errstr(cli1));
3913 return False;
3916 if (!torture_close_connection(cli1)) {
3917 correct = False;
3920 return correct;
3924 Test rename on files open with share delete and no share delete.
3926 static bool run_rename(int dummy)
3928 static struct cli_state *cli1;
3929 const char *fname = "\\test.txt";
3930 const char *fname1 = "\\test1.txt";
3931 bool correct = True;
3932 uint16_t fnum1;
3933 uint16_t attr;
3934 NTSTATUS status;
3936 printf("starting rename test\n");
3938 if (!torture_open_connection(&cli1, 0)) {
3939 return False;
3942 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3943 cli_unlink(cli1, fname1, aSYSTEM | aHIDDEN);
3944 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
3945 FILE_SHARE_READ, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
3946 printf("First open failed - %s\n", cli_errstr(cli1));
3947 return False;
3950 if (!NT_STATUS_IS_OK(cli_rename(cli1, fname, fname1))) {
3951 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", cli_errstr(cli1));
3952 } else {
3953 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
3954 correct = False;
3957 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3958 printf("close - 1 failed (%s)\n", cli_errstr(cli1));
3959 return False;
3962 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3963 cli_unlink(cli1, fname1, aSYSTEM | aHIDDEN);
3964 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
3965 #if 0
3966 FILE_SHARE_DELETE|FILE_SHARE_NONE,
3967 #else
3968 FILE_SHARE_DELETE|FILE_SHARE_READ,
3969 #endif
3970 FILE_OVERWRITE_IF, 0, 0, &fnum1);
3971 if (!NT_STATUS_IS_OK(status)) {
3972 printf("Second open failed - %s\n", cli_errstr(cli1));
3973 return False;
3976 if (!NT_STATUS_IS_OK(cli_rename(cli1, fname, fname1))) {
3977 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", cli_errstr(cli1));
3978 correct = False;
3979 } else {
3980 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
3983 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3984 printf("close - 2 failed (%s)\n", cli_errstr(cli1));
3985 return False;
3988 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3989 cli_unlink(cli1, fname1, aSYSTEM | aHIDDEN);
3991 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS, FILE_ATTRIBUTE_NORMAL,
3992 FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
3993 printf("Third open failed - %s\n", cli_errstr(cli1));
3994 return False;
3998 #if 0
4000 uint16_t fnum2;
4002 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
4003 FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4004 printf("Fourth open failed - %s\n", cli_errstr(cli1));
4005 return False;
4007 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum2, true))) {
4008 printf("[8] setting delete_on_close on file failed !\n");
4009 return False;
4012 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
4013 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
4014 return False;
4017 #endif
4019 if (!NT_STATUS_IS_OK(cli_rename(cli1, fname, fname1))) {
4020 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", cli_errstr(cli1));
4021 correct = False;
4022 } else {
4023 printf("Third rename succeeded (SHARE_NONE)\n");
4026 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4027 printf("close - 3 failed (%s)\n", cli_errstr(cli1));
4028 return False;
4031 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4032 cli_unlink(cli1, fname1, aSYSTEM | aHIDDEN);
4034 /*----*/
4036 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4037 FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4038 printf("Fourth open failed - %s\n", cli_errstr(cli1));
4039 return False;
4042 if (!NT_STATUS_IS_OK(cli_rename(cli1, fname, fname1))) {
4043 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", cli_errstr(cli1));
4044 } else {
4045 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
4046 correct = False;
4049 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4050 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
4051 return False;
4054 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4055 cli_unlink(cli1, fname1, aSYSTEM | aHIDDEN);
4057 /*--*/
4059 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4060 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4061 printf("Fifth open failed - %s\n", cli_errstr(cli1));
4062 return False;
4065 if (!NT_STATUS_IS_OK(cli_rename(cli1, fname, fname1))) {
4066 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n",
4067 cli_errstr(cli1));
4068 correct = False;
4069 } else {
4070 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", cli_errstr(cli1));
4074 * Now check if the first name still exists ...
4077 /* if (!NT_STATUS_OP(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4078 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4079 printf("Opening original file after rename of open file fails: %s\n",
4080 cli_errstr(cli1));
4082 else {
4083 printf("Opening original file after rename of open file works ...\n");
4084 (void)cli_close(cli1, fnum2);
4085 } */
4087 /*--*/
4088 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4089 printf("close - 5 failed (%s)\n", cli_errstr(cli1));
4090 return False;
4093 /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
4094 if (!NT_STATUS_IS_OK(cli_getatr(cli1, fname1, &attr, NULL, NULL))) {
4095 printf("getatr on file %s failed - %s ! \n",
4096 fname1,
4097 cli_errstr(cli1));
4098 correct = False;
4099 } else {
4100 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
4101 printf("Renamed file %s has wrong attr 0x%x "
4102 "(should be 0x%x)\n",
4103 fname1,
4104 attr,
4105 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
4106 correct = False;
4107 } else {
4108 printf("Renamed file %s has archive bit set\n", fname1);
4112 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4113 cli_unlink(cli1, fname1, aSYSTEM | aHIDDEN);
4115 if (!torture_close_connection(cli1)) {
4116 correct = False;
4119 return correct;
4122 static bool run_pipe_number(int dummy)
4124 struct cli_state *cli1;
4125 const char *pipe_name = "\\SPOOLSS";
4126 uint16_t fnum;
4127 int num_pipes = 0;
4129 printf("starting pipenumber test\n");
4130 if (!torture_open_connection(&cli1, 0)) {
4131 return False;
4134 cli_sockopt(cli1, sockops);
4135 while(1) {
4136 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
4137 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN_IF, 0, 0, &fnum))) {
4138 printf("Open of pipe %s failed with error (%s)\n", pipe_name, cli_errstr(cli1));
4139 break;
4141 num_pipes++;
4142 printf("\r%6d", num_pipes);
4145 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
4146 torture_close_connection(cli1);
4147 return True;
4151 Test open mode returns on read-only files.
4153 static bool run_opentest(int dummy)
4155 static struct cli_state *cli1;
4156 static struct cli_state *cli2;
4157 const char *fname = "\\readonly.file";
4158 uint16_t fnum1, fnum2;
4159 char buf[20];
4160 SMB_OFF_T fsize;
4161 bool correct = True;
4162 char *tmp_path;
4164 printf("starting open test\n");
4166 if (!torture_open_connection(&cli1, 0)) {
4167 return False;
4170 cli_setatr(cli1, fname, 0, 0);
4171 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4173 cli_sockopt(cli1, sockops);
4175 if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1))) {
4176 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1));
4177 return False;
4180 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4181 printf("close2 failed (%s)\n", cli_errstr(cli1));
4182 return False;
4185 if (!NT_STATUS_IS_OK(cli_setatr(cli1, fname, aRONLY, 0))) {
4186 printf("cli_setatr failed (%s)\n", cli_errstr(cli1));
4187 return False;
4190 if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1))) {
4191 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1));
4192 return False;
4195 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
4196 cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4198 if (check_error(__LINE__, cli1, ERRDOS, ERRnoaccess,
4199 NT_STATUS_ACCESS_DENIED)) {
4200 printf("correct error code ERRDOS/ERRnoaccess returned\n");
4203 printf("finished open test 1\n");
4205 cli_close(cli1, fnum1);
4207 /* Now try not readonly and ensure ERRbadshare is returned. */
4209 cli_setatr(cli1, fname, 0, 0);
4211 if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1))) {
4212 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1));
4213 return False;
4216 /* This will fail - but the error should be ERRshare. */
4217 cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4219 if (check_error(__LINE__, cli1, ERRDOS, ERRbadshare,
4220 NT_STATUS_SHARING_VIOLATION)) {
4221 printf("correct error code ERRDOS/ERRbadshare returned\n");
4224 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4225 printf("close2 failed (%s)\n", cli_errstr(cli1));
4226 return False;
4229 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4231 printf("finished open test 2\n");
4233 /* Test truncate open disposition on file opened for read. */
4235 if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1))) {
4236 printf("(3) open (1) of %s failed (%s)\n", fname, cli_errstr(cli1));
4237 return False;
4240 /* write 20 bytes. */
4242 memset(buf, '\0', 20);
4244 if (cli_write(cli1, fnum1, 0, buf, 0, 20) != 20) {
4245 printf("write failed (%s)\n", cli_errstr(cli1));
4246 correct = False;
4249 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4250 printf("(3) close1 failed (%s)\n", cli_errstr(cli1));
4251 return False;
4254 /* Ensure size == 20. */
4255 if (!NT_STATUS_IS_OK(cli_getatr(cli1, fname, NULL, &fsize, NULL))) {
4256 printf("(3) getatr failed (%s)\n", cli_errstr(cli1));
4257 return False;
4260 if (fsize != 20) {
4261 printf("(3) file size != 20\n");
4262 return False;
4265 /* Now test if we can truncate a file opened for readonly. */
4267 if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1))) {
4268 printf("(3) open (2) of %s failed (%s)\n", fname, cli_errstr(cli1));
4269 return False;
4272 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4273 printf("close2 failed (%s)\n", cli_errstr(cli1));
4274 return False;
4277 /* Ensure size == 0. */
4278 if (!NT_STATUS_IS_OK(cli_getatr(cli1, fname, NULL, &fsize, NULL))) {
4279 printf("(3) getatr failed (%s)\n", cli_errstr(cli1));
4280 return False;
4283 if (fsize != 0) {
4284 printf("(3) file size != 0\n");
4285 return False;
4287 printf("finished open test 3\n");
4289 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4291 printf("Do ctemp tests\n");
4292 if (!NT_STATUS_IS_OK(cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path))) {
4293 printf("ctemp failed (%s)\n", cli_errstr(cli1));
4294 return False;
4296 printf("ctemp gave path %s\n", tmp_path);
4297 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4298 printf("close of temp failed (%s)\n", cli_errstr(cli1));
4300 if (!NT_STATUS_IS_OK(cli_unlink(cli1, tmp_path, aSYSTEM | aHIDDEN))) {
4301 printf("unlink of temp failed (%s)\n", cli_errstr(cli1));
4304 /* Test the non-io opens... */
4306 if (!torture_open_connection(&cli2, 1)) {
4307 return False;
4310 cli_setatr(cli2, fname, 0, 0);
4311 cli_unlink(cli2, fname, aSYSTEM | aHIDDEN);
4313 cli_sockopt(cli2, sockops);
4315 printf("TEST #1 testing 2 non-io opens (no delete)\n");
4317 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4318 FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4319 printf("TEST #1 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4320 return False;
4323 if (!NT_STATUS_IS_OK(cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4324 FILE_SHARE_NONE, FILE_OPEN_IF, 0, 0, &fnum2))) {
4325 printf("TEST #1 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4326 return False;
4329 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4330 printf("TEST #1 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4331 return False;
4333 if (!NT_STATUS_IS_OK(cli_close(cli2, fnum2))) {
4334 printf("TEST #1 close 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4335 return False;
4338 printf("non-io open test #1 passed.\n");
4340 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4342 printf("TEST #2 testing 2 non-io opens (first with delete)\n");
4344 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4345 FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4346 printf("TEST #2 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4347 return False;
4350 if (!NT_STATUS_IS_OK(cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4351 FILE_SHARE_NONE, FILE_OPEN_IF, 0, 0, &fnum2))) {
4352 printf("TEST #2 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4353 return False;
4356 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4357 printf("TEST #2 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4358 return False;
4360 if (!NT_STATUS_IS_OK(cli_close(cli2, fnum2))) {
4361 printf("TEST #2 close 2 of %s failed (%s)\n", fname, cli_errstr(cli1));
4362 return False;
4365 printf("non-io open test #2 passed.\n");
4367 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4369 printf("TEST #3 testing 2 non-io opens (second with delete)\n");
4371 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4372 FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4373 printf("TEST #3 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4374 return False;
4377 if (!NT_STATUS_IS_OK(cli_ntcreate(cli2, fname, 0, DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4378 FILE_SHARE_NONE, FILE_OPEN_IF, 0, 0, &fnum2))) {
4379 printf("TEST #3 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4380 return False;
4383 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4384 printf("TEST #3 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4385 return False;
4387 if (!NT_STATUS_IS_OK(cli_close(cli2, fnum2))) {
4388 printf("TEST #3 close 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4389 return False;
4392 printf("non-io open test #3 passed.\n");
4394 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4396 printf("TEST #4 testing 2 non-io opens (both with delete)\n");
4398 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4399 FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4400 printf("TEST #4 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4401 return False;
4404 if (NT_STATUS_IS_OK(cli_ntcreate(cli2, fname, 0, DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4405 FILE_SHARE_NONE, FILE_OPEN_IF, 0, 0, &fnum2))) {
4406 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, cli_errstr(cli2));
4407 return False;
4410 printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, cli_errstr(cli2), "sharing violation");
4412 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4413 printf("TEST #4 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4414 return False;
4417 printf("non-io open test #4 passed.\n");
4419 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4421 printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
4423 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4424 FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4425 printf("TEST #5 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4426 return False;
4429 if (!NT_STATUS_IS_OK(cli_ntcreate(cli2, fname, 0, DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4430 FILE_SHARE_DELETE, FILE_OPEN_IF, 0, 0, &fnum2))) {
4431 printf("TEST #5 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4432 return False;
4435 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4436 printf("TEST #5 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4437 return False;
4440 if (!NT_STATUS_IS_OK(cli_close(cli2, fnum2))) {
4441 printf("TEST #5 close 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4442 return False;
4445 printf("non-io open test #5 passed.\n");
4447 printf("TEST #6 testing 1 non-io open, one io open\n");
4449 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4451 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
4452 FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4453 printf("TEST #6 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4454 return False;
4457 if (!NT_STATUS_IS_OK(cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4458 FILE_SHARE_READ, FILE_OPEN_IF, 0, 0, &fnum2))) {
4459 printf("TEST #6 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4460 return False;
4463 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4464 printf("TEST #6 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4465 return False;
4468 if (!NT_STATUS_IS_OK(cli_close(cli2, fnum2))) {
4469 printf("TEST #6 close 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4470 return False;
4473 printf("non-io open test #6 passed.\n");
4475 printf("TEST #7 testing 1 non-io open, one io open with delete\n");
4477 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4479 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
4480 FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4481 printf("TEST #7 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4482 return False;
4485 if (NT_STATUS_IS_OK(cli_ntcreate(cli2, fname, 0, DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4486 FILE_SHARE_READ|FILE_SHARE_DELETE, FILE_OPEN_IF, 0, 0, &fnum2))) {
4487 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, cli_errstr(cli2));
4488 return False;
4491 printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, cli_errstr(cli2), "sharing violation");
4493 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4494 printf("TEST #7 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4495 return False;
4498 printf("non-io open test #7 passed.\n");
4500 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4502 if (!torture_close_connection(cli1)) {
4503 correct = False;
4505 if (!torture_close_connection(cli2)) {
4506 correct = False;
4509 return correct;
4512 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
4514 uint16 major, minor;
4515 uint32 caplow, caphigh;
4516 NTSTATUS status;
4518 if (!SERVER_HAS_UNIX_CIFS(cli)) {
4519 printf("Server doesn't support UNIX CIFS extensions.\n");
4520 return NT_STATUS_NOT_SUPPORTED;
4523 status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
4524 &caphigh);
4525 if (!NT_STATUS_IS_OK(status)) {
4526 printf("Server didn't return UNIX CIFS extensions: %s\n",
4527 nt_errstr(status));
4528 return status;
4531 status = cli_set_unix_extensions_capabilities(cli, major, minor,
4532 caplow, caphigh);
4533 if (!NT_STATUS_IS_OK(status)) {
4534 printf("Server doesn't support setting UNIX CIFS extensions: "
4535 "%s.\n", nt_errstr(status));
4536 return status;
4539 return NT_STATUS_OK;
4543 Test POSIX open /mkdir calls.
4545 static bool run_simple_posix_open_test(int dummy)
4547 static struct cli_state *cli1;
4548 const char *fname = "posix:file";
4549 const char *hname = "posix:hlink";
4550 const char *sname = "posix:symlink";
4551 const char *dname = "posix:dir";
4552 char buf[10];
4553 char namebuf[11];
4554 uint16_t fnum1 = (uint16_t)-1;
4555 SMB_STRUCT_STAT sbuf;
4556 bool correct = false;
4557 NTSTATUS status;
4559 printf("Starting simple POSIX open test\n");
4561 if (!torture_open_connection(&cli1, 0)) {
4562 return false;
4565 cli_sockopt(cli1, sockops);
4567 status = torture_setup_unix_extensions(cli1);
4568 if (!NT_STATUS_IS_OK(status)) {
4569 return false;
4572 cli_setatr(cli1, fname, 0, 0);
4573 cli_posix_unlink(cli1, fname);
4574 cli_setatr(cli1, dname, 0, 0);
4575 cli_posix_rmdir(cli1, dname);
4576 cli_setatr(cli1, hname, 0, 0);
4577 cli_posix_unlink(cli1, hname);
4578 cli_setatr(cli1, sname, 0, 0);
4579 cli_posix_unlink(cli1, sname);
4581 /* Create a directory. */
4582 if (!NT_STATUS_IS_OK(cli_posix_mkdir(cli1, dname, 0777))) {
4583 printf("POSIX mkdir of %s failed (%s)\n", dname, cli_errstr(cli1));
4584 goto out;
4587 if (!NT_STATUS_IS_OK(cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1))) {
4588 printf("POSIX create of %s failed (%s)\n", fname, cli_errstr(cli1));
4589 goto out;
4592 /* Test ftruncate - set file size. */
4593 if (!NT_STATUS_IS_OK(cli_ftruncate(cli1, fnum1, 1000))) {
4594 printf("ftruncate failed (%s)\n", cli_errstr(cli1));
4595 goto out;
4598 /* Ensure st_size == 1000 */
4599 if (!NT_STATUS_IS_OK(cli_posix_stat(cli1, fname, &sbuf))) {
4600 printf("stat failed (%s)\n", cli_errstr(cli1));
4601 goto out;
4604 if (sbuf.st_ex_size != 1000) {
4605 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
4606 goto out;
4609 /* Test ftruncate - set file size back to zero. */
4610 if (!NT_STATUS_IS_OK(cli_ftruncate(cli1, fnum1, 0))) {
4611 printf("ftruncate failed (%s)\n", cli_errstr(cli1));
4612 goto out;
4615 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4616 printf("close failed (%s)\n", cli_errstr(cli1));
4617 goto out;
4620 /* Now open the file again for read only. */
4621 if (!NT_STATUS_IS_OK(cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1))) {
4622 printf("POSIX open of %s failed (%s)\n", fname, cli_errstr(cli1));
4623 goto out;
4626 /* Now unlink while open. */
4627 if (!NT_STATUS_IS_OK(cli_posix_unlink(cli1, fname))) {
4628 printf("POSIX unlink of %s failed (%s)\n", fname, cli_errstr(cli1));
4629 goto out;
4632 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4633 printf("close(2) failed (%s)\n", cli_errstr(cli1));
4634 goto out;
4637 /* Ensure the file has gone. */
4638 if (NT_STATUS_IS_OK(cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1))) {
4639 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
4640 goto out;
4643 /* What happens when we try and POSIX open a directory ? */
4644 if (NT_STATUS_IS_OK(cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1))) {
4645 printf("POSIX open of directory %s succeeded, should have failed.\n", fname);
4646 goto out;
4647 } else {
4648 if (!check_error(__LINE__, cli1, ERRDOS, EISDIR,
4649 NT_STATUS_FILE_IS_A_DIRECTORY)) {
4650 goto out;
4654 /* Create the file. */
4655 if (!NT_STATUS_IS_OK(cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1))) {
4656 printf("POSIX create of %s failed (%s)\n", fname, cli_errstr(cli1));
4657 goto out;
4660 /* Write some data into it. */
4661 if (cli_write(cli1, fnum1, 0, "TEST DATA\n", 0, 10) != 10) {
4662 printf("cli_write failed: %s\n", cli_errstr(cli1));
4663 goto out;
4666 cli_close(cli1, fnum1);
4668 /* Now create a hardlink. */
4669 if (!NT_STATUS_IS_OK(cli_posix_hardlink(cli1, fname, hname))) {
4670 printf("POSIX hardlink of %s failed (%s)\n", hname, cli_errstr(cli1));
4671 goto out;
4674 /* Now create a symlink. */
4675 if (!NT_STATUS_IS_OK(cli_posix_symlink(cli1, fname, sname))) {
4676 printf("POSIX symlink of %s failed (%s)\n", sname, cli_errstr(cli1));
4677 goto out;
4680 /* Open the hardlink for read. */
4681 if (!NT_STATUS_IS_OK(cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1))) {
4682 printf("POSIX open of %s failed (%s)\n", hname, cli_errstr(cli1));
4683 goto out;
4686 if (cli_read(cli1, fnum1, buf, 0, 10) != 10) {
4687 printf("POSIX read of %s failed (%s)\n", hname, cli_errstr(cli1));
4688 goto out;
4691 if (memcmp(buf, "TEST DATA\n", 10)) {
4692 printf("invalid data read from hardlink\n");
4693 goto out;
4696 /* Do a POSIX lock/unlock. */
4697 if (!NT_STATUS_IS_OK(cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK))) {
4698 printf("POSIX lock failed %s\n", cli_errstr(cli1));
4699 goto out;
4702 /* Punch a hole in the locked area. */
4703 if (!NT_STATUS_IS_OK(cli_posix_unlock(cli1, fnum1, 10, 80))) {
4704 printf("POSIX unlock failed %s\n", cli_errstr(cli1));
4705 goto out;
4708 cli_close(cli1, fnum1);
4710 /* Open the symlink for read - this should fail. A POSIX
4711 client should not be doing opens on a symlink. */
4712 if (NT_STATUS_IS_OK(cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1))) {
4713 printf("POSIX open of %s succeeded (should have failed)\n", sname);
4714 goto out;
4715 } else {
4716 if (!check_error(__LINE__, cli1, ERRDOS, ERRbadpath,
4717 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
4718 printf("POSIX open of %s should have failed "
4719 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
4720 "failed with %s instead.\n",
4721 sname, cli_errstr(cli1));
4722 goto out;
4726 if (!NT_STATUS_IS_OK(cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf)))) {
4727 printf("POSIX readlink on %s failed (%s)\n", sname, cli_errstr(cli1));
4728 goto out;
4731 if (strcmp(namebuf, fname) != 0) {
4732 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
4733 sname, fname, namebuf);
4734 goto out;
4737 if (!NT_STATUS_IS_OK(cli_posix_rmdir(cli1, dname))) {
4738 printf("POSIX rmdir failed (%s)\n", cli_errstr(cli1));
4739 goto out;
4742 printf("Simple POSIX open test passed\n");
4743 correct = true;
4745 out:
4747 if (fnum1 != (uint16_t)-1) {
4748 cli_close(cli1, fnum1);
4749 fnum1 = (uint16_t)-1;
4752 cli_setatr(cli1, sname, 0, 0);
4753 cli_posix_unlink(cli1, sname);
4754 cli_setatr(cli1, hname, 0, 0);
4755 cli_posix_unlink(cli1, hname);
4756 cli_setatr(cli1, fname, 0, 0);
4757 cli_posix_unlink(cli1, fname);
4758 cli_setatr(cli1, dname, 0, 0);
4759 cli_posix_rmdir(cli1, dname);
4761 if (!torture_close_connection(cli1)) {
4762 correct = false;
4765 return correct;
4769 static uint32 open_attrs_table[] = {
4770 FILE_ATTRIBUTE_NORMAL,
4771 FILE_ATTRIBUTE_ARCHIVE,
4772 FILE_ATTRIBUTE_READONLY,
4773 FILE_ATTRIBUTE_HIDDEN,
4774 FILE_ATTRIBUTE_SYSTEM,
4776 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
4777 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
4778 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
4779 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
4780 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
4781 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
4783 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
4784 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
4785 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
4786 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
4789 struct trunc_open_results {
4790 unsigned int num;
4791 uint32 init_attr;
4792 uint32 trunc_attr;
4793 uint32 result_attr;
4796 static struct trunc_open_results attr_results[] = {
4797 { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
4798 { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
4799 { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
4800 { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
4801 { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
4802 { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
4803 { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
4804 { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
4805 { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
4806 { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
4807 { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
4808 { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
4809 { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
4810 { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
4811 { 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 },
4812 { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
4813 { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
4814 { 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 },
4815 { 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 },
4816 { 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 },
4817 { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
4818 { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
4819 { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
4820 { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
4821 { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
4822 { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
4825 static bool run_openattrtest(int dummy)
4827 static struct cli_state *cli1;
4828 const char *fname = "\\openattr.file";
4829 uint16_t fnum1;
4830 bool correct = True;
4831 uint16 attr;
4832 unsigned int i, j, k, l;
4834 printf("starting open attr test\n");
4836 if (!torture_open_connection(&cli1, 0)) {
4837 return False;
4840 cli_sockopt(cli1, sockops);
4842 for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32); i++) {
4843 cli_setatr(cli1, fname, 0, 0);
4844 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4845 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, open_attrs_table[i],
4846 FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4847 printf("open %d (1) of %s failed (%s)\n", i, fname, cli_errstr(cli1));
4848 return False;
4851 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4852 printf("close %d (1) of %s failed (%s)\n", i, fname, cli_errstr(cli1));
4853 return False;
4856 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32); j++) {
4857 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA, open_attrs_table[j],
4858 FILE_SHARE_NONE, FILE_OVERWRITE, 0, 0, &fnum1))) {
4859 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
4860 if (attr_results[l].num == k) {
4861 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
4862 k, open_attrs_table[i],
4863 open_attrs_table[j],
4864 fname, NT_STATUS_V(cli_nt_error(cli1)), cli_errstr(cli1));
4865 correct = False;
4868 if (NT_STATUS_V(cli_nt_error(cli1)) != NT_STATUS_V(NT_STATUS_ACCESS_DENIED)) {
4869 printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
4870 k, open_attrs_table[i], open_attrs_table[j],
4871 cli_errstr(cli1));
4872 correct = False;
4874 #if 0
4875 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
4876 #endif
4877 k++;
4878 continue;
4881 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4882 printf("close %d (2) of %s failed (%s)\n", j, fname, cli_errstr(cli1));
4883 return False;
4886 if (!NT_STATUS_IS_OK(cli_getatr(cli1, fname, &attr, NULL, NULL))) {
4887 printf("getatr(2) failed (%s)\n", cli_errstr(cli1));
4888 return False;
4891 #if 0
4892 printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
4893 k, open_attrs_table[i], open_attrs_table[j], attr );
4894 #endif
4896 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
4897 if (attr_results[l].num == k) {
4898 if (attr != attr_results[l].result_attr ||
4899 open_attrs_table[i] != attr_results[l].init_attr ||
4900 open_attrs_table[j] != attr_results[l].trunc_attr) {
4901 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
4902 open_attrs_table[i],
4903 open_attrs_table[j],
4904 (unsigned int)attr,
4905 attr_results[l].result_attr);
4906 correct = False;
4908 break;
4911 k++;
4915 cli_setatr(cli1, fname, 0, 0);
4916 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4918 printf("open attr test %s.\n", correct ? "passed" : "failed");
4920 if (!torture_close_connection(cli1)) {
4921 correct = False;
4923 return correct;
4926 static void list_fn(const char *mnt, struct file_info *finfo,
4927 const char *name, void *state)
4929 int *matched = (int *)state;
4930 if (matched != NULL) {
4931 *matched += 1;
4936 test directory listing speed
4938 static bool run_dirtest(int dummy)
4940 int i;
4941 static struct cli_state *cli;
4942 uint16_t fnum;
4943 struct timeval core_start;
4944 bool correct = True;
4945 int matched;
4947 printf("starting directory test\n");
4949 if (!torture_open_connection(&cli, 0)) {
4950 return False;
4953 cli_sockopt(cli, sockops);
4955 srandom(0);
4956 for (i=0;i<torture_numops;i++) {
4957 fstring fname;
4958 slprintf(fname, sizeof(fname), "\\%x", (int)random());
4959 if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
4960 fprintf(stderr,"Failed to open %s\n", fname);
4961 return False;
4963 cli_close(cli, fnum);
4966 core_start = timeval_current();
4968 matched = 0;
4969 cli_list(cli, "a*.*", 0, list_fn, &matched);
4970 printf("Matched %d\n", matched);
4972 matched = 0;
4973 cli_list(cli, "b*.*", 0, list_fn, &matched);
4974 printf("Matched %d\n", matched);
4976 matched = 0;
4977 cli_list(cli, "xyzabc", 0, list_fn, &matched);
4978 printf("Matched %d\n", matched);
4980 printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
4982 srandom(0);
4983 for (i=0;i<torture_numops;i++) {
4984 fstring fname;
4985 slprintf(fname, sizeof(fname), "\\%x", (int)random());
4986 cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
4989 if (!torture_close_connection(cli)) {
4990 correct = False;
4993 printf("finished dirtest\n");
4995 return correct;
4998 static void del_fn(const char *mnt, struct file_info *finfo, const char *mask,
4999 void *state)
5001 struct cli_state *pcli = (struct cli_state *)state;
5002 fstring fname;
5003 slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
5005 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
5006 return;
5008 if (finfo->mode & aDIR) {
5009 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
5010 printf("del_fn: failed to rmdir %s\n,", fname );
5011 } else {
5012 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, aSYSTEM | aHIDDEN)))
5013 printf("del_fn: failed to unlink %s\n,", fname );
5019 sees what IOCTLs are supported
5021 bool torture_ioctl_test(int dummy)
5023 static struct cli_state *cli;
5024 uint16_t device, function;
5025 uint16_t fnum;
5026 const char *fname = "\\ioctl.dat";
5027 DATA_BLOB blob;
5028 NTSTATUS status;
5030 if (!torture_open_connection(&cli, 0)) {
5031 return False;
5034 printf("starting ioctl test\n");
5036 cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
5038 if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum))) {
5039 printf("open of %s failed (%s)\n", fname, cli_errstr(cli));
5040 return False;
5043 status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
5044 printf("ioctl device info: %s\n", nt_errstr(status));
5046 status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
5047 printf("ioctl job info: %s\n", nt_errstr(status));
5049 for (device=0;device<0x100;device++) {
5050 printf("ioctl test with device = 0x%x\n", device);
5051 for (function=0;function<0x100;function++) {
5052 uint32 code = (device<<16) | function;
5054 status = cli_raw_ioctl(cli, fnum, code, &blob);
5056 if (NT_STATUS_IS_OK(status)) {
5057 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
5058 (int)blob.length);
5059 data_blob_free(&blob);
5064 if (!torture_close_connection(cli)) {
5065 return False;
5068 return True;
5073 tries varients of chkpath
5075 bool torture_chkpath_test(int dummy)
5077 static struct cli_state *cli;
5078 uint16_t fnum;
5079 bool ret;
5081 if (!torture_open_connection(&cli, 0)) {
5082 return False;
5085 printf("starting chkpath test\n");
5087 /* cleanup from an old run */
5088 cli_rmdir(cli, "\\chkpath.dir\\dir2");
5089 cli_unlink(cli, "\\chkpath.dir\\*", aSYSTEM | aHIDDEN);
5090 cli_rmdir(cli, "\\chkpath.dir");
5092 if (!NT_STATUS_IS_OK(cli_mkdir(cli, "\\chkpath.dir"))) {
5093 printf("mkdir1 failed : %s\n", cli_errstr(cli));
5094 return False;
5097 if (!NT_STATUS_IS_OK(cli_mkdir(cli, "\\chkpath.dir\\dir2"))) {
5098 printf("mkdir2 failed : %s\n", cli_errstr(cli));
5099 return False;
5102 if (!NT_STATUS_IS_OK(cli_open(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum))) {
5103 printf("open1 failed (%s)\n", cli_errstr(cli));
5104 return False;
5106 cli_close(cli, fnum);
5108 if (!NT_STATUS_IS_OK(cli_chkpath(cli, "\\chkpath.dir"))) {
5109 printf("chkpath1 failed: %s\n", cli_errstr(cli));
5110 ret = False;
5113 if (!NT_STATUS_IS_OK(cli_chkpath(cli, "\\chkpath.dir\\dir2"))) {
5114 printf("chkpath2 failed: %s\n", cli_errstr(cli));
5115 ret = False;
5118 if (!NT_STATUS_IS_OK(cli_chkpath(cli, "\\chkpath.dir\\foo.txt"))) {
5119 ret = check_error(__LINE__, cli, ERRDOS, ERRbadpath,
5120 NT_STATUS_NOT_A_DIRECTORY);
5121 } else {
5122 printf("* chkpath on a file should fail\n");
5123 ret = False;
5126 if (!NT_STATUS_IS_OK(cli_chkpath(cli, "\\chkpath.dir\\bar.txt"))) {
5127 ret = check_error(__LINE__, cli, ERRDOS, ERRbadfile,
5128 NT_STATUS_OBJECT_NAME_NOT_FOUND);
5129 } else {
5130 printf("* chkpath on a non existant file should fail\n");
5131 ret = False;
5134 if (!NT_STATUS_IS_OK(cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt"))) {
5135 ret = check_error(__LINE__, cli, ERRDOS, ERRbadpath,
5136 NT_STATUS_OBJECT_PATH_NOT_FOUND);
5137 } else {
5138 printf("* chkpath on a non existent component should fail\n");
5139 ret = False;
5142 cli_rmdir(cli, "\\chkpath.dir\\dir2");
5143 cli_unlink(cli, "\\chkpath.dir\\*", aSYSTEM | aHIDDEN);
5144 cli_rmdir(cli, "\\chkpath.dir");
5146 if (!torture_close_connection(cli)) {
5147 return False;
5150 return ret;
5153 static bool run_eatest(int dummy)
5155 static struct cli_state *cli;
5156 const char *fname = "\\eatest.txt";
5157 bool correct = True;
5158 uint16_t fnum;
5159 int i;
5160 size_t num_eas;
5161 struct ea_struct *ea_list = NULL;
5162 TALLOC_CTX *mem_ctx = talloc_init("eatest");
5163 NTSTATUS status;
5165 printf("starting eatest\n");
5167 if (!torture_open_connection(&cli, 0)) {
5168 talloc_destroy(mem_ctx);
5169 return False;
5172 cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
5173 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0,
5174 FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
5175 FILE_SHARE_NONE, FILE_OVERWRITE_IF,
5176 0x4044, 0, &fnum))) {
5177 printf("open failed - %s\n", cli_errstr(cli));
5178 talloc_destroy(mem_ctx);
5179 return False;
5182 for (i = 0; i < 10; i++) {
5183 fstring ea_name, ea_val;
5185 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
5186 memset(ea_val, (char)i+1, i+1);
5187 if (!cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1)) {
5188 printf("ea_set of name %s failed - %s\n", ea_name, cli_errstr(cli));
5189 talloc_destroy(mem_ctx);
5190 return False;
5194 cli_close(cli, fnum);
5195 for (i = 0; i < 10; i++) {
5196 fstring ea_name, ea_val;
5198 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
5199 memset(ea_val, (char)i+1, i+1);
5200 if (!cli_set_ea_path(cli, fname, ea_name, ea_val, i+1)) {
5201 printf("ea_set of name %s failed - %s\n", ea_name, cli_errstr(cli));
5202 talloc_destroy(mem_ctx);
5203 return False;
5207 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
5208 if (!NT_STATUS_IS_OK(status)) {
5209 printf("ea_get list failed - %s\n", nt_errstr(status));
5210 correct = False;
5213 printf("num_eas = %d\n", (int)num_eas);
5215 if (num_eas != 20) {
5216 printf("Should be 20 EA's stored... failing.\n");
5217 correct = False;
5220 for (i = 0; i < num_eas; i++) {
5221 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
5222 dump_data(0, ea_list[i].value.data,
5223 ea_list[i].value.length);
5226 /* Setting EA's to zero length deletes them. Test this */
5227 printf("Now deleting all EA's - case indepenent....\n");
5229 #if 1
5230 cli_set_ea_path(cli, fname, "", "", 0);
5231 #else
5232 for (i = 0; i < 20; i++) {
5233 fstring ea_name;
5234 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
5235 if (!cli_set_ea_path(cli, fname, ea_name, "", 0)) {
5236 printf("ea_set of name %s failed - %s\n", ea_name, cli_errstr(cli));
5237 talloc_destroy(mem_ctx);
5238 return False;
5241 #endif
5243 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
5244 if (!NT_STATUS_IS_OK(status)) {
5245 printf("ea_get list failed - %s\n", nt_errstr(status));
5246 correct = False;
5249 printf("num_eas = %d\n", (int)num_eas);
5250 for (i = 0; i < num_eas; i++) {
5251 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
5252 dump_data(0, ea_list[i].value.data,
5253 ea_list[i].value.length);
5256 if (num_eas != 0) {
5257 printf("deleting EA's failed.\n");
5258 correct = False;
5261 /* Try and delete a non existant EA. */
5262 if (!cli_set_ea_path(cli, fname, "foo", "", 0)) {
5263 printf("deleting non-existant EA 'foo' should succeed. %s\n", cli_errstr(cli));
5264 correct = False;
5267 talloc_destroy(mem_ctx);
5268 if (!torture_close_connection(cli)) {
5269 correct = False;
5272 return correct;
5275 static bool run_dirtest1(int dummy)
5277 int i;
5278 static struct cli_state *cli;
5279 uint16_t fnum;
5280 int num_seen;
5281 bool correct = True;
5283 printf("starting directory test\n");
5285 if (!torture_open_connection(&cli, 0)) {
5286 return False;
5289 cli_sockopt(cli, sockops);
5291 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
5292 cli_list(cli, "\\LISTDIR\\*", aDIR, del_fn, cli);
5293 cli_rmdir(cli, "\\LISTDIR");
5294 cli_mkdir(cli, "\\LISTDIR");
5296 /* Create 1000 files and 1000 directories. */
5297 for (i=0;i<1000;i++) {
5298 fstring fname;
5299 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
5300 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
5301 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum))) {
5302 fprintf(stderr,"Failed to open %s\n", fname);
5303 return False;
5305 cli_close(cli, fnum);
5307 for (i=0;i<1000;i++) {
5308 fstring fname;
5309 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
5310 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
5311 fprintf(stderr,"Failed to open %s\n", fname);
5312 return False;
5316 /* Now ensure that doing an old list sees both files and directories. */
5317 num_seen = 0;
5318 cli_list_old(cli, "\\LISTDIR\\*", aDIR, list_fn, &num_seen);
5319 printf("num_seen = %d\n", num_seen );
5320 /* We should see 100 files + 1000 directories + . and .. */
5321 if (num_seen != 2002)
5322 correct = False;
5324 /* Ensure if we have the "must have" bits we only see the
5325 * relevent entries.
5327 num_seen = 0;
5328 cli_list_old(cli, "\\LISTDIR\\*", (aDIR<<8)|aDIR, list_fn, &num_seen);
5329 printf("num_seen = %d\n", num_seen );
5330 if (num_seen != 1002)
5331 correct = False;
5333 num_seen = 0;
5334 cli_list_old(cli, "\\LISTDIR\\*", (aARCH<<8)|aDIR, list_fn, &num_seen);
5335 printf("num_seen = %d\n", num_seen );
5336 if (num_seen != 1000)
5337 correct = False;
5339 /* Delete everything. */
5340 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
5341 cli_list(cli, "\\LISTDIR\\*", aDIR, del_fn, cli);
5342 cli_rmdir(cli, "\\LISTDIR");
5344 #if 0
5345 printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
5346 printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
5347 printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
5348 #endif
5350 if (!torture_close_connection(cli)) {
5351 correct = False;
5354 printf("finished dirtest1\n");
5356 return correct;
5359 static bool run_error_map_extract(int dummy) {
5361 static struct cli_state *c_dos;
5362 static struct cli_state *c_nt;
5363 NTSTATUS status;
5365 uint32 error;
5367 uint32 flgs2, errnum;
5368 uint8 errclass;
5370 NTSTATUS nt_status;
5372 fstring user;
5374 /* NT-Error connection */
5376 if (!(c_nt = open_nbt_connection())) {
5377 return False;
5380 c_nt->use_spnego = False;
5382 status = cli_negprot(c_nt);
5384 if (!NT_STATUS_IS_OK(status)) {
5385 printf("%s rejected the NT-error negprot (%s)\n", host,
5386 nt_errstr(status));
5387 cli_shutdown(c_nt);
5388 return False;
5391 if (!NT_STATUS_IS_OK(cli_session_setup(c_nt, "", "", 0, "", 0,
5392 workgroup))) {
5393 printf("%s rejected the NT-error initial session setup (%s)\n",host, cli_errstr(c_nt));
5394 return False;
5397 /* DOS-Error connection */
5399 if (!(c_dos = open_nbt_connection())) {
5400 return False;
5403 c_dos->use_spnego = False;
5404 c_dos->force_dos_errors = True;
5406 status = cli_negprot(c_dos);
5407 if (!NT_STATUS_IS_OK(status)) {
5408 printf("%s rejected the DOS-error negprot (%s)\n", host,
5409 nt_errstr(status));
5410 cli_shutdown(c_dos);
5411 return False;
5414 if (!NT_STATUS_IS_OK(cli_session_setup(c_dos, "", "", 0, "", 0,
5415 workgroup))) {
5416 printf("%s rejected the DOS-error initial session setup (%s)\n",host, cli_errstr(c_dos));
5417 return False;
5420 for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
5421 fstr_sprintf(user, "%X", error);
5423 if (NT_STATUS_IS_OK(cli_session_setup(c_nt, user,
5424 password, strlen(password),
5425 password, strlen(password),
5426 workgroup))) {
5427 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
5430 flgs2 = SVAL(c_nt->inbuf,smb_flg2);
5432 /* Case #1: 32-bit NT errors */
5433 if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) {
5434 nt_status = NT_STATUS(IVAL(c_nt->inbuf,smb_rcls));
5435 } else {
5436 printf("/** Dos error on NT connection! (%s) */\n",
5437 cli_errstr(c_nt));
5438 nt_status = NT_STATUS(0xc0000000);
5441 if (NT_STATUS_IS_OK(cli_session_setup(c_dos, user,
5442 password, strlen(password),
5443 password, strlen(password),
5444 workgroup))) {
5445 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
5447 flgs2 = SVAL(c_dos->inbuf,smb_flg2), errnum;
5449 /* Case #1: 32-bit NT errors */
5450 if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) {
5451 printf("/** NT error on DOS connection! (%s) */\n",
5452 cli_errstr(c_nt));
5453 errnum = errclass = 0;
5454 } else {
5455 cli_dos_error(c_dos, &errclass, &errnum);
5458 if (NT_STATUS_V(nt_status) != error) {
5459 printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
5460 get_nt_error_c_code(NT_STATUS(error)),
5461 get_nt_error_c_code(nt_status));
5464 printf("\t{%s,\t%s,\t%s},\n",
5465 smb_dos_err_class(errclass),
5466 smb_dos_err_name(errclass, errnum),
5467 get_nt_error_c_code(NT_STATUS(error)));
5469 return True;
5472 static bool run_sesssetup_bench(int dummy)
5474 static struct cli_state *c;
5475 const char *fname = "\\file.dat";
5476 uint16_t fnum;
5477 NTSTATUS status;
5478 int i;
5480 if (!torture_open_connection(&c, 0)) {
5481 return false;
5484 if (!NT_STATUS_IS_OK(cli_ntcreate(
5485 c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5486 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5487 FILE_DELETE_ON_CLOSE, 0, &fnum))) {
5488 d_printf("open %s failed: %s\n", fname, cli_errstr(c));
5489 return false;
5492 for (i=0; i<torture_numops; i++) {
5493 status = cli_session_setup(
5494 c, username,
5495 password, strlen(password),
5496 password, strlen(password),
5497 workgroup);
5498 if (!NT_STATUS_IS_OK(status)) {
5499 d_printf("(%s) cli_session_setup failed: %s\n",
5500 __location__, nt_errstr(status));
5501 return false;
5504 d_printf("\r%d ", (int)c->vuid);
5506 status = cli_ulogoff(c);
5507 if (!NT_STATUS_IS_OK(status)) {
5508 d_printf("(%s) cli_ulogoff failed: %s\n",
5509 __location__, nt_errstr(status));
5510 return false;
5512 c->vuid = 0;
5515 return true;
5518 static bool subst_test(const char *str, const char *user, const char *domain,
5519 uid_t uid, gid_t gid, const char *expected)
5521 char *subst;
5522 bool result = true;
5524 subst = talloc_sub_specified(talloc_tos(), str, user, domain, uid, gid);
5526 if (strcmp(subst, expected) != 0) {
5527 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
5528 "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
5529 expected);
5530 result = false;
5533 TALLOC_FREE(subst);
5534 return result;
5537 static void chain1_open_completion(struct tevent_req *req)
5539 uint16_t fnum;
5540 NTSTATUS status;
5541 status = cli_open_recv(req, &fnum);
5542 TALLOC_FREE(req);
5544 d_printf("cli_open_recv returned %s: %d\n",
5545 nt_errstr(status),
5546 NT_STATUS_IS_OK(status) ? fnum : -1);
5549 static void chain1_write_completion(struct tevent_req *req)
5551 size_t written;
5552 NTSTATUS status;
5553 status = cli_write_andx_recv(req, &written);
5554 TALLOC_FREE(req);
5556 d_printf("cli_write_andx_recv returned %s: %d\n",
5557 nt_errstr(status),
5558 NT_STATUS_IS_OK(status) ? (int)written : -1);
5561 static void chain1_close_completion(struct tevent_req *req)
5563 NTSTATUS status;
5564 bool *done = (bool *)tevent_req_callback_data_void(req);
5566 status = cli_close_recv(req);
5567 *done = true;
5569 TALLOC_FREE(req);
5571 d_printf("cli_close returned %s\n", nt_errstr(status));
5574 static bool run_chain1(int dummy)
5576 struct cli_state *cli1;
5577 struct event_context *evt = event_context_init(NULL);
5578 struct tevent_req *reqs[3], *smbreqs[3];
5579 bool done = false;
5580 const char *str = "foobar";
5581 NTSTATUS status;
5583 printf("starting chain1 test\n");
5584 if (!torture_open_connection(&cli1, 0)) {
5585 return False;
5588 cli_sockopt(cli1, sockops);
5590 reqs[0] = cli_open_create(talloc_tos(), evt, cli1, "\\test",
5591 O_CREAT|O_RDWR, 0, &smbreqs[0]);
5592 if (reqs[0] == NULL) return false;
5593 tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
5596 reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
5597 (uint8_t *)str, 0, strlen(str)+1,
5598 smbreqs, 1, &smbreqs[1]);
5599 if (reqs[1] == NULL) return false;
5600 tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
5602 reqs[2] = cli_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
5603 if (reqs[2] == NULL) return false;
5604 tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
5606 status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
5607 if (!NT_STATUS_IS_OK(status)) {
5608 return false;
5611 while (!done) {
5612 event_loop_once(evt);
5615 torture_close_connection(cli1);
5616 return True;
5619 static void chain2_sesssetup_completion(struct tevent_req *req)
5621 NTSTATUS status;
5622 status = cli_session_setup_guest_recv(req);
5623 d_printf("sesssetup returned %s\n", nt_errstr(status));
5626 static void chain2_tcon_completion(struct tevent_req *req)
5628 bool *done = (bool *)tevent_req_callback_data_void(req);
5629 NTSTATUS status;
5630 status = cli_tcon_andx_recv(req);
5631 d_printf("tcon_and_x returned %s\n", nt_errstr(status));
5632 *done = true;
5635 static bool run_chain2(int dummy)
5637 struct cli_state *cli1;
5638 struct event_context *evt = event_context_init(NULL);
5639 struct tevent_req *reqs[2], *smbreqs[2];
5640 bool done = false;
5641 NTSTATUS status;
5643 printf("starting chain2 test\n");
5644 status = cli_start_connection(&cli1, global_myname(), host, NULL,
5645 port_to_use, Undefined, 0, NULL);
5646 if (!NT_STATUS_IS_OK(status)) {
5647 return False;
5650 cli_sockopt(cli1, sockops);
5652 reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
5653 &smbreqs[0]);
5654 if (reqs[0] == NULL) return false;
5655 tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
5657 reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
5658 "?????", NULL, 0, &smbreqs[1]);
5659 if (reqs[1] == NULL) return false;
5660 tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
5662 status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
5663 if (!NT_STATUS_IS_OK(status)) {
5664 return false;
5667 while (!done) {
5668 event_loop_once(evt);
5671 torture_close_connection(cli1);
5672 return True;
5676 struct torture_createdel_state {
5677 struct tevent_context *ev;
5678 struct cli_state *cli;
5681 static void torture_createdel_created(struct tevent_req *subreq);
5682 static void torture_createdel_closed(struct tevent_req *subreq);
5684 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
5685 struct tevent_context *ev,
5686 struct cli_state *cli,
5687 const char *name)
5689 struct tevent_req *req, *subreq;
5690 struct torture_createdel_state *state;
5692 req = tevent_req_create(mem_ctx, &state,
5693 struct torture_createdel_state);
5694 if (req == NULL) {
5695 return NULL;
5697 state->ev = ev;
5698 state->cli = cli;
5700 subreq = cli_ntcreate_send(
5701 state, ev, cli, name, 0,
5702 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5703 FILE_ATTRIBUTE_NORMAL,
5704 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5705 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
5707 if (tevent_req_nomem(subreq, req)) {
5708 return tevent_req_post(req, ev);
5710 tevent_req_set_callback(subreq, torture_createdel_created, req);
5711 return req;
5714 static void torture_createdel_created(struct tevent_req *subreq)
5716 struct tevent_req *req = tevent_req_callback_data(
5717 subreq, struct tevent_req);
5718 struct torture_createdel_state *state = tevent_req_data(
5719 req, struct torture_createdel_state);
5720 NTSTATUS status;
5721 uint16_t fnum;
5723 status = cli_ntcreate_recv(subreq, &fnum);
5724 TALLOC_FREE(subreq);
5725 if (!NT_STATUS_IS_OK(status)) {
5726 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
5727 nt_errstr(status)));
5728 tevent_req_nterror(req, status);
5729 return;
5732 subreq = cli_close_send(state, state->ev, state->cli, fnum);
5733 if (tevent_req_nomem(subreq, req)) {
5734 return;
5736 tevent_req_set_callback(subreq, torture_createdel_closed, req);
5739 static void torture_createdel_closed(struct tevent_req *subreq)
5741 struct tevent_req *req = tevent_req_callback_data(
5742 subreq, struct tevent_req);
5743 NTSTATUS status;
5745 status = cli_close_recv(subreq);
5746 if (!NT_STATUS_IS_OK(status)) {
5747 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
5748 tevent_req_nterror(req, status);
5749 return;
5751 tevent_req_done(req);
5754 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
5756 return tevent_req_simple_recv_ntstatus(req);
5759 struct torture_createdels_state {
5760 struct tevent_context *ev;
5761 struct cli_state *cli;
5762 const char *base_name;
5763 int sent;
5764 int received;
5765 int num_files;
5766 struct tevent_req **reqs;
5769 static void torture_createdels_done(struct tevent_req *subreq);
5771 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
5772 struct tevent_context *ev,
5773 struct cli_state *cli,
5774 const char *base_name,
5775 int num_parallel,
5776 int num_files)
5778 struct tevent_req *req;
5779 struct torture_createdels_state *state;
5780 int i;
5782 req = tevent_req_create(mem_ctx, &state,
5783 struct torture_createdels_state);
5784 if (req == NULL) {
5785 return NULL;
5787 state->ev = ev;
5788 state->cli = cli;
5789 state->base_name = talloc_strdup(state, base_name);
5790 if (tevent_req_nomem(state->base_name, req)) {
5791 return tevent_req_post(req, ev);
5793 state->num_files = MAX(num_parallel, num_files);
5794 state->sent = 0;
5795 state->received = 0;
5797 state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
5798 if (tevent_req_nomem(state->reqs, req)) {
5799 return tevent_req_post(req, ev);
5802 for (i=0; i<num_parallel; i++) {
5803 char *name;
5805 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
5806 state->sent);
5807 if (tevent_req_nomem(name, req)) {
5808 return tevent_req_post(req, ev);
5810 state->reqs[i] = torture_createdel_send(
5811 state->reqs, state->ev, state->cli, name);
5812 if (tevent_req_nomem(state->reqs[i], req)) {
5813 return tevent_req_post(req, ev);
5815 name = talloc_move(state->reqs[i], &name);
5816 tevent_req_set_callback(state->reqs[i],
5817 torture_createdels_done, req);
5818 state->sent += 1;
5820 return req;
5823 static void torture_createdels_done(struct tevent_req *subreq)
5825 struct tevent_req *req = tevent_req_callback_data(
5826 subreq, struct tevent_req);
5827 struct torture_createdels_state *state = tevent_req_data(
5828 req, struct torture_createdels_state);
5829 size_t num_parallel = talloc_array_length(state->reqs);
5830 NTSTATUS status;
5831 char *name;
5832 int i;
5834 status = torture_createdel_recv(subreq);
5835 if (!NT_STATUS_IS_OK(status)){
5836 DEBUG(10, ("torture_createdel_recv returned %s\n",
5837 nt_errstr(status)));
5838 TALLOC_FREE(subreq);
5839 tevent_req_nterror(req, status);
5840 return;
5843 for (i=0; i<num_parallel; i++) {
5844 if (subreq == state->reqs[i]) {
5845 break;
5848 if (i == num_parallel) {
5849 DEBUG(10, ("received something we did not send\n"));
5850 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
5851 return;
5853 TALLOC_FREE(state->reqs[i]);
5855 if (state->sent >= state->num_files) {
5856 tevent_req_done(req);
5857 return;
5860 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
5861 state->sent);
5862 if (tevent_req_nomem(name, req)) {
5863 return;
5865 state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
5866 state->cli, name);
5867 if (tevent_req_nomem(state->reqs[i], req)) {
5868 return;
5870 name = talloc_move(state->reqs[i], &name);
5871 tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
5872 state->sent += 1;
5875 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
5877 return tevent_req_simple_recv_ntstatus(req);
5880 struct swallow_notify_state {
5881 struct tevent_context *ev;
5882 struct cli_state *cli;
5883 uint16_t fnum;
5884 uint32_t completion_filter;
5885 bool recursive;
5886 bool (*fn)(uint32_t action, const char *name, void *priv);
5887 void *priv;
5890 static void swallow_notify_done(struct tevent_req *subreq);
5892 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
5893 struct tevent_context *ev,
5894 struct cli_state *cli,
5895 uint16_t fnum,
5896 uint32_t completion_filter,
5897 bool recursive,
5898 bool (*fn)(uint32_t action,
5899 const char *name,
5900 void *priv),
5901 void *priv)
5903 struct tevent_req *req, *subreq;
5904 struct swallow_notify_state *state;
5906 req = tevent_req_create(mem_ctx, &state,
5907 struct swallow_notify_state);
5908 if (req == NULL) {
5909 return NULL;
5911 state->ev = ev;
5912 state->cli = cli;
5913 state->fnum = fnum;
5914 state->completion_filter = completion_filter;
5915 state->recursive = recursive;
5916 state->fn = fn;
5917 state->priv = priv;
5919 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
5920 0xffff, state->completion_filter,
5921 state->recursive);
5922 if (tevent_req_nomem(subreq, req)) {
5923 return tevent_req_post(req, ev);
5925 tevent_req_set_callback(subreq, swallow_notify_done, req);
5926 return req;
5929 static void swallow_notify_done(struct tevent_req *subreq)
5931 struct tevent_req *req = tevent_req_callback_data(
5932 subreq, struct tevent_req);
5933 struct swallow_notify_state *state = tevent_req_data(
5934 req, struct swallow_notify_state);
5935 NTSTATUS status;
5936 uint32_t i, num_changes;
5937 struct notify_change *changes;
5939 status = cli_notify_recv(subreq, state, &num_changes, &changes);
5940 TALLOC_FREE(subreq);
5941 if (!NT_STATUS_IS_OK(status)) {
5942 DEBUG(10, ("cli_notify_recv returned %s\n",
5943 nt_errstr(status)));
5944 tevent_req_nterror(req, status);
5945 return;
5948 for (i=0; i<num_changes; i++) {
5949 state->fn(changes[i].action, changes[i].name, state->priv);
5951 TALLOC_FREE(changes);
5953 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
5954 0xffff, state->completion_filter,
5955 state->recursive);
5956 if (tevent_req_nomem(subreq, req)) {
5957 return;
5959 tevent_req_set_callback(subreq, swallow_notify_done, req);
5962 static bool print_notifies(uint32_t action, const char *name, void *priv)
5964 if (DEBUGLEVEL > 5) {
5965 d_printf("%d %s\n", (int)action, name);
5967 return true;
5970 static void notify_bench_done(struct tevent_req *req)
5972 int *num_finished = (int *)tevent_req_callback_data_void(req);
5973 *num_finished += 1;
5976 static bool run_notify_bench(int dummy)
5978 const char *dname = "\\notify-bench";
5979 struct tevent_context *ev;
5980 NTSTATUS status;
5981 uint16_t dnum;
5982 struct tevent_req *req1;
5983 struct tevent_req *req2 = NULL;
5984 int i, num_unc_names;
5985 int num_finished = 0;
5987 printf("starting notify-bench test\n");
5989 if (use_multishare_conn) {
5990 char **unc_list;
5991 unc_list = file_lines_load(multishare_conn_fname,
5992 &num_unc_names, 0, NULL);
5993 if (!unc_list || num_unc_names <= 0) {
5994 d_printf("Failed to load unc names list from '%s'\n",
5995 multishare_conn_fname);
5996 return false;
5998 TALLOC_FREE(unc_list);
5999 } else {
6000 num_unc_names = 1;
6003 ev = tevent_context_init(talloc_tos());
6004 if (ev == NULL) {
6005 d_printf("tevent_context_init failed\n");
6006 return false;
6009 for (i=0; i<num_unc_names; i++) {
6010 struct cli_state *cli;
6011 char *base_fname;
6013 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
6014 dname, i);
6015 if (base_fname == NULL) {
6016 return false;
6019 if (!torture_open_connection(&cli, i)) {
6020 return false;
6023 status = cli_ntcreate(cli, dname, 0,
6024 MAXIMUM_ALLOWED_ACCESS,
6025 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
6026 FILE_SHARE_DELETE,
6027 FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
6028 &dnum);
6030 if (!NT_STATUS_IS_OK(status)) {
6031 d_printf("Could not create %s: %s\n", dname,
6032 nt_errstr(status));
6033 return false;
6036 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
6037 FILE_NOTIFY_CHANGE_FILE_NAME |
6038 FILE_NOTIFY_CHANGE_DIR_NAME |
6039 FILE_NOTIFY_CHANGE_ATTRIBUTES |
6040 FILE_NOTIFY_CHANGE_LAST_WRITE,
6041 false, print_notifies, NULL);
6042 if (req1 == NULL) {
6043 d_printf("Could not create notify request\n");
6044 return false;
6047 req2 = torture_createdels_send(talloc_tos(), ev, cli,
6048 base_fname, 10, torture_numops);
6049 if (req2 == NULL) {
6050 d_printf("Could not create createdels request\n");
6051 return false;
6053 TALLOC_FREE(base_fname);
6055 tevent_req_set_callback(req2, notify_bench_done,
6056 &num_finished);
6059 while (num_finished < num_unc_names) {
6060 int ret;
6061 ret = tevent_loop_once(ev);
6062 if (ret != 0) {
6063 d_printf("tevent_loop_once failed\n");
6064 return false;
6068 if (!tevent_req_poll(req2, ev)) {
6069 d_printf("tevent_req_poll failed\n");
6072 status = torture_createdels_recv(req2);
6073 d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
6075 return true;
6078 static bool run_mangle1(int dummy)
6080 struct cli_state *cli;
6081 const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
6082 uint16_t fnum;
6083 fstring alt_name;
6084 NTSTATUS status;
6085 time_t change_time, access_time, write_time;
6086 SMB_OFF_T size;
6087 uint16_t mode;
6089 printf("starting mangle1 test\n");
6090 if (!torture_open_connection(&cli, 0)) {
6091 return False;
6094 cli_sockopt(cli, sockops);
6096 if (!NT_STATUS_IS_OK(cli_ntcreate(
6097 cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6098 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF, 0, 0, &fnum))) {
6099 d_printf("open %s failed: %s\n", fname, cli_errstr(cli));
6100 return false;
6102 cli_close(cli, fnum);
6104 status = cli_qpathinfo_alt_name(cli, fname, alt_name);
6105 if (!NT_STATUS_IS_OK(status)) {
6106 d_printf("cli_qpathinfo_alt_name failed: %s\n",
6107 nt_errstr(status));
6108 return false;
6110 d_printf("alt_name: %s\n", alt_name);
6112 if (!NT_STATUS_IS_OK(cli_open(cli, alt_name, O_RDONLY, DENY_NONE, &fnum))) {
6113 d_printf("cli_open(%s) failed: %s\n", alt_name,
6114 cli_errstr(cli));
6115 return false;
6117 cli_close(cli, fnum);
6119 status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
6120 &write_time, &size, &mode);
6121 if (!NT_STATUS_IS_OK(status)) {
6122 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
6123 nt_errstr(status));
6124 return false;
6127 return true;
6130 static size_t null_source(uint8_t *buf, size_t n, void *priv)
6132 size_t *to_pull = (size_t *)priv;
6133 size_t thistime = *to_pull;
6135 thistime = MIN(thistime, n);
6136 if (thistime == 0) {
6137 return 0;
6140 memset(buf, 0, thistime);
6141 *to_pull -= thistime;
6142 return thistime;
6145 static bool run_windows_write(int dummy)
6147 struct cli_state *cli1;
6148 uint16_t fnum;
6149 int i;
6150 bool ret = false;
6151 const char *fname = "\\writetest.txt";
6152 struct timeval start_time;
6153 double seconds;
6154 double kbytes;
6156 printf("starting windows_write test\n");
6157 if (!torture_open_connection(&cli1, 0)) {
6158 return False;
6161 if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum))) {
6162 printf("open failed (%s)\n", cli_errstr(cli1));
6163 return False;
6166 cli_sockopt(cli1, sockops);
6168 start_time = timeval_current();
6170 for (i=0; i<torture_numops; i++) {
6171 char c = 0;
6172 off_t start = i * torture_blocksize;
6173 NTSTATUS status;
6174 size_t to_pull = torture_blocksize - 1;
6176 if (cli_write(cli1, fnum, 0, &c,
6177 start + torture_blocksize - 1, 1) != 1) {
6178 printf("cli_write failed: %s\n", cli_errstr(cli1));
6179 goto fail;
6182 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
6183 null_source, &to_pull);
6184 if (!NT_STATUS_IS_OK(status)) {
6185 printf("cli_push returned: %s\n", nt_errstr(status));
6186 goto fail;
6190 seconds = timeval_elapsed(&start_time);
6191 kbytes = (double)torture_blocksize * torture_numops;
6192 kbytes /= 1024;
6194 printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
6195 (double)seconds, (int)(kbytes/seconds));
6197 ret = true;
6198 fail:
6199 cli_close(cli1, fnum);
6200 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
6201 torture_close_connection(cli1);
6202 return ret;
6205 static bool run_cli_echo(int dummy)
6207 struct cli_state *cli;
6208 NTSTATUS status;
6210 printf("starting cli_echo test\n");
6211 if (!torture_open_connection(&cli, 0)) {
6212 return false;
6214 cli_sockopt(cli, sockops);
6216 status = cli_echo(cli, 5, data_blob_const("hello", 5));
6218 d_printf("cli_echo returned %s\n", nt_errstr(status));
6220 torture_close_connection(cli);
6221 return NT_STATUS_IS_OK(status);
6224 static bool run_uid_regression_test(int dummy)
6226 static struct cli_state *cli;
6227 int16_t old_vuid;
6228 int16_t old_cnum;
6229 bool correct = True;
6230 NTSTATUS status;
6232 printf("starting uid regression test\n");
6234 if (!torture_open_connection(&cli, 0)) {
6235 return False;
6238 cli_sockopt(cli, sockops);
6240 /* Ok - now save then logoff our current user. */
6241 old_vuid = cli->vuid;
6243 status = cli_ulogoff(cli);
6244 if (!NT_STATUS_IS_OK(status)) {
6245 d_printf("(%s) cli_ulogoff failed: %s\n",
6246 __location__, nt_errstr(status));
6247 correct = false;
6248 goto out;
6251 cli->vuid = old_vuid;
6253 /* Try an operation. */
6254 status = cli_mkdir(cli, "\\uid_reg_test");
6255 if (NT_STATUS_IS_OK(status)) {
6256 d_printf("(%s) cli_mkdir succeeded\n",
6257 __location__);
6258 correct = false;
6259 goto out;
6260 } else {
6261 /* Should be bad uid. */
6262 if (!check_error(__LINE__, cli, ERRSRV, ERRbaduid,
6263 NT_STATUS_USER_SESSION_DELETED)) {
6264 correct = false;
6265 goto out;
6269 old_cnum = cli->cnum;
6271 /* Now try a SMBtdis with the invald vuid set to zero. */
6272 cli->vuid = 0;
6274 /* This should succeed. */
6275 status = cli_tdis(cli);
6277 if (NT_STATUS_IS_OK(status)) {
6278 d_printf("First tdis with invalid vuid should succeed.\n");
6279 } else {
6280 d_printf("First tdis failed (%s)\n", nt_errstr(status));
6281 correct = false;
6282 goto out;
6285 cli->vuid = old_vuid;
6286 cli->cnum = old_cnum;
6288 /* This should fail. */
6289 status = cli_tdis(cli);
6290 if (NT_STATUS_IS_OK(status)) {
6291 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
6292 correct = false;
6293 goto out;
6294 } else {
6295 /* Should be bad tid. */
6296 if (!check_error(__LINE__, cli, ERRSRV, ERRinvnid,
6297 NT_STATUS_NETWORK_NAME_DELETED)) {
6298 correct = false;
6299 goto out;
6303 cli_rmdir(cli, "\\uid_reg_test");
6305 out:
6307 cli_shutdown(cli);
6308 return correct;
6312 static const char *illegal_chars = "*\\/?<>|\":";
6313 static char force_shortname_chars[] = " +,.[];=\177";
6315 static void shortname_del_fn(const char *mnt, struct file_info *finfo,
6316 const char *mask, void *state)
6318 struct cli_state *pcli = (struct cli_state *)state;
6319 fstring fname;
6320 slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
6322 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
6323 return;
6325 if (finfo->mode & aDIR) {
6326 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
6327 printf("del_fn: failed to rmdir %s\n,", fname );
6328 } else {
6329 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, aSYSTEM | aHIDDEN)))
6330 printf("del_fn: failed to unlink %s\n,", fname );
6334 struct sn_state {
6335 int matched;
6336 int i;
6337 bool val;
6340 static void shortname_list_fn(const char *mnt, struct file_info *finfo,
6341 const char *name, void *state)
6343 struct sn_state *s = (struct sn_state *)state;
6344 int i = s->i;
6346 #if 0
6347 printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
6348 i, finfo->name, finfo->short_name);
6349 #endif
6351 if (strchr(force_shortname_chars, i)) {
6352 if (!finfo->short_name[0]) {
6353 /* Shortname not created when it should be. */
6354 d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
6355 __location__, finfo->name, i);
6356 s->val = true;
6358 } else if (finfo->short_name[0]){
6359 /* Shortname created when it should not be. */
6360 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
6361 __location__, finfo->short_name, finfo->name);
6362 s->val = true;
6364 s->matched += 1;
6367 static bool run_shortname_test(int dummy)
6369 static struct cli_state *cli;
6370 bool correct = True;
6371 int i;
6372 struct sn_state s;
6373 char fname[20];
6375 printf("starting shortname test\n");
6377 if (!torture_open_connection(&cli, 0)) {
6378 return False;
6381 cli_sockopt(cli, sockops);
6383 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
6384 cli_list(cli, "\\shortname\\*", aDIR, shortname_del_fn, cli);
6385 cli_rmdir(cli, "\\shortname");
6387 if (!NT_STATUS_IS_OK(cli_mkdir(cli, "\\shortname"))) {
6388 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
6389 __location__, cli_errstr(cli));
6390 correct = false;
6391 goto out;
6394 strlcpy(fname, "\\shortname\\", sizeof(fname));
6395 strlcat(fname, "test .txt", sizeof(fname));
6397 s.val = false;
6399 for (i = 32; i < 128; i++) {
6400 NTSTATUS status;
6401 uint16_t fnum = (uint16_t)-1;
6403 s.i = i;
6405 if (strchr(illegal_chars, i)) {
6406 continue;
6408 fname[15] = i;
6410 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
6411 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum);
6412 if (!NT_STATUS_IS_OK(status)) {
6413 d_printf("(%s) cli_nt_create of %s failed: %s\n",
6414 __location__, fname, cli_errstr(cli));
6415 correct = false;
6416 goto out;
6418 cli_close(cli, fnum);
6420 s.matched = 0;
6421 cli_list(cli, "\\shortname\\test*.*", 0, shortname_list_fn,
6422 &s);
6423 if (s.matched != 1) {
6424 d_printf("(%s) failed to list %s: %s\n",
6425 __location__, fname, cli_errstr(cli));
6426 correct = false;
6427 goto out;
6429 if (!NT_STATUS_IS_OK(cli_unlink(cli, fname, aSYSTEM | aHIDDEN))) {
6430 d_printf("(%s) failed to delete %s: %s\n",
6431 __location__, fname, cli_errstr(cli));
6432 correct = false;
6433 goto out;
6436 if (s.val) {
6437 correct = false;
6438 goto out;
6442 out:
6444 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
6445 cli_list(cli, "\\shortname\\*", aDIR, shortname_del_fn, cli);
6446 cli_rmdir(cli, "\\shortname");
6447 torture_close_connection(cli);
6448 return correct;
6451 static void pagedsearch_cb(struct tevent_req *req)
6453 int rc;
6454 struct tldap_message *msg;
6455 char *dn;
6457 rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
6458 if (rc != TLDAP_SUCCESS) {
6459 d_printf("tldap_search_paged_recv failed: %s\n",
6460 tldap_err2string(rc));
6461 return;
6463 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
6464 TALLOC_FREE(msg);
6465 return;
6467 if (!tldap_entry_dn(msg, &dn)) {
6468 d_printf("tldap_entry_dn failed\n");
6469 return;
6471 d_printf("%s\n", dn);
6472 TALLOC_FREE(msg);
6475 static bool run_tldap(int dummy)
6477 struct tldap_context *ld;
6478 int fd, rc;
6479 NTSTATUS status;
6480 struct sockaddr_storage addr;
6481 struct tevent_context *ev;
6482 struct tevent_req *req;
6483 char *basedn;
6484 const char *filter;
6486 if (!resolve_name(host, &addr, 0, false)) {
6487 d_printf("could not find host %s\n", host);
6488 return false;
6490 status = open_socket_out(&addr, 389, 9999, &fd);
6491 if (!NT_STATUS_IS_OK(status)) {
6492 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
6493 return false;
6496 ld = tldap_context_create(talloc_tos(), fd);
6497 if (ld == NULL) {
6498 close(fd);
6499 d_printf("tldap_context_create failed\n");
6500 return false;
6503 rc = tldap_fetch_rootdse(ld);
6504 if (rc != TLDAP_SUCCESS) {
6505 d_printf("tldap_fetch_rootdse failed: %s\n",
6506 tldap_errstr(talloc_tos(), ld, rc));
6507 return false;
6510 basedn = tldap_talloc_single_attribute(
6511 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
6512 if (basedn == NULL) {
6513 d_printf("no defaultNamingContext\n");
6514 return false;
6516 d_printf("defaultNamingContext: %s\n", basedn);
6518 ev = tevent_context_init(talloc_tos());
6519 if (ev == NULL) {
6520 d_printf("tevent_context_init failed\n");
6521 return false;
6524 req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
6525 TLDAP_SCOPE_SUB, "(objectclass=*)",
6526 NULL, 0, 0,
6527 NULL, 0, NULL, 0, 0, 0, 0, 5);
6528 if (req == NULL) {
6529 d_printf("tldap_search_paged_send failed\n");
6530 return false;
6532 tevent_req_set_callback(req, pagedsearch_cb, NULL);
6534 tevent_req_poll(req, ev);
6536 TALLOC_FREE(req);
6538 /* test search filters against rootDSE */
6539 filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
6540 "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
6542 rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
6543 NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
6544 talloc_tos(), NULL, NULL);
6545 if (rc != TLDAP_SUCCESS) {
6546 d_printf("tldap_search with complex filter failed: %s\n",
6547 tldap_errstr(talloc_tos(), ld, rc));
6548 return false;
6551 TALLOC_FREE(ld);
6552 return true;
6555 /* Torture test to ensure no regression of :
6556 https://bugzilla.samba.org/show_bug.cgi?id=7084
6559 static bool run_dir_createtime(int dummy)
6561 struct cli_state *cli;
6562 const char *dname = "\\testdir";
6563 const char *fname = "\\testdir\\testfile";
6564 NTSTATUS status;
6565 struct timespec create_time;
6566 struct timespec create_time1;
6567 uint16_t fnum;
6568 bool ret = false;
6570 if (!torture_open_connection(&cli, 0)) {
6571 return false;
6574 cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
6575 cli_rmdir(cli, dname);
6577 status = cli_mkdir(cli, dname);
6578 if (!NT_STATUS_IS_OK(status)) {
6579 printf("mkdir failed: %s\n", nt_errstr(status));
6580 goto out;
6583 status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
6584 NULL, NULL, NULL);
6585 if (!NT_STATUS_IS_OK(status)) {
6586 printf("cli_qpathinfo2 returned %s\n",
6587 nt_errstr(status));
6588 goto out;
6591 /* Sleep 3 seconds, then create a file. */
6592 sleep(3);
6594 status = cli_open(cli, fname, O_RDWR | O_CREAT | O_EXCL,
6595 DENY_NONE, &fnum);
6596 if (!NT_STATUS_IS_OK(status)) {
6597 printf("cli_open failed: %s\n", nt_errstr(status));
6598 goto out;
6601 status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
6602 NULL, NULL, NULL);
6603 if (!NT_STATUS_IS_OK(status)) {
6604 printf("cli_qpathinfo2 (2) returned %s\n",
6605 nt_errstr(status));
6606 goto out;
6609 if (timespec_compare(&create_time1, &create_time)) {
6610 printf("run_dir_createtime: create time was updated (error)\n");
6611 } else {
6612 printf("run_dir_createtime: create time was not updated (correct)\n");
6613 ret = true;
6616 out:
6618 cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
6619 cli_rmdir(cli, dname);
6620 if (!torture_close_connection(cli)) {
6621 ret = false;
6623 return ret;
6627 static bool run_streamerror(int dummy)
6629 struct cli_state *cli;
6630 const char *dname = "\\testdir";
6631 const char *streamname =
6632 "testdir:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
6633 NTSTATUS status;
6634 time_t change_time, access_time, write_time;
6635 SMB_OFF_T size;
6636 uint16_t mode, fnum;
6637 bool ret = true;
6639 if (!torture_open_connection(&cli, 0)) {
6640 return false;
6643 cli_unlink(cli, "\\testdir\\*", aSYSTEM | aHIDDEN);
6644 cli_rmdir(cli, dname);
6646 status = cli_mkdir(cli, dname);
6647 if (!NT_STATUS_IS_OK(status)) {
6648 printf("mkdir failed: %s\n", nt_errstr(status));
6649 return false;
6652 cli_qpathinfo1(cli, streamname, &change_time, &access_time, &write_time,
6653 &size, &mode);
6654 status = cli_nt_error(cli);
6656 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6657 printf("pathinfo returned %s, expected "
6658 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
6659 nt_errstr(status));
6660 ret = false;
6663 status = cli_ntcreate(cli, streamname, 0x16,
6664 FILE_READ_DATA|FILE_READ_EA|
6665 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
6666 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6667 FILE_OPEN, 0, 0, &fnum);
6669 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6670 printf("ntcreate returned %s, expected "
6671 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
6672 nt_errstr(status));
6673 ret = false;
6677 cli_rmdir(cli, dname);
6678 return ret;
6681 static bool run_local_substitute(int dummy)
6683 bool ok = true;
6685 ok &= subst_test("%U", "bla", "", -1, -1, "bla");
6686 ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
6687 ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
6688 ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
6689 ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
6690 ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
6691 ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
6692 ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
6694 /* Different captialization rules in sub_basic... */
6696 ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
6697 "blaDOM") == 0);
6699 return ok;
6702 static bool run_local_base64(int dummy)
6704 int i;
6705 bool ret = true;
6707 for (i=1; i<2000; i++) {
6708 DATA_BLOB blob1, blob2;
6709 char *b64;
6711 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
6712 blob1.length = i;
6713 generate_random_buffer(blob1.data, blob1.length);
6715 b64 = base64_encode_data_blob(talloc_tos(), blob1);
6716 if (b64 == NULL) {
6717 d_fprintf(stderr, "base64_encode_data_blob failed "
6718 "for %d bytes\n", i);
6719 ret = false;
6721 blob2 = base64_decode_data_blob(b64);
6722 TALLOC_FREE(b64);
6724 if (data_blob_cmp(&blob1, &blob2)) {
6725 d_fprintf(stderr, "data_blob_cmp failed for %d "
6726 "bytes\n", i);
6727 ret = false;
6729 TALLOC_FREE(blob1.data);
6730 data_blob_free(&blob2);
6732 return ret;
6735 static bool run_local_gencache(int dummy)
6737 char *val;
6738 time_t tm;
6739 DATA_BLOB blob;
6741 if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
6742 d_printf("%s: gencache_set() failed\n", __location__);
6743 return False;
6746 if (!gencache_get("foo", NULL, NULL)) {
6747 d_printf("%s: gencache_get() failed\n", __location__);
6748 return False;
6751 if (!gencache_get("foo", &val, &tm)) {
6752 d_printf("%s: gencache_get() failed\n", __location__);
6753 return False;
6756 if (strcmp(val, "bar") != 0) {
6757 d_printf("%s: gencache_get() returned %s, expected %s\n",
6758 __location__, val, "bar");
6759 SAFE_FREE(val);
6760 return False;
6763 SAFE_FREE(val);
6765 if (!gencache_del("foo")) {
6766 d_printf("%s: gencache_del() failed\n", __location__);
6767 return False;
6769 if (gencache_del("foo")) {
6770 d_printf("%s: second gencache_del() succeeded\n",
6771 __location__);
6772 return False;
6775 if (gencache_get("foo", &val, &tm)) {
6776 d_printf("%s: gencache_get() on deleted entry "
6777 "succeeded\n", __location__);
6778 return False;
6781 blob = data_blob_string_const_null("bar");
6782 tm = time(NULL) + 60;
6784 if (!gencache_set_data_blob("foo", &blob, tm)) {
6785 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
6786 return False;
6789 if (!gencache_get_data_blob("foo", &blob, NULL, NULL)) {
6790 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
6791 return False;
6794 if (strcmp((const char *)blob.data, "bar") != 0) {
6795 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
6796 __location__, (const char *)blob.data, "bar");
6797 data_blob_free(&blob);
6798 return False;
6801 data_blob_free(&blob);
6803 if (!gencache_del("foo")) {
6804 d_printf("%s: gencache_del() failed\n", __location__);
6805 return False;
6807 if (gencache_del("foo")) {
6808 d_printf("%s: second gencache_del() succeeded\n",
6809 __location__);
6810 return False;
6813 if (gencache_get_data_blob("foo", &blob, NULL, NULL)) {
6814 d_printf("%s: gencache_get_data_blob() on deleted entry "
6815 "succeeded\n", __location__);
6816 return False;
6819 return True;
6822 static bool rbt_testval(struct db_context *db, const char *key,
6823 const char *value)
6825 struct db_record *rec;
6826 TDB_DATA data = string_tdb_data(value);
6827 bool ret = false;
6828 NTSTATUS status;
6830 rec = db->fetch_locked(db, db, string_tdb_data(key));
6831 if (rec == NULL) {
6832 d_fprintf(stderr, "fetch_locked failed\n");
6833 goto done;
6835 status = rec->store(rec, data, 0);
6836 if (!NT_STATUS_IS_OK(status)) {
6837 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
6838 goto done;
6840 TALLOC_FREE(rec);
6842 rec = db->fetch_locked(db, db, string_tdb_data(key));
6843 if (rec == NULL) {
6844 d_fprintf(stderr, "second fetch_locked failed\n");
6845 goto done;
6847 if ((rec->value.dsize != data.dsize)
6848 || (memcmp(rec->value.dptr, data.dptr, data.dsize) != 0)) {
6849 d_fprintf(stderr, "Got wrong data back\n");
6850 goto done;
6853 ret = true;
6854 done:
6855 TALLOC_FREE(rec);
6856 return ret;
6859 static bool run_local_rbtree(int dummy)
6861 struct db_context *db;
6862 bool ret = false;
6863 int i;
6865 db = db_open_rbt(NULL);
6867 if (db == NULL) {
6868 d_fprintf(stderr, "db_open_rbt failed\n");
6869 return false;
6872 for (i=0; i<1000; i++) {
6873 char *key, *value;
6875 if (asprintf(&key, "key%ld", random()) == -1) {
6876 goto done;
6878 if (asprintf(&value, "value%ld", random()) == -1) {
6879 SAFE_FREE(key);
6880 goto done;
6883 if (!rbt_testval(db, key, value)) {
6884 SAFE_FREE(key);
6885 SAFE_FREE(value);
6886 goto done;
6889 SAFE_FREE(value);
6890 if (asprintf(&value, "value%ld", random()) == -1) {
6891 SAFE_FREE(key);
6892 goto done;
6895 if (!rbt_testval(db, key, value)) {
6896 SAFE_FREE(key);
6897 SAFE_FREE(value);
6898 goto done;
6901 SAFE_FREE(key);
6902 SAFE_FREE(value);
6905 ret = true;
6907 done:
6908 TALLOC_FREE(db);
6909 return ret;
6912 struct talloc_dict_test {
6913 int content;
6916 static int talloc_dict_traverse_fn(DATA_BLOB key, void *data, void *priv)
6918 int *count = (int *)priv;
6919 *count += 1;
6920 return 0;
6923 static bool run_local_talloc_dict(int dummy)
6925 struct talloc_dict *dict;
6926 struct talloc_dict_test *t;
6927 int key, count;
6929 dict = talloc_dict_init(talloc_tos());
6930 if (dict == NULL) {
6931 return false;
6934 t = talloc(talloc_tos(), struct talloc_dict_test);
6935 if (t == NULL) {
6936 return false;
6939 key = 1;
6940 t->content = 1;
6941 if (!talloc_dict_set(dict, data_blob_const(&key, sizeof(key)), t)) {
6942 return false;
6945 count = 0;
6946 if (talloc_dict_traverse(dict, talloc_dict_traverse_fn, &count) != 0) {
6947 return false;
6950 if (count != 1) {
6951 return false;
6954 TALLOC_FREE(dict);
6956 return true;
6959 static bool run_local_string_to_sid(int dummy) {
6960 struct dom_sid sid;
6962 if (string_to_sid(&sid, "S--1-5-32-545")) {
6963 printf("allowing S--1-5-32-545\n");
6964 return false;
6966 if (string_to_sid(&sid, "S-1-5-32-+545")) {
6967 printf("allowing S-1-5-32-+545\n");
6968 return false;
6970 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")) {
6971 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
6972 return false;
6974 if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
6975 printf("allowing S-1-5-32-545-abc\n");
6976 return false;
6978 if (!string_to_sid(&sid, "S-1-5-32-545")) {
6979 printf("could not parse S-1-5-32-545\n");
6980 return false;
6982 if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
6983 printf("mis-parsed S-1-5-32-545 as %s\n",
6984 sid_string_tos(&sid));
6985 return false;
6987 return true;
6990 static bool run_local_binary_to_sid(int dummy) {
6991 struct dom_sid *sid = talloc(NULL, struct dom_sid);
6992 static const char good_binary_sid[] = {
6993 0x1, /* revision number */
6994 15, /* num auths */
6995 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
6996 0x1, 0x1, 0x1, 0x1, /* auth[0] */
6997 0x1, 0x1, 0x1, 0x1, /* auth[1] */
6998 0x1, 0x1, 0x1, 0x1, /* auth[2] */
6999 0x1, 0x1, 0x1, 0x1, /* auth[3] */
7000 0x1, 0x1, 0x1, 0x1, /* auth[4] */
7001 0x1, 0x1, 0x1, 0x1, /* auth[5] */
7002 0x1, 0x1, 0x1, 0x1, /* auth[6] */
7003 0x1, 0x1, 0x1, 0x1, /* auth[7] */
7004 0x1, 0x1, 0x1, 0x1, /* auth[8] */
7005 0x1, 0x1, 0x1, 0x1, /* auth[9] */
7006 0x1, 0x1, 0x1, 0x1, /* auth[10] */
7007 0x1, 0x1, 0x1, 0x1, /* auth[11] */
7008 0x1, 0x1, 0x1, 0x1, /* auth[12] */
7009 0x1, 0x1, 0x1, 0x1, /* auth[13] */
7010 0x1, 0x1, 0x1, 0x1, /* auth[14] */
7013 static const char long_binary_sid[] = {
7014 0x1, /* revision number */
7015 15, /* num auths */
7016 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
7017 0x1, 0x1, 0x1, 0x1, /* auth[0] */
7018 0x1, 0x1, 0x1, 0x1, /* auth[1] */
7019 0x1, 0x1, 0x1, 0x1, /* auth[2] */
7020 0x1, 0x1, 0x1, 0x1, /* auth[3] */
7021 0x1, 0x1, 0x1, 0x1, /* auth[4] */
7022 0x1, 0x1, 0x1, 0x1, /* auth[5] */
7023 0x1, 0x1, 0x1, 0x1, /* auth[6] */
7024 0x1, 0x1, 0x1, 0x1, /* auth[7] */
7025 0x1, 0x1, 0x1, 0x1, /* auth[8] */
7026 0x1, 0x1, 0x1, 0x1, /* auth[9] */
7027 0x1, 0x1, 0x1, 0x1, /* auth[10] */
7028 0x1, 0x1, 0x1, 0x1, /* auth[11] */
7029 0x1, 0x1, 0x1, 0x1, /* auth[12] */
7030 0x1, 0x1, 0x1, 0x1, /* auth[13] */
7031 0x1, 0x1, 0x1, 0x1, /* auth[14] */
7032 0x1, 0x1, 0x1, 0x1, /* auth[15] */
7033 0x1, 0x1, 0x1, 0x1, /* auth[16] */
7034 0x1, 0x1, 0x1, 0x1, /* auth[17] */
7037 static const char long_binary_sid2[] = {
7038 0x1, /* revision number */
7039 32, /* num auths */
7040 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
7041 0x1, 0x1, 0x1, 0x1, /* auth[0] */
7042 0x1, 0x1, 0x1, 0x1, /* auth[1] */
7043 0x1, 0x1, 0x1, 0x1, /* auth[2] */
7044 0x1, 0x1, 0x1, 0x1, /* auth[3] */
7045 0x1, 0x1, 0x1, 0x1, /* auth[4] */
7046 0x1, 0x1, 0x1, 0x1, /* auth[5] */
7047 0x1, 0x1, 0x1, 0x1, /* auth[6] */
7048 0x1, 0x1, 0x1, 0x1, /* auth[7] */
7049 0x1, 0x1, 0x1, 0x1, /* auth[8] */
7050 0x1, 0x1, 0x1, 0x1, /* auth[9] */
7051 0x1, 0x1, 0x1, 0x1, /* auth[10] */
7052 0x1, 0x1, 0x1, 0x1, /* auth[11] */
7053 0x1, 0x1, 0x1, 0x1, /* auth[12] */
7054 0x1, 0x1, 0x1, 0x1, /* auth[13] */
7055 0x1, 0x1, 0x1, 0x1, /* auth[14] */
7056 0x1, 0x1, 0x1, 0x1, /* auth[15] */
7057 0x1, 0x1, 0x1, 0x1, /* auth[16] */
7058 0x1, 0x1, 0x1, 0x1, /* auth[17] */
7059 0x1, 0x1, 0x1, 0x1, /* auth[18] */
7060 0x1, 0x1, 0x1, 0x1, /* auth[19] */
7061 0x1, 0x1, 0x1, 0x1, /* auth[20] */
7062 0x1, 0x1, 0x1, 0x1, /* auth[21] */
7063 0x1, 0x1, 0x1, 0x1, /* auth[22] */
7064 0x1, 0x1, 0x1, 0x1, /* auth[23] */
7065 0x1, 0x1, 0x1, 0x1, /* auth[24] */
7066 0x1, 0x1, 0x1, 0x1, /* auth[25] */
7067 0x1, 0x1, 0x1, 0x1, /* auth[26] */
7068 0x1, 0x1, 0x1, 0x1, /* auth[27] */
7069 0x1, 0x1, 0x1, 0x1, /* auth[28] */
7070 0x1, 0x1, 0x1, 0x1, /* auth[29] */
7071 0x1, 0x1, 0x1, 0x1, /* auth[30] */
7072 0x1, 0x1, 0x1, 0x1, /* auth[31] */
7075 if (!sid_parse(good_binary_sid, sizeof(good_binary_sid), sid)) {
7076 return false;
7078 if (sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid)) {
7079 return false;
7081 if (sid_parse(long_binary_sid, sizeof(long_binary_sid), sid)) {
7082 return false;
7084 return true;
7087 /* Split a path name into filename and stream name components. Canonicalise
7088 * such that an implicit $DATA token is always explicit.
7090 * The "specification" of this function can be found in the
7091 * run_local_stream_name() function in torture.c, I've tried those
7092 * combinations against a W2k3 server.
7095 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
7096 char **pbase, char **pstream)
7098 char *base = NULL;
7099 char *stream = NULL;
7100 char *sname; /* stream name */
7101 const char *stype; /* stream type */
7103 DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
7105 sname = strchr_m(fname, ':');
7107 if (lp_posix_pathnames() || (sname == NULL)) {
7108 if (pbase != NULL) {
7109 base = talloc_strdup(mem_ctx, fname);
7110 NT_STATUS_HAVE_NO_MEMORY(base);
7112 goto done;
7115 if (pbase != NULL) {
7116 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
7117 NT_STATUS_HAVE_NO_MEMORY(base);
7120 sname += 1;
7122 stype = strchr_m(sname, ':');
7124 if (stype == NULL) {
7125 sname = talloc_strdup(mem_ctx, sname);
7126 stype = "$DATA";
7128 else {
7129 if (StrCaseCmp(stype, ":$DATA") != 0) {
7131 * If there is an explicit stream type, so far we only
7132 * allow $DATA. Is there anything else allowed? -- vl
7134 DEBUG(10, ("[%s] is an invalid stream type\n", stype));
7135 TALLOC_FREE(base);
7136 return NT_STATUS_OBJECT_NAME_INVALID;
7138 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
7139 stype += 1;
7142 if (sname == NULL) {
7143 TALLOC_FREE(base);
7144 return NT_STATUS_NO_MEMORY;
7147 if (sname[0] == '\0') {
7149 * no stream name, so no stream
7151 goto done;
7154 if (pstream != NULL) {
7155 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
7156 if (stream == NULL) {
7157 TALLOC_FREE(sname);
7158 TALLOC_FREE(base);
7159 return NT_STATUS_NO_MEMORY;
7162 * upper-case the type field
7164 strupper_m(strchr_m(stream, ':')+1);
7167 done:
7168 if (pbase != NULL) {
7169 *pbase = base;
7171 if (pstream != NULL) {
7172 *pstream = stream;
7174 return NT_STATUS_OK;
7177 static bool test_stream_name(const char *fname, const char *expected_base,
7178 const char *expected_stream,
7179 NTSTATUS expected_status)
7181 NTSTATUS status;
7182 char *base = NULL;
7183 char *stream = NULL;
7185 status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
7186 if (!NT_STATUS_EQUAL(status, expected_status)) {
7187 goto error;
7190 if (!NT_STATUS_IS_OK(status)) {
7191 return true;
7194 if (base == NULL) goto error;
7196 if (strcmp(expected_base, base) != 0) goto error;
7198 if ((expected_stream != NULL) && (stream == NULL)) goto error;
7199 if ((expected_stream == NULL) && (stream != NULL)) goto error;
7201 if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
7202 goto error;
7204 TALLOC_FREE(base);
7205 TALLOC_FREE(stream);
7206 return true;
7208 error:
7209 d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
7210 fname, expected_base ? expected_base : "<NULL>",
7211 expected_stream ? expected_stream : "<NULL>",
7212 nt_errstr(expected_status));
7213 d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
7214 base ? base : "<NULL>", stream ? stream : "<NULL>",
7215 nt_errstr(status));
7216 TALLOC_FREE(base);
7217 TALLOC_FREE(stream);
7218 return false;
7221 static bool run_local_stream_name(int dummy)
7223 bool ret = true;
7225 ret &= test_stream_name(
7226 "bla", "bla", NULL, NT_STATUS_OK);
7227 ret &= test_stream_name(
7228 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
7229 ret &= test_stream_name(
7230 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
7231 ret &= test_stream_name(
7232 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
7233 ret &= test_stream_name(
7234 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
7235 ret &= test_stream_name(
7236 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
7237 ret &= test_stream_name(
7238 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
7239 ret &= test_stream_name(
7240 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
7242 return ret;
7245 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
7247 if (a.length != b.length) {
7248 printf("a.length=%d != b.length=%d\n",
7249 (int)a.length, (int)b.length);
7250 return false;
7252 if (memcmp(a.data, b.data, a.length) != 0) {
7253 printf("a.data and b.data differ\n");
7254 return false;
7256 return true;
7259 static bool run_local_memcache(int dummy)
7261 struct memcache *cache;
7262 DATA_BLOB k1, k2;
7263 DATA_BLOB d1, d2, d3;
7264 DATA_BLOB v1, v2, v3;
7266 TALLOC_CTX *mem_ctx;
7267 char *str1, *str2;
7268 size_t size1, size2;
7269 bool ret = false;
7271 cache = memcache_init(NULL, 100);
7273 if (cache == NULL) {
7274 printf("memcache_init failed\n");
7275 return false;
7278 d1 = data_blob_const("d1", 2);
7279 d2 = data_blob_const("d2", 2);
7280 d3 = data_blob_const("d3", 2);
7282 k1 = data_blob_const("d1", 2);
7283 k2 = data_blob_const("d2", 2);
7285 memcache_add(cache, STAT_CACHE, k1, d1);
7286 memcache_add(cache, GETWD_CACHE, k2, d2);
7288 if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
7289 printf("could not find k1\n");
7290 return false;
7292 if (!data_blob_equal(d1, v1)) {
7293 return false;
7296 if (!memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
7297 printf("could not find k2\n");
7298 return false;
7300 if (!data_blob_equal(d2, v2)) {
7301 return false;
7304 memcache_add(cache, STAT_CACHE, k1, d3);
7306 if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
7307 printf("could not find replaced k1\n");
7308 return false;
7310 if (!data_blob_equal(d3, v3)) {
7311 return false;
7314 memcache_add(cache, GETWD_CACHE, k1, d1);
7316 if (memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
7317 printf("Did find k2, should have been purged\n");
7318 return false;
7321 TALLOC_FREE(cache);
7323 cache = memcache_init(NULL, 0);
7325 mem_ctx = talloc_init("foo");
7327 str1 = talloc_strdup(mem_ctx, "string1");
7328 str2 = talloc_strdup(mem_ctx, "string2");
7330 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
7331 data_blob_string_const("torture"), &str1);
7332 size1 = talloc_total_size(cache);
7334 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
7335 data_blob_string_const("torture"), &str2);
7336 size2 = talloc_total_size(cache);
7338 printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
7340 if (size2 > size1) {
7341 printf("memcache leaks memory!\n");
7342 goto fail;
7345 ret = true;
7346 fail:
7347 TALLOC_FREE(cache);
7348 return ret;
7351 static void wbclient_done(struct tevent_req *req)
7353 wbcErr wbc_err;
7354 struct winbindd_response *wb_resp;
7355 int *i = (int *)tevent_req_callback_data_void(req);
7357 wbc_err = wb_trans_recv(req, req, &wb_resp);
7358 TALLOC_FREE(req);
7359 *i += 1;
7360 d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
7363 static bool run_local_wbclient(int dummy)
7365 struct event_context *ev;
7366 struct wb_context **wb_ctx;
7367 struct winbindd_request wb_req;
7368 bool result = false;
7369 int i, j;
7371 BlockSignals(True, SIGPIPE);
7373 ev = tevent_context_init_byname(talloc_tos(), "epoll");
7374 if (ev == NULL) {
7375 goto fail;
7378 wb_ctx = TALLOC_ARRAY(ev, struct wb_context *, nprocs);
7379 if (wb_ctx == NULL) {
7380 goto fail;
7383 ZERO_STRUCT(wb_req);
7384 wb_req.cmd = WINBINDD_PING;
7386 d_printf("nprocs=%d, numops=%d\n", (int)nprocs, (int)torture_numops);
7388 for (i=0; i<nprocs; i++) {
7389 wb_ctx[i] = wb_context_init(ev, NULL);
7390 if (wb_ctx[i] == NULL) {
7391 goto fail;
7393 for (j=0; j<torture_numops; j++) {
7394 struct tevent_req *req;
7395 req = wb_trans_send(ev, ev, wb_ctx[i],
7396 (j % 2) == 0, &wb_req);
7397 if (req == NULL) {
7398 goto fail;
7400 tevent_req_set_callback(req, wbclient_done, &i);
7404 i = 0;
7406 while (i < nprocs * torture_numops) {
7407 event_loop_once(ev);
7410 result = true;
7411 fail:
7412 TALLOC_FREE(ev);
7413 return result;
7416 static void getaddrinfo_finished(struct tevent_req *req)
7418 char *name = (char *)tevent_req_callback_data_void(req);
7419 struct addrinfo *ainfo;
7420 int res;
7422 res = getaddrinfo_recv(req, &ainfo);
7423 if (res != 0) {
7424 d_printf("gai(%s) returned %s\n", name, gai_strerror(res));
7425 return;
7427 d_printf("gai(%s) succeeded\n", name);
7428 freeaddrinfo(ainfo);
7431 static bool run_getaddrinfo_send(int dummy)
7433 TALLOC_CTX *frame = talloc_stackframe();
7434 struct fncall_context *ctx;
7435 struct tevent_context *ev;
7436 bool result = false;
7437 const char *names[4] = { "www.samba.org", "notfound.samba.org",
7438 "www.slashdot.org", "heise.de" };
7439 struct tevent_req *reqs[4];
7440 int i;
7442 ev = event_context_init(frame);
7443 if (ev == NULL) {
7444 goto fail;
7447 ctx = fncall_context_init(frame, 4);
7449 for (i=0; i<ARRAY_SIZE(names); i++) {
7450 reqs[i] = getaddrinfo_send(frame, ev, ctx, names[i], NULL,
7451 NULL);
7452 if (reqs[i] == NULL) {
7453 goto fail;
7455 tevent_req_set_callback(reqs[i], getaddrinfo_finished,
7456 (void *)names[i]);
7459 for (i=0; i<ARRAY_SIZE(reqs); i++) {
7460 tevent_loop_once(ev);
7463 result = true;
7464 fail:
7465 TALLOC_FREE(frame);
7466 return result;
7469 static bool dbtrans_inc(struct db_context *db)
7471 struct db_record *rec;
7472 uint32_t *val;
7473 bool ret = false;
7474 NTSTATUS status;
7476 rec = db->fetch_locked(db, db, string_term_tdb_data("transtest"));
7477 if (rec == NULL) {
7478 printf(__location__ "fetch_lock failed\n");
7479 return false;
7482 if (rec->value.dsize != sizeof(uint32_t)) {
7483 printf(__location__ "value.dsize = %d\n",
7484 (int)rec->value.dsize);
7485 goto fail;
7488 val = (uint32_t *)rec->value.dptr;
7489 *val += 1;
7491 status = rec->store(rec, make_tdb_data((uint8_t *)val,
7492 sizeof(uint32_t)),
7494 if (!NT_STATUS_IS_OK(status)) {
7495 printf(__location__ "store failed: %s\n",
7496 nt_errstr(status));
7497 goto fail;
7500 ret = true;
7501 fail:
7502 TALLOC_FREE(rec);
7503 return ret;
7506 static bool run_local_dbtrans(int dummy)
7508 struct db_context *db;
7509 struct db_record *rec;
7510 NTSTATUS status;
7511 uint32_t initial;
7512 int res;
7514 db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
7515 O_RDWR|O_CREAT, 0600);
7516 if (db == NULL) {
7517 printf("Could not open transtest.db\n");
7518 return false;
7521 res = db->transaction_start(db);
7522 if (res == -1) {
7523 printf(__location__ "transaction_start failed\n");
7524 return false;
7527 rec = db->fetch_locked(db, db, string_term_tdb_data("transtest"));
7528 if (rec == NULL) {
7529 printf(__location__ "fetch_lock failed\n");
7530 return false;
7533 if (rec->value.dptr == NULL) {
7534 initial = 0;
7535 status = rec->store(
7536 rec, make_tdb_data((uint8_t *)&initial,
7537 sizeof(initial)),
7539 if (!NT_STATUS_IS_OK(status)) {
7540 printf(__location__ "store returned %s\n",
7541 nt_errstr(status));
7542 return false;
7546 TALLOC_FREE(rec);
7548 res = db->transaction_commit(db);
7549 if (res == -1) {
7550 printf(__location__ "transaction_commit failed\n");
7551 return false;
7554 while (true) {
7555 uint32_t val, val2;
7556 int i;
7558 res = db->transaction_start(db);
7559 if (res == -1) {
7560 printf(__location__ "transaction_start failed\n");
7561 break;
7564 if (!dbwrap_fetch_uint32(db, "transtest", &val)) {
7565 printf(__location__ "dbwrap_fetch_uint32 failed\n");
7566 break;
7569 for (i=0; i<10; i++) {
7570 if (!dbtrans_inc(db)) {
7571 return false;
7575 if (!dbwrap_fetch_uint32(db, "transtest", &val2)) {
7576 printf(__location__ "dbwrap_fetch_uint32 failed\n");
7577 break;
7580 if (val2 != val + 10) {
7581 printf(__location__ "val=%d, val2=%d\n",
7582 (int)val, (int)val2);
7583 break;
7586 printf("val2=%d\r", val2);
7588 res = db->transaction_commit(db);
7589 if (res == -1) {
7590 printf(__location__ "transaction_commit failed\n");
7591 break;
7595 TALLOC_FREE(db);
7596 return true;
7600 * Just a dummy test to be run under a debugger. There's no real way
7601 * to inspect the tevent_select specific function from outside of
7602 * tevent_select.c.
7605 static bool run_local_tevent_select(int dummy)
7607 struct tevent_context *ev;
7608 struct tevent_fd *fd1, *fd2;
7609 bool result = false;
7611 ev = tevent_context_init_byname(NULL, "select");
7612 if (ev == NULL) {
7613 d_fprintf(stderr, "tevent_context_init_byname failed\n");
7614 goto fail;
7617 fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
7618 if (fd1 == NULL) {
7619 d_fprintf(stderr, "tevent_add_fd failed\n");
7620 goto fail;
7622 fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
7623 if (fd2 == NULL) {
7624 d_fprintf(stderr, "tevent_add_fd failed\n");
7625 goto fail;
7627 TALLOC_FREE(fd2);
7629 fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
7630 if (fd2 == NULL) {
7631 d_fprintf(stderr, "tevent_add_fd failed\n");
7632 goto fail;
7635 result = true;
7636 fail:
7637 TALLOC_FREE(ev);
7638 return result;
7641 static double create_procs(bool (*fn)(int), bool *result)
7643 int i, status;
7644 volatile pid_t *child_status;
7645 volatile bool *child_status_out;
7646 int synccount;
7647 int tries = 8;
7648 struct timeval start;
7650 synccount = 0;
7652 child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*nprocs);
7653 if (!child_status) {
7654 printf("Failed to setup shared memory\n");
7655 return -1;
7658 child_status_out = (volatile bool *)shm_setup(sizeof(bool)*nprocs);
7659 if (!child_status_out) {
7660 printf("Failed to setup result status shared memory\n");
7661 return -1;
7664 for (i = 0; i < nprocs; i++) {
7665 child_status[i] = 0;
7666 child_status_out[i] = True;
7669 start = timeval_current();
7671 for (i=0;i<nprocs;i++) {
7672 procnum = i;
7673 if (fork() == 0) {
7674 pid_t mypid = getpid();
7675 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
7677 slprintf(myname,sizeof(myname),"CLIENT%d", i);
7679 while (1) {
7680 if (torture_open_connection(&current_cli, i)) break;
7681 if (tries-- == 0) {
7682 printf("pid %d failed to start\n", (int)getpid());
7683 _exit(1);
7685 smb_msleep(10);
7688 child_status[i] = getpid();
7690 while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
7692 child_status_out[i] = fn(i);
7693 _exit(0);
7697 do {
7698 synccount = 0;
7699 for (i=0;i<nprocs;i++) {
7700 if (child_status[i]) synccount++;
7702 if (synccount == nprocs) break;
7703 smb_msleep(10);
7704 } while (timeval_elapsed(&start) < 30);
7706 if (synccount != nprocs) {
7707 printf("FAILED TO START %d CLIENTS (started %d)\n", nprocs, synccount);
7708 *result = False;
7709 return timeval_elapsed(&start);
7712 /* start the client load */
7713 start = timeval_current();
7715 for (i=0;i<nprocs;i++) {
7716 child_status[i] = 0;
7719 printf("%d clients started\n", nprocs);
7721 for (i=0;i<nprocs;i++) {
7722 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
7725 printf("\n");
7727 for (i=0;i<nprocs;i++) {
7728 if (!child_status_out[i]) {
7729 *result = False;
7732 return timeval_elapsed(&start);
7735 #define FLAG_MULTIPROC 1
7737 static struct {
7738 const char *name;
7739 bool (*fn)(int);
7740 unsigned flags;
7741 } torture_ops[] = {
7742 {"FDPASS", run_fdpasstest, 0},
7743 {"LOCK1", run_locktest1, 0},
7744 {"LOCK2", run_locktest2, 0},
7745 {"LOCK3", run_locktest3, 0},
7746 {"LOCK4", run_locktest4, 0},
7747 {"LOCK5", run_locktest5, 0},
7748 {"LOCK6", run_locktest6, 0},
7749 {"LOCK7", run_locktest7, 0},
7750 {"LOCK8", run_locktest8, 0},
7751 {"LOCK9", run_locktest9, 0},
7752 {"UNLINK", run_unlinktest, 0},
7753 {"BROWSE", run_browsetest, 0},
7754 {"ATTR", run_attrtest, 0},
7755 {"TRANS2", run_trans2test, 0},
7756 {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
7757 {"TORTURE",run_torture, FLAG_MULTIPROC},
7758 {"RANDOMIPC", run_randomipc, 0},
7759 {"NEGNOWAIT", run_negprot_nowait, 0},
7760 {"NBENCH", run_nbench, 0},
7761 {"NBENCH2", run_nbench2, 0},
7762 {"OPLOCK1", run_oplock1, 0},
7763 {"OPLOCK2", run_oplock2, 0},
7764 {"OPLOCK3", run_oplock3, 0},
7765 {"DIR", run_dirtest, 0},
7766 {"DIR1", run_dirtest1, 0},
7767 {"DIR-CREATETIME", run_dir_createtime, 0},
7768 {"DENY1", torture_denytest1, 0},
7769 {"DENY2", torture_denytest2, 0},
7770 {"TCON", run_tcon_test, 0},
7771 {"TCONDEV", run_tcon_devtype_test, 0},
7772 {"RW1", run_readwritetest, 0},
7773 {"RW2", run_readwritemulti, FLAG_MULTIPROC},
7774 {"RW3", run_readwritelarge, 0},
7775 {"OPEN", run_opentest, 0},
7776 {"POSIX", run_simple_posix_open_test, 0},
7777 {"POSIX-APPEND", run_posix_append, 0},
7778 {"ASYNC-ECHO", run_async_echo, 0},
7779 { "UID-REGRESSION-TEST", run_uid_regression_test, 0},
7780 { "SHORTNAME-TEST", run_shortname_test, 0},
7781 #if 1
7782 {"OPENATTR", run_openattrtest, 0},
7783 #endif
7784 {"XCOPY", run_xcopy, 0},
7785 {"RENAME", run_rename, 0},
7786 {"DELETE", run_deletetest, 0},
7787 {"PROPERTIES", run_properties, 0},
7788 {"MANGLE", torture_mangle, 0},
7789 {"MANGLE1", run_mangle1, 0},
7790 {"W2K", run_w2ktest, 0},
7791 {"TRANS2SCAN", torture_trans2_scan, 0},
7792 {"NTTRANSSCAN", torture_nttrans_scan, 0},
7793 {"UTABLE", torture_utable, 0},
7794 {"CASETABLE", torture_casetable, 0},
7795 {"ERRMAPEXTRACT", run_error_map_extract, 0},
7796 {"PIPE_NUMBER", run_pipe_number, 0},
7797 {"TCON2", run_tcon2_test, 0},
7798 {"IOCTL", torture_ioctl_test, 0},
7799 {"CHKPATH", torture_chkpath_test, 0},
7800 {"FDSESS", run_fdsesstest, 0},
7801 { "EATEST", run_eatest, 0},
7802 { "SESSSETUP_BENCH", run_sesssetup_bench, 0},
7803 { "CHAIN1", run_chain1, 0},
7804 { "CHAIN2", run_chain2, 0},
7805 { "WINDOWS-WRITE", run_windows_write, 0},
7806 { "CLI_ECHO", run_cli_echo, 0},
7807 { "GETADDRINFO", run_getaddrinfo_send, 0},
7808 { "TLDAP", run_tldap },
7809 { "STREAMERROR", run_streamerror },
7810 { "NOTIFY-BENCH", run_notify_bench },
7811 { "BAD-NBT-SESSION", run_bad_nbt_session },
7812 { "LOCAL-SUBSTITUTE", run_local_substitute, 0},
7813 { "LOCAL-GENCACHE", run_local_gencache, 0},
7814 { "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0},
7815 { "LOCAL-BASE64", run_local_base64, 0},
7816 { "LOCAL-RBTREE", run_local_rbtree, 0},
7817 { "LOCAL-MEMCACHE", run_local_memcache, 0},
7818 { "LOCAL-STREAM-NAME", run_local_stream_name, 0},
7819 { "LOCAL-WBCLIENT", run_local_wbclient, 0},
7820 { "LOCAL-string_to_sid", run_local_string_to_sid, 0},
7821 { "LOCAL-binary_to_sid", run_local_binary_to_sid, 0},
7822 { "LOCAL-DBTRANS", run_local_dbtrans, 0},
7823 { "LOCAL-TEVENT-SELECT", run_local_tevent_select, 0},
7824 {NULL, NULL, 0}};
7828 /****************************************************************************
7829 run a specified test or "ALL"
7830 ****************************************************************************/
7831 static bool run_test(const char *name)
7833 bool ret = True;
7834 bool result = True;
7835 bool found = False;
7836 int i;
7837 double t;
7838 if (strequal(name,"ALL")) {
7839 for (i=0;torture_ops[i].name;i++) {
7840 run_test(torture_ops[i].name);
7842 found = True;
7845 for (i=0;torture_ops[i].name;i++) {
7846 fstr_sprintf(randomfname, "\\XX%x",
7847 (unsigned)random());
7849 if (strequal(name, torture_ops[i].name)) {
7850 found = True;
7851 printf("Running %s\n", name);
7852 if (torture_ops[i].flags & FLAG_MULTIPROC) {
7853 t = create_procs(torture_ops[i].fn, &result);
7854 if (!result) {
7855 ret = False;
7856 printf("TEST %s FAILED!\n", name);
7858 } else {
7859 struct timeval start;
7860 start = timeval_current();
7861 if (!torture_ops[i].fn(0)) {
7862 ret = False;
7863 printf("TEST %s FAILED!\n", name);
7865 t = timeval_elapsed(&start);
7867 printf("%s took %g secs\n\n", name, t);
7871 if (!found) {
7872 printf("Did not find a test named %s\n", name);
7873 ret = False;
7876 return ret;
7880 static void usage(void)
7882 int i;
7884 printf("WARNING samba4 test suite is much more complete nowadays.\n");
7885 printf("Please use samba4 torture.\n\n");
7887 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
7889 printf("\t-d debuglevel\n");
7890 printf("\t-U user%%pass\n");
7891 printf("\t-k use kerberos\n");
7892 printf("\t-N numprocs\n");
7893 printf("\t-n my_netbios_name\n");
7894 printf("\t-W workgroup\n");
7895 printf("\t-o num_operations\n");
7896 printf("\t-O socket_options\n");
7897 printf("\t-m maximum protocol\n");
7898 printf("\t-L use oplocks\n");
7899 printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
7900 printf("\t-A showall\n");
7901 printf("\t-p port\n");
7902 printf("\t-s seed\n");
7903 printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
7904 printf("\n\n");
7906 printf("tests are:");
7907 for (i=0;torture_ops[i].name;i++) {
7908 printf(" %s", torture_ops[i].name);
7910 printf("\n");
7912 printf("default test is ALL\n");
7914 exit(1);
7917 /****************************************************************************
7918 main program
7919 ****************************************************************************/
7920 int main(int argc,char *argv[])
7922 int opt, i;
7923 char *p;
7924 int gotuser = 0;
7925 int gotpass = 0;
7926 bool correct = True;
7927 TALLOC_CTX *frame = talloc_stackframe();
7928 int seed = time(NULL);
7930 dbf = x_stdout;
7932 #ifdef HAVE_SETBUFFER
7933 setbuffer(stdout, NULL, 0);
7934 #endif
7936 load_case_tables();
7938 setup_logging("smbtorture", true);
7940 if (is_default_dyn_CONFIGFILE()) {
7941 if(getenv("SMB_CONF_PATH")) {
7942 set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
7945 lp_load(get_dyn_CONFIGFILE(),True,False,False,True);
7946 load_interfaces();
7948 if (argc < 2) {
7949 usage();
7952 for(p = argv[1]; *p; p++)
7953 if(*p == '\\')
7954 *p = '/';
7956 if (strncmp(argv[1], "//", 2)) {
7957 usage();
7960 fstrcpy(host, &argv[1][2]);
7961 p = strchr_m(&host[2],'/');
7962 if (!p) {
7963 usage();
7965 *p = 0;
7966 fstrcpy(share, p+1);
7968 fstrcpy(myname, get_myname(talloc_tos()));
7969 if (!*myname) {
7970 fprintf(stderr, "Failed to get my hostname.\n");
7971 return 1;
7974 if (*username == 0 && getenv("LOGNAME")) {
7975 fstrcpy(username,getenv("LOGNAME"));
7978 argc--;
7979 argv++;
7981 fstrcpy(workgroup, lp_workgroup());
7983 while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:")) != EOF) {
7984 switch (opt) {
7985 case 'p':
7986 port_to_use = atoi(optarg);
7987 break;
7988 case 's':
7989 seed = atoi(optarg);
7990 break;
7991 case 'W':
7992 fstrcpy(workgroup,optarg);
7993 break;
7994 case 'm':
7995 max_protocol = interpret_protocol(optarg, max_protocol);
7996 break;
7997 case 'N':
7998 nprocs = atoi(optarg);
7999 break;
8000 case 'o':
8001 torture_numops = atoi(optarg);
8002 break;
8003 case 'd':
8004 DEBUGLEVEL = atoi(optarg);
8005 break;
8006 case 'O':
8007 sockops = optarg;
8008 break;
8009 case 'L':
8010 use_oplocks = True;
8011 break;
8012 case 'l':
8013 local_path = optarg;
8014 break;
8015 case 'A':
8016 torture_showall = True;
8017 break;
8018 case 'n':
8019 fstrcpy(myname, optarg);
8020 break;
8021 case 'c':
8022 client_txt = optarg;
8023 break;
8024 case 'e':
8025 do_encrypt = true;
8026 break;
8027 case 'k':
8028 #ifdef HAVE_KRB5
8029 use_kerberos = True;
8030 #else
8031 d_printf("No kerberos support compiled in\n");
8032 exit(1);
8033 #endif
8034 break;
8035 case 'U':
8036 gotuser = 1;
8037 fstrcpy(username,optarg);
8038 p = strchr_m(username,'%');
8039 if (p) {
8040 *p = 0;
8041 fstrcpy(password, p+1);
8042 gotpass = 1;
8044 break;
8045 case 'b':
8046 fstrcpy(multishare_conn_fname, optarg);
8047 use_multishare_conn = True;
8048 break;
8049 case 'B':
8050 torture_blocksize = atoi(optarg);
8051 break;
8052 default:
8053 printf("Unknown option %c (%d)\n", (char)opt, opt);
8054 usage();
8058 d_printf("using seed %d\n", seed);
8060 srandom(seed);
8062 if(use_kerberos && !gotuser) gotpass = True;
8064 while (!gotpass) {
8065 p = getpass("Password:");
8066 if (p) {
8067 fstrcpy(password, p);
8068 gotpass = 1;
8072 printf("host=%s share=%s user=%s myname=%s\n",
8073 host, share, username, myname);
8075 if (argc == optind) {
8076 correct = run_test("ALL");
8077 } else {
8078 for (i=optind;i<argc;i++) {
8079 if (!run_test(argv[i])) {
8080 correct = False;
8085 TALLOC_FREE(frame);
8087 if (correct) {
8088 return(0);
8089 } else {
8090 return(1);