1/*
2   Unix SMB/CIFS implementation.
3   SMB torture tester
4   Copyright (C) Andrew Tridgell 1997-1998
5   Copyright (C) Jeremy Allison 2009
6
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.
11
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.
16
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/>.
19*/
20
21#include "includes.h"
22#include "nsswitch/libwbclient/wbc_async.h"
23
24extern char *optarg;
25extern int optind;
26
27static fstring host, workgroup, share, password, username, myname;
28static int max_protocol = PROTOCOL_NT1;
29static const char *sockops="TCP_NODELAY";
30static int nprocs=1;
31static int port_to_use=0;
32int torture_numops=100;
33int torture_blocksize=1024*1024;
34static int procnum; /* records process count number when forking */
35static struct cli_state *current_cli;
36static fstring randomfname;
37static bool use_oplocks;
38static bool use_level_II_oplocks;
39static const char *client_txt = "client_oplocks.txt";
40static bool use_kerberos;
41static fstring multishare_conn_fname;
42static bool use_multishare_conn = False;
43static bool do_encrypt;
44static const char *local_path = NULL;
45
46bool torture_showall = False;
47
48static double create_procs(bool (*fn)(int), bool *result);
49
50
51static struct timeval tp1,tp2;
52
53
54void start_timer(void)
55{
56	GetTimeOfDay(&tp1);
57}
58
59double end_timer(void)
60{
61	GetTimeOfDay(&tp2);
62	return((tp2.tv_sec - tp1.tv_sec) +
63	       (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
64}
65
66
67/* return a pointer to a anonymous shared memory segment of size "size"
68   which will persist across fork() but will disappear when all processes
69   exit
70
71   The memory is not zeroed
72
73   This function uses system5 shared memory. It takes advantage of a property
74   that the memory is not destroyed if it is attached when the id is removed
75   */
76void *shm_setup(int size)
77{
78	int shmid;
79	void *ret;
80
81#ifdef __QNXNTO__
82	shmid = shm_open("private", O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
83	if (shmid == -1) {
84		printf("can't get shared memory\n");
85		exit(1);
86	}
87	shm_unlink("private");
88	if (ftruncate(shmid, size) == -1) {
89		printf("can't set shared memory size\n");
90		exit(1);
91	}
92	ret = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, shmid, 0);
93	if (ret == MAP_FAILED) {
94		printf("can't map shared memory\n");
95		exit(1);
96	}
97#else
98	shmid = shmget(IPC_PRIVATE, size, S_IRUSR | S_IWUSR);
99	if (shmid == -1) {
100		printf("can't get shared memory\n");
101		exit(1);
102	}
103	ret = (void *)shmat(shmid, 0, 0);
104	if (!ret || ret == (void *)-1) {
105		printf("can't attach to shared memory\n");
106		return NULL;
107	}
108	/* the following releases the ipc, but note that this process
109	   and all its children will still have access to the memory, its
110	   just that the shmid is no longer valid for other shm calls. This
111	   means we don't leave behind lots of shm segments after we exit
112
113	   See Stevens "advanced programming in unix env" for details
114	   */
115	shmctl(shmid, IPC_RMID, 0);
116#endif
117
118	return ret;
119}
120
121/********************************************************************
122 Ensure a connection is encrypted.
123********************************************************************/
124
125static bool force_cli_encryption(struct cli_state *c,
126			const char *sharename)
127{
128	uint16 major, minor;
129	uint32 caplow, caphigh;
130	NTSTATUS status;
131
132	if (!SERVER_HAS_UNIX_CIFS(c)) {
133		d_printf("Encryption required and "
134			"server that doesn't support "
135			"UNIX extensions - failing connect\n");
136			return false;
137	}
138
139	status = cli_unix_extensions_version(c, &major, &minor, &caplow,
140					     &caphigh);
141	if (!NT_STATUS_IS_OK(status)) {
142		d_printf("Encryption required and "
143			"can't get UNIX CIFS extensions "
144			"version from server: %s\n", nt_errstr(status));
145		return false;
146	}
147
148	if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
149		d_printf("Encryption required and "
150			"share %s doesn't support "
151			"encryption.\n", sharename);
152		return false;
153	}
154
155	if (c->use_kerberos) {
156		status = cli_gss_smb_encryption_start(c);
157	} else {
158		status = cli_raw_ntlm_smb_encryption_start(c,
159						username,
160						password,
161						workgroup);
162	}
163
164	if (!NT_STATUS_IS_OK(status)) {
165		d_printf("Encryption required and "
166			"setup failed with error %s.\n",
167			nt_errstr(status));
168		return false;
169	}
170
171	return true;
172}
173
174
175static struct cli_state *open_nbt_connection(void)
176{
177	struct nmb_name called, calling;
178	struct sockaddr_storage ss;
179	struct cli_state *c;
180	NTSTATUS status;
181
182	make_nmb_name(&calling, myname, 0x0);
183	make_nmb_name(&called , host, 0x20);
184
185        zero_sockaddr(&ss);
186
187	if (!(c = cli_initialise())) {
188		printf("Failed initialize cli_struct to connect with %s\n", host);
189		return NULL;
190	}
191
192	c->port = port_to_use;
193
194	status = cli_connect(c, host, &ss);
195	if (!NT_STATUS_IS_OK(status)) {
196		printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
197		return NULL;
198	}
199
200	c->use_kerberos = use_kerberos;
201
202	c->timeout = 120000; /* set a really long timeout (2 minutes) */
203	if (use_oplocks) c->use_oplocks = True;
204	if (use_level_II_oplocks) c->use_level_II_oplocks = True;
205
206	if (!cli_session_request(c, &calling, &called)) {
207		/*
208		 * Well, that failed, try *SMBSERVER ...
209		 * However, we must reconnect as well ...
210		 */
211		status = cli_connect(c, host, &ss);
212		if (!NT_STATUS_IS_OK(status)) {
213			printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
214			return NULL;
215		}
216
217		make_nmb_name(&called, "*SMBSERVER", 0x20);
218		if (!cli_session_request(c, &calling, &called)) {
219			printf("%s rejected the session\n",host);
220			printf("We tried with a called name of %s & %s\n",
221				host, "*SMBSERVER");
222			cli_shutdown(c);
223			return NULL;
224		}
225	}
226
227	return c;
228}
229
230/* Insert a NULL at the first separator of the given path and return a pointer
231 * to the remainder of the string.
232 */
233static char *
234terminate_path_at_separator(char * path)
235{
236	char * p;
237
238	if (!path) {
239		return NULL;
240	}
241
242	if ((p = strchr_m(path, '/'))) {
243		*p = '\0';
244		return p + 1;
245	}
246
247	if ((p = strchr_m(path, '\\'))) {
248		*p = '\0';
249		return p + 1;
250	}
251
252	/* No separator. */
253	return NULL;
254}
255
256/*
257  parse a //server/share type UNC name
258*/
259bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
260		      char **hostname, char **sharename)
261{
262	char *p;
263
264	*hostname = *sharename = NULL;
265
266	if (strncmp(unc_name, "\\\\", 2) &&
267	    strncmp(unc_name, "//", 2)) {
268		return False;
269	}
270
271	*hostname = talloc_strdup(mem_ctx, &unc_name[2]);
272	p = terminate_path_at_separator(*hostname);
273
274	if (p && *p) {
275		*sharename = talloc_strdup(mem_ctx, p);
276		terminate_path_at_separator(*sharename);
277	}
278
279	if (*hostname && *sharename) {
280		return True;
281	}
282
283	TALLOC_FREE(*hostname);
284	TALLOC_FREE(*sharename);
285	return False;
286}
287
288static bool torture_open_connection_share(struct cli_state **c,
289				   const char *hostname,
290				   const char *sharename)
291{
292	bool retry;
293	int flags = 0;
294	NTSTATUS status;
295
296	if (use_kerberos)
297		flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
298	if (use_oplocks)
299		flags |= CLI_FULL_CONNECTION_OPLOCKS;
300	if (use_level_II_oplocks)
301		flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
302
303	status = cli_full_connection(c, myname,
304				     hostname, NULL, port_to_use,
305				     sharename, "?????",
306				     username, workgroup,
307				     password, flags, Undefined, &retry);
308	if (!NT_STATUS_IS_OK(status)) {
309		printf("failed to open share connection: //%s/%s port:%d - %s\n",
310			hostname, sharename, port_to_use, nt_errstr(status));
311		return False;
312	}
313
314	(*c)->timeout = 120000; /* set a really long timeout (2 minutes) */
315
316	if (do_encrypt) {
317		return force_cli_encryption(*c,
318					sharename);
319	}
320	return True;
321}
322
323bool torture_open_connection(struct cli_state **c, int conn_index)
324{
325	char **unc_list = NULL;
326	int num_unc_names = 0;
327	bool result;
328
329	if (use_multishare_conn==True) {
330		char *h, *s;
331		unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
332		if (!unc_list || num_unc_names <= 0) {
333			printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
334			exit(1);
335		}
336
337		if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
338				      NULL, &h, &s)) {
339			printf("Failed to parse UNC name %s\n",
340			       unc_list[conn_index % num_unc_names]);
341			TALLOC_FREE(unc_list);
342			exit(1);
343		}
344
345		result = torture_open_connection_share(c, h, s);
346
347		/* h, s were copied earlier */
348		TALLOC_FREE(unc_list);
349		return result;
350	}
351
352	return torture_open_connection_share(c, host, share);
353}
354
355bool torture_cli_session_setup2(struct cli_state *cli, uint16 *new_vuid)
356{
357	uint16 old_vuid = cli->vuid;
358	fstring old_user_name;
359	size_t passlen = strlen(password);
360	NTSTATUS status;
361	bool ret;
362
363	fstrcpy(old_user_name, cli->user_name);
364	cli->vuid = 0;
365	ret = NT_STATUS_IS_OK(cli_session_setup(cli, username,
366						password, passlen,
367						password, passlen,
368						workgroup));
369	*new_vuid = cli->vuid;
370	cli->vuid = old_vuid;
371	status = cli_set_username(cli, old_user_name);
372	if (!NT_STATUS_IS_OK(status)) {
373		return false;
374	}
375	return ret;
376}
377
378
379bool torture_close_connection(struct cli_state *c)
380{
381	bool ret = True;
382	if (!cli_tdis(c)) {
383		printf("tdis failed (%s)\n", cli_errstr(c));
384		ret = False;
385	}
386
387        cli_shutdown(c);
388
389	return ret;
390}
391
392
393/* check if the server produced the expected error code */
394static bool check_error(int line, struct cli_state *c,
395			uint8 eclass, uint32 ecode, NTSTATUS nterr)
396{
397        if (cli_is_dos_error(c)) {
398                uint8 cclass;
399                uint32 num;
400
401                /* Check DOS error */
402
403                cli_dos_error(c, &cclass, &num);
404
405                if (eclass != cclass || ecode != num) {
406                        printf("unexpected error code class=%d code=%d\n",
407                               (int)cclass, (int)num);
408                        printf(" expected %d/%d %s (line=%d)\n",
409                               (int)eclass, (int)ecode, nt_errstr(nterr), line);
410                        return False;
411                }
412
413        } else {
414                NTSTATUS status;
415
416                /* Check NT error */
417
418                status = cli_nt_error(c);
419
420                if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
421                        printf("unexpected error code %s\n", nt_errstr(status));
422                        printf(" expected %s (line=%d)\n", nt_errstr(nterr), line);
423                        return False;
424                }
425        }
426
427	return True;
428}
429
430
431static bool wait_lock(struct cli_state *c, int fnum, uint32 offset, uint32 len)
432{
433	while (!cli_lock(c, fnum, offset, len, -1, WRITE_LOCK)) {
434		if (!check_error(__LINE__, c, ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) return False;
435	}
436	return True;
437}
438
439
440static bool rw_torture(struct cli_state *c)
441{
442	const char *lockfname = "\\torture.lck";
443	fstring fname;
444	uint16_t fnum;
445	uint16_t fnum2;
446	pid_t pid2, pid = getpid();
447	int i, j;
448	char buf[1024];
449	bool correct = True;
450	NTSTATUS status;
451
452	memset(buf, '\0', sizeof(buf));
453
454	status = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
455			 DENY_NONE, &fnum2);
456	if (!NT_STATUS_IS_OK(status)) {
457		status = cli_open(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
458	}
459	if (!NT_STATUS_IS_OK(status)) {
460		printf("open of %s failed (%s)\n", lockfname, cli_errstr(c));
461		return False;
462	}
463
464	for (i=0;i<torture_numops;i++) {
465		unsigned n = (unsigned)sys_random()%10;
466		if (i % 10 == 0) {
467			printf("%d\r", i); fflush(stdout);
468		}
469		slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
470
471		if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
472			return False;
473		}
474
475		if (!NT_STATUS_IS_OK(cli_open(c, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL, &fnum))) {
476			printf("open failed (%s)\n", cli_errstr(c));
477			correct = False;
478			break;
479		}
480
481		if (cli_write(c, fnum, 0, (char *)&pid, 0, sizeof(pid)) != sizeof(pid)) {
482			printf("write failed (%s)\n", cli_errstr(c));
483			correct = False;
484		}
485
486		for (j=0;j<50;j++) {
487			if (cli_write(c, fnum, 0, (char *)buf,
488				      sizeof(pid)+(j*sizeof(buf)),
489				      sizeof(buf)) != sizeof(buf)) {
490				printf("write failed (%s)\n", cli_errstr(c));
491				correct = False;
492			}
493		}
494
495		pid2 = 0;
496
497		if (cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid)) != sizeof(pid)) {
498			printf("read failed (%s)\n", cli_errstr(c));
499			correct = False;
500		}
501
502		if (pid2 != pid) {
503			printf("data corruption!\n");
504			correct = False;
505		}
506
507		if (!NT_STATUS_IS_OK(cli_close(c, fnum))) {
508			printf("close failed (%s)\n", cli_errstr(c));
509			correct = False;
510		}
511
512		if (!NT_STATUS_IS_OK(cli_unlink(c, fname, aSYSTEM | aHIDDEN))) {
513			printf("unlink failed (%s)\n", cli_errstr(c));
514			correct = False;
515		}
516
517		if (!NT_STATUS_IS_OK(cli_unlock(c, fnum2, n*sizeof(int), sizeof(int)))) {
518			printf("unlock failed (%s)\n", cli_errstr(c));
519			correct = False;
520		}
521	}
522
523	cli_close(c, fnum2);
524	cli_unlink(c, lockfname, aSYSTEM | aHIDDEN);
525
526	printf("%d\n", i);
527
528	return correct;
529}
530
531static bool run_torture(int dummy)
532{
533	struct cli_state *cli;
534        bool ret;
535
536	cli = current_cli;
537
538	cli_sockopt(cli, sockops);
539
540	ret = rw_torture(cli);
541
542	if (!torture_close_connection(cli)) {
543		ret = False;
544	}
545
546	return ret;
547}
548
549static bool rw_torture3(struct cli_state *c, char *lockfname)
550{
551	uint16_t fnum = (uint16_t)-1;
552	unsigned int i = 0;
553	char buf[131072];
554	char buf_rd[131072];
555	unsigned count;
556	unsigned countprev = 0;
557	ssize_t sent = 0;
558	bool correct = True;
559	NTSTATUS status;
560
561	srandom(1);
562	for (i = 0; i < sizeof(buf); i += sizeof(uint32))
563	{
564		SIVAL(buf, i, sys_random());
565	}
566
567	if (procnum == 0)
568	{
569		if (!NT_STATUS_IS_OK(cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
570				 DENY_NONE, &fnum))) {
571			printf("first open read/write of %s failed (%s)\n",
572					lockfname, cli_errstr(c));
573			return False;
574		}
575	}
576	else
577	{
578		for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
579		{
580			status = cli_open(c, lockfname, O_RDONLY,
581					 DENY_NONE, &fnum);
582			if (!NT_STATUS_IS_OK(status)) {
583				break;
584			}
585			smb_msleep(10);
586		}
587		if (!NT_STATUS_IS_OK(status)) {
588			printf("second open read-only of %s failed (%s)\n",
589					lockfname, cli_errstr(c));
590			return False;
591		}
592	}
593
594	i = 0;
595	for (count = 0; count < sizeof(buf); count += sent)
596	{
597		if (count >= countprev) {
598			printf("%d %8d\r", i, count);
599			fflush(stdout);
600			i++;
601			countprev += (sizeof(buf) / 20);
602		}
603
604		if (procnum == 0)
605		{
606			sent = ((unsigned)sys_random()%(20))+ 1;
607			if (sent > sizeof(buf) - count)
608			{
609				sent = sizeof(buf) - count;
610			}
611
612			if (cli_write(c, fnum, 0, buf+count, count, (size_t)sent) != sent) {
613				printf("write failed (%s)\n", cli_errstr(c));
614				correct = False;
615			}
616		}
617		else
618		{
619			sent = cli_read(c, fnum, buf_rd+count, count,
620						  sizeof(buf)-count);
621			if (sent < 0)
622			{
623				printf("read failed offset:%d size:%ld (%s)\n",
624				       count, (unsigned long)sizeof(buf)-count,
625				       cli_errstr(c));
626				correct = False;
627				sent = 0;
628			}
629			if (sent > 0)
630			{
631				if (memcmp(buf_rd+count, buf+count, sent) != 0)
632				{
633					printf("read/write compare failed\n");
634					printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
635					correct = False;
636					break;
637				}
638			}
639		}
640
641	}
642
643	if (!NT_STATUS_IS_OK(cli_close(c, fnum))) {
644		printf("close failed (%s)\n", cli_errstr(c));
645		correct = False;
646	}
647
648	return correct;
649}
650
651static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
652{
653	const char *lockfname = "\\torture2.lck";
654	uint16_t fnum1;
655	uint16_t fnum2;
656	int i;
657	char buf[131072];
658	char buf_rd[131072];
659	bool correct = True;
660	ssize_t bytes_read;
661
662	if (!NT_STATUS_IS_OK(cli_unlink(c1, lockfname, aSYSTEM | aHIDDEN))) {
663		printf("unlink failed (%s) (normal, this file should not exist)\n", cli_errstr(c1));
664	}
665
666	if (!NT_STATUS_IS_OK(cli_open(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
667			 DENY_NONE, &fnum1))) {
668		printf("first open read/write of %s failed (%s)\n",
669				lockfname, cli_errstr(c1));
670		return False;
671	}
672	if (!NT_STATUS_IS_OK(cli_open(c2, lockfname, O_RDONLY,
673			 DENY_NONE, &fnum2))) {
674		printf("second open read-only of %s failed (%s)\n",
675				lockfname, cli_errstr(c2));
676		cli_close(c1, fnum1);
677		return False;
678	}
679
680	for (i=0;i<torture_numops;i++)
681	{
682		size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
683		if (i % 10 == 0) {
684			printf("%d\r", i); fflush(stdout);
685		}
686
687		generate_random_buffer((unsigned char *)buf, buf_size);
688
689		if (cli_write(c1, fnum1, 0, buf, 0, buf_size) != buf_size) {
690			printf("write failed (%s)\n", cli_errstr(c1));
691			correct = False;
692			break;
693		}
694
695		if ((bytes_read = cli_read(c2, fnum2, buf_rd, 0, buf_size)) != buf_size) {
696			printf("read failed (%s)\n", cli_errstr(c2));
697			printf("read %d, expected %ld\n", (int)bytes_read,
698			       (unsigned long)buf_size);
699			correct = False;
700			break;
701		}
702
703		if (memcmp(buf_rd, buf, buf_size) != 0)
704		{
705			printf("read/write compare failed\n");
706			correct = False;
707			break;
708		}
709	}
710
711	if (!NT_STATUS_IS_OK(cli_close(c2, fnum2))) {
712		printf("close failed (%s)\n", cli_errstr(c2));
713		correct = False;
714	}
715	if (!NT_STATUS_IS_OK(cli_close(c1, fnum1))) {
716		printf("close failed (%s)\n", cli_errstr(c1));
717		correct = False;
718	}
719
720	if (!NT_STATUS_IS_OK(cli_unlink(c1, lockfname, aSYSTEM | aHIDDEN))) {
721		printf("unlink failed (%s)\n", cli_errstr(c1));
722		correct = False;
723	}
724
725	return correct;
726}
727
728static bool run_readwritetest(int dummy)
729{
730	struct cli_state *cli1, *cli2;
731	bool test1, test2 = False;
732
733	if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
734		return False;
735	}
736	cli_sockopt(cli1, sockops);
737	cli_sockopt(cli2, sockops);
738
739	printf("starting readwritetest\n");
740
741	test1 = rw_torture2(cli1, cli2);
742	printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
743
744	if (test1) {
745		test2 = rw_torture2(cli1, cli1);
746		printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
747	}
748
749	if (!torture_close_connection(cli1)) {
750		test1 = False;
751	}
752
753	if (!torture_close_connection(cli2)) {
754		test2 = False;
755	}
756
757	return (test1 && test2);
758}
759
760static bool run_readwritemulti(int dummy)
761{
762	struct cli_state *cli;
763	bool test;
764
765	cli = current_cli;
766
767	cli_sockopt(cli, sockops);
768
769	printf("run_readwritemulti: fname %s\n", randomfname);
770	test = rw_torture3(cli, randomfname);
771
772	if (!torture_close_connection(cli)) {
773		test = False;
774	}
775
776	return test;
777}
778
779static bool run_readwritelarge(int dummy)
780{
781	static struct cli_state *cli1;
782	uint16_t fnum1;
783	const char *lockfname = "\\large.dat";
784	SMB_OFF_T fsize;
785	char buf[126*1024];
786	bool correct = True;
787
788	if (!torture_open_connection(&cli1, 0)) {
789		return False;
790	}
791	cli_sockopt(cli1, sockops);
792	memset(buf,'\0',sizeof(buf));
793
794	cli1->max_xmit = 128*1024;
795
796	printf("starting readwritelarge\n");
797
798	cli_unlink(cli1, lockfname, aSYSTEM | aHIDDEN);
799
800	if (!NT_STATUS_IS_OK(cli_open(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL, DENY_NONE, &fnum1))) {
801		printf("open read/write of %s failed (%s)\n", lockfname, cli_errstr(cli1));
802		return False;
803	}
804
805	cli_write(cli1, fnum1, 0, buf, 0, sizeof(buf));
806
807	if (!cli_qfileinfo(cli1, fnum1, NULL, &fsize, NULL, NULL, NULL, NULL, NULL)) {
808		printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
809		correct = False;
810	}
811
812	if (fsize == sizeof(buf))
813		printf("readwritelarge test 1 succeeded (size = %lx)\n",
814		       (unsigned long)fsize);
815	else {
816		printf("readwritelarge test 1 failed (size = %lx)\n",
817		       (unsigned long)fsize);
818		correct = False;
819	}
820
821	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
822		printf("close failed (%s)\n", cli_errstr(cli1));
823		correct = False;
824	}
825
826	if (!NT_STATUS_IS_OK(cli_unlink(cli1, lockfname, aSYSTEM | aHIDDEN))) {
827		printf("unlink failed (%s)\n", cli_errstr(cli1));
828		correct = False;
829	}
830
831	if (!NT_STATUS_IS_OK(cli_open(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL, DENY_NONE, &fnum1))) {
832		printf("open read/write of %s failed (%s)\n", lockfname, cli_errstr(cli1));
833		return False;
834	}
835
836	cli1->max_xmit = 4*1024;
837
838	cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf));
839
840	if (!cli_qfileinfo(cli1, fnum1, NULL, &fsize, NULL, NULL, NULL, NULL, NULL)) {
841		printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
842		correct = False;
843	}
844
845	if (fsize == sizeof(buf))
846		printf("readwritelarge test 2 succeeded (size = %lx)\n",
847		       (unsigned long)fsize);
848	else {
849		printf("readwritelarge test 2 failed (size = %lx)\n",
850		       (unsigned long)fsize);
851		correct = False;
852	}
853
854#if 0
855	/* ToDo - set allocation. JRA */
856	if(!cli_set_allocation_size(cli1, fnum1, 0)) {
857		printf("set allocation size to zero failed (%s)\n", cli_errstr(&cli1));
858		return False;
859	}
860	if (!cli_qfileinfo(cli1, fnum1, NULL, &fsize, NULL, NULL, NULL, NULL, NULL)) {
861		printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
862		correct = False;
863	}
864	if (fsize != 0)
865		printf("readwritelarge test 3 (truncate test) succeeded (size = %x)\n", fsize);
866#endif
867
868	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
869		printf("close failed (%s)\n", cli_errstr(cli1));
870		correct = False;
871	}
872
873	if (!torture_close_connection(cli1)) {
874		correct = False;
875	}
876	return correct;
877}
878
879int line_count = 0;
880int nbio_id;
881
882#define ival(s) strtol(s, NULL, 0)
883
884/* run a test that simulates an approximate netbench client load */
885static bool run_netbench(int client)
886{
887	struct cli_state *cli;
888	int i;
889	char line[1024];
890	char cname[20];
891	FILE *f;
892	const char *params[20];
893	bool correct = True;
894
895	cli = current_cli;
896
897	nbio_id = client;
898
899	cli_sockopt(cli, sockops);
900
901	nb_setup(cli);
902
903	slprintf(cname,sizeof(cname)-1, "client%d", client);
904
905	f = fopen(client_txt, "r");
906
907	if (!f) {
908		perror(client_txt);
909		return False;
910	}
911
912	while (fgets(line, sizeof(line)-1, f)) {
913		char *saveptr;
914		line_count++;
915
916		line[strlen(line)-1] = 0;
917
918		/* printf("[%d] %s\n", line_count, line); */
919
920		all_string_sub(line,"client1", cname, sizeof(line));
921
922		/* parse the command parameters */
923		params[0] = strtok_r(line, " ", &saveptr);
924		i = 0;
925		while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
926
927		params[i] = "";
928
929		if (i < 2) continue;
930
931		if (!strncmp(params[0],"SMB", 3)) {
932			printf("ERROR: You are using a dbench 1 load file\n");
933			exit(1);
934		}
935
936		if (!strcmp(params[0],"NTCreateX")) {
937			nb_createx(params[1], ival(params[2]), ival(params[3]),
938				   ival(params[4]));
939		} else if (!strcmp(params[0],"Close")) {
940			nb_close(ival(params[1]));
941		} else if (!strcmp(params[0],"Rename")) {
942			nb_rename(params[1], params[2]);
943		} else if (!strcmp(params[0],"Unlink")) {
944			nb_unlink(params[1]);
945		} else if (!strcmp(params[0],"Deltree")) {
946			nb_deltree(params[1]);
947		} else if (!strcmp(params[0],"Rmdir")) {
948			nb_rmdir(params[1]);
949		} else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
950			nb_qpathinfo(params[1]);
951		} else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
952			nb_qfileinfo(ival(params[1]));
953		} else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
954			nb_qfsinfo(ival(params[1]));
955		} else if (!strcmp(params[0],"FIND_FIRST")) {
956			nb_findfirst(params[1]);
957		} else if (!strcmp(params[0],"WriteX")) {
958			nb_writex(ival(params[1]),
959				  ival(params[2]), ival(params[3]), ival(params[4]));
960		} else if (!strcmp(params[0],"ReadX")) {
961			nb_readx(ival(params[1]),
962				  ival(params[2]), ival(params[3]), ival(params[4]));
963		} else if (!strcmp(params[0],"Flush")) {
964			nb_flush(ival(params[1]));
965		} else {
966			printf("Unknown operation %s\n", params[0]);
967			exit(1);
968		}
969	}
970	fclose(f);
971
972	nb_cleanup();
973
974	if (!torture_close_connection(cli)) {
975		correct = False;
976	}
977
978	return correct;
979}
980
981
982/* run a test that simulates an approximate netbench client load */
983static bool run_nbench(int dummy)
984{
985	double t;
986	bool correct = True;
987
988	nbio_shmem(nprocs);
989
990	nbio_id = -1;
991
992	signal(SIGALRM, nb_alarm);
993	alarm(1);
994	t = create_procs(run_netbench, &correct);
995	alarm(0);
996
997	printf("\nThroughput %g MB/sec\n",
998	       1.0e-6 * nbio_total() / t);
999	return correct;
1000}
1001
1002
1003/*
1004  This test checks for two things:
1005
1006  1) correct support for retaining locks over a close (ie. the server
1007     must not use posix semantics)
1008  2) support for lock timeouts
1009 */
1010static bool run_locktest1(int dummy)
1011{
1012	struct cli_state *cli1, *cli2;
1013	const char *fname = "\\lockt1.lck";
1014	uint16_t fnum1, fnum2, fnum3;
1015	time_t t1, t2;
1016	unsigned lock_timeout;
1017
1018	if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1019		return False;
1020	}
1021	cli_sockopt(cli1, sockops);
1022	cli_sockopt(cli2, sockops);
1023
1024	printf("starting locktest1\n");
1025
1026	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
1027
1028	if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1))) {
1029		printf("open of %s failed (%s)\n", fname, cli_errstr(cli1));
1030		return False;
1031	}
1032	if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum2))) {
1033		printf("open2 of %s failed (%s)\n", fname, cli_errstr(cli1));
1034		return False;
1035	}
1036	if (!NT_STATUS_IS_OK(cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum3))) {
1037		printf("open3 of %s failed (%s)\n", fname, cli_errstr(cli2));
1038		return False;
1039	}
1040
1041	if (!cli_lock(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) {
1042		printf("lock1 failed (%s)\n", cli_errstr(cli1));
1043		return False;
1044	}
1045
1046
1047	if (cli_lock(cli2, fnum3, 0, 4, 0, WRITE_LOCK)) {
1048		printf("lock2 succeeded! This is a locking bug\n");
1049		return False;
1050	} else {
1051		if (!check_error(__LINE__, cli2, ERRDOS, ERRlock,
1052				 NT_STATUS_LOCK_NOT_GRANTED)) return False;
1053	}
1054
1055
1056	lock_timeout = (1 + (random() % 20));
1057	printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1058	t1 = time(NULL);
1059	if (cli_lock(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK)) {
1060		printf("lock3 succeeded! This is a locking bug\n");
1061		return False;
1062	} else {
1063		if (!check_error(__LINE__, cli2, ERRDOS, ERRlock,
1064				 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
1065	}
1066	t2 = time(NULL);
1067
1068	if (ABS(t2 - t1) < lock_timeout-1) {
1069		printf("error: This server appears not to support timed lock requests\n");
1070	}
1071
1072	printf("server slept for %u seconds for a %u second timeout\n",
1073	       (unsigned int)(t2-t1), lock_timeout);
1074
1075	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
1076		printf("close1 failed (%s)\n", cli_errstr(cli1));
1077		return False;
1078	}
1079
1080	if (cli_lock(cli2, fnum3, 0, 4, 0, WRITE_LOCK)) {
1081		printf("lock4 succeeded! This is a locking bug\n");
1082		return False;
1083	} else {
1084		if (!check_error(__LINE__, cli2, ERRDOS, ERRlock,
1085				 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
1086	}
1087
1088	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
1089		printf("close2 failed (%s)\n", cli_errstr(cli1));
1090		return False;
1091	}
1092
1093	if (!NT_STATUS_IS_OK(cli_close(cli2, fnum3))) {
1094		printf("close3 failed (%s)\n", cli_errstr(cli2));
1095		return False;
1096	}
1097
1098	if (!NT_STATUS_IS_OK(cli_unlink(cli1, fname, aSYSTEM | aHIDDEN))) {
1099		printf("unlink failed (%s)\n", cli_errstr(cli1));
1100		return False;
1101	}
1102
1103
1104	if (!torture_close_connection(cli1)) {
1105		return False;
1106	}
1107
1108	if (!torture_close_connection(cli2)) {
1109		return False;
1110	}
1111
1112	printf("Passed locktest1\n");
1113	return True;
1114}
1115
1116/*
1117  this checks to see if a secondary tconx can use open files from an
1118  earlier tconx
1119 */
1120static bool run_tcon_test(int dummy)
1121{
1122	static struct cli_state *cli;
1123	const char *fname = "\\tcontest.tmp";
1124	uint16 fnum1;
1125	uint16 cnum1, cnum2, cnum3;
1126	uint16 vuid1, vuid2;
1127	char buf[4];
1128	bool ret = True;
1129	NTSTATUS status;
1130
1131	memset(buf, '\0', sizeof(buf));
1132
1133	if (!torture_open_connection(&cli, 0)) {
1134		return False;
1135	}
1136	cli_sockopt(cli, sockops);
1137
1138	printf("starting tcontest\n");
1139
1140	cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
1141
1142	if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1))) {
1143		printf("open of %s failed (%s)\n", fname, cli_errstr(cli));
1144		return False;
1145	}
1146
1147	cnum1 = cli->cnum;
1148	vuid1 = cli->vuid;
1149
1150	if (cli_write(cli, fnum1, 0, buf, 130, 4) != 4) {
1151		printf("initial write failed (%s)", cli_errstr(cli));
1152		return False;
1153	}
1154
1155	status = cli_tcon_andx(cli, share, "?????",
1156			       password, strlen(password)+1);
1157	if (!NT_STATUS_IS_OK(status)) {
1158		printf("%s refused 2nd tree connect (%s)\n", host,
1159		       nt_errstr(status));
1160		cli_shutdown(cli);
1161		return False;
1162	}
1163
1164	cnum2 = cli->cnum;
1165	cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1166	vuid2 = cli->vuid + 1;
1167
1168	/* try a write with the wrong tid */
1169	cli->cnum = cnum2;
1170
1171	if (cli_write(cli, fnum1, 0, buf, 130, 4) == 4) {
1172		printf("* server allows write with wrong TID\n");
1173		ret = False;
1174	} else {
1175		printf("server fails write with wrong TID : %s\n", cli_errstr(cli));
1176	}
1177
1178
1179	/* try a write with an invalid tid */
1180	cli->cnum = cnum3;
1181
1182	if (cli_write(cli, fnum1, 0, buf, 130, 4) == 4) {
1183		printf("* server allows write with invalid TID\n");
1184		ret = False;
1185	} else {
1186		printf("server fails write with invalid TID : %s\n", cli_errstr(cli));
1187	}
1188
1189	/* try a write with an invalid vuid */
1190	cli->vuid = vuid2;
1191	cli->cnum = cnum1;
1192
1193	if (cli_write(cli, fnum1, 0, buf, 130, 4) == 4) {
1194		printf("* server allows write with invalid VUID\n");
1195		ret = False;
1196	} else {
1197		printf("server fails write with invalid VUID : %s\n", cli_errstr(cli));
1198	}
1199
1200	cli->cnum = cnum1;
1201	cli->vuid = vuid1;
1202
1203	if (!NT_STATUS_IS_OK(cli_close(cli, fnum1))) {
1204		printf("close failed (%s)\n", cli_errstr(cli));
1205		return False;
1206	}
1207
1208	cli->cnum = cnum2;
1209
1210	if (!cli_tdis(cli)) {
1211		printf("secondary tdis failed (%s)\n", cli_errstr(cli));
1212		return False;
1213	}
1214
1215	cli->cnum = cnum1;
1216
1217	if (!torture_close_connection(cli)) {
1218		return False;
1219	}
1220
1221	return ret;
1222}
1223
1224
1225/*
1226 checks for old style tcon support
1227 */
1228static bool run_tcon2_test(int dummy)
1229{
1230	static struct cli_state *cli;
1231	uint16 cnum, max_xmit;
1232	char *service;
1233	NTSTATUS status;
1234
1235	if (!torture_open_connection(&cli, 0)) {
1236		return False;
1237	}
1238	cli_sockopt(cli, sockops);
1239
1240	printf("starting tcon2 test\n");
1241
1242	if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1243		return false;
1244	}
1245
1246	status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1247
1248	if (!NT_STATUS_IS_OK(status)) {
1249		printf("tcon2 failed : %s\n", cli_errstr(cli));
1250	} else {
1251		printf("tcon OK : max_xmit=%d cnum=%d tid=%d\n",
1252		       (int)max_xmit, (int)cnum, SVAL(cli->inbuf, smb_tid));
1253	}
1254
1255	if (!torture_close_connection(cli)) {
1256		return False;
1257	}
1258
1259	printf("Passed tcon2 test\n");
1260	return True;
1261}
1262
1263static bool tcon_devtest(struct cli_state *cli,
1264			 const char *myshare, const char *devtype,
1265			 const char *return_devtype,
1266			 NTSTATUS expected_error)
1267{
1268	NTSTATUS status;
1269	bool ret;
1270
1271	status = cli_tcon_andx(cli, myshare, devtype,
1272			       password, strlen(password)+1);
1273
1274	if (NT_STATUS_IS_OK(expected_error)) {
1275		if (NT_STATUS_IS_OK(status)) {
1276			if (strcmp(cli->dev, return_devtype) == 0) {
1277				ret = True;
1278			} else {
1279				printf("tconX to share %s with type %s "
1280				       "succeeded but returned the wrong "
1281				       "device type (got [%s] but should have got [%s])\n",
1282				       myshare, devtype, cli->dev, return_devtype);
1283				ret = False;
1284			}
1285		} else {
1286			printf("tconX to share %s with type %s "
1287			       "should have succeeded but failed\n",
1288			       myshare, devtype);
1289			ret = False;
1290		}
1291		cli_tdis(cli);
1292	} else {
1293		if (NT_STATUS_IS_OK(status)) {
1294			printf("tconx to share %s with type %s "
1295			       "should have failed but succeeded\n",
1296			       myshare, devtype);
1297			ret = False;
1298		} else {
1299			if (NT_STATUS_EQUAL(cli_nt_error(cli),
1300					    expected_error)) {
1301				ret = True;
1302			} else {
1303				printf("Returned unexpected error\n");
1304				ret = False;
1305			}
1306		}
1307	}
1308	return ret;
1309}
1310
1311/*
1312 checks for correct tconX support
1313 */
1314static bool run_tcon_devtype_test(int dummy)
1315{
1316	static struct cli_state *cli1 = NULL;
1317	bool retry;
1318	int flags = 0;
1319	NTSTATUS status;
1320	bool ret = True;
1321
1322	status = cli_full_connection(&cli1, myname,
1323				     host, NULL, port_to_use,
1324				     NULL, NULL,
1325				     username, workgroup,
1326				     password, flags, Undefined, &retry);
1327
1328	if (!NT_STATUS_IS_OK(status)) {
1329		printf("could not open connection\n");
1330		return False;
1331	}
1332
1333	if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1334		ret = False;
1335
1336	if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1337		ret = False;
1338
1339	if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1340		ret = False;
1341
1342	if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1343		ret = False;
1344
1345	if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1346		ret = False;
1347
1348	if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1349		ret = False;
1350
1351	if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1352		ret = False;
1353
1354	if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1355		ret = False;
1356
1357	if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1358		ret = False;
1359
1360	if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1361		ret = False;
1362
1363	cli_shutdown(cli1);
1364
1365	if (ret)
1366		printf("Passed tcondevtest\n");
1367
1368	return ret;
1369}
1370
1371
1372/*
1373  This test checks that
1374
1375  1) the server supports multiple locking contexts on the one SMB
1376  connection, distinguished by PID.
1377
1378  2) the server correctly fails overlapping locks made by the same PID (this
1379     goes against POSIX behaviour, which is why it is tricky to implement)
1380
1381  3) the server denies unlock requests by an incorrect client PID
1382*/
1383static bool run_locktest2(int dummy)
1384{
1385	static struct cli_state *cli;
1386	const char *fname = "\\lockt2.lck";
1387	uint16_t fnum1, fnum2, fnum3;
1388	bool correct = True;
1389
1390	if (!torture_open_connection(&cli, 0)) {
1391		return False;
1392	}
1393
1394	cli_sockopt(cli, sockops);
1395
1396	printf("starting locktest2\n");
1397
1398	cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
1399
1400	cli_setpid(cli, 1);
1401
1402	if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1))) {
1403		printf("open of %s failed (%s)\n", fname, cli_errstr(cli));
1404		return False;
1405	}
1406
1407	if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum2))) {
1408		printf("open2 of %s failed (%s)\n", fname, cli_errstr(cli));
1409		return False;
1410	}
1411
1412	cli_setpid(cli, 2);
1413
1414	if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum3))) {
1415		printf("open3 of %s failed (%s)\n", fname, cli_errstr(cli));
1416		return False;
1417	}
1418
1419	cli_setpid(cli, 1);
1420
1421	if (!cli_lock(cli, fnum1, 0, 4, 0, WRITE_LOCK)) {
1422		printf("lock1 failed (%s)\n", cli_errstr(cli));
1423		return False;
1424	}
1425
1426	if (cli_lock(cli, fnum1, 0, 4, 0, WRITE_LOCK)) {
1427		printf("WRITE lock1 succeeded! This is a locking bug\n");
1428		correct = False;
1429	} else {
1430		if (!check_error(__LINE__, cli, ERRDOS, ERRlock,
1431				 NT_STATUS_LOCK_NOT_GRANTED)) return False;
1432	}
1433
1434	if (cli_lock(cli, fnum2, 0, 4, 0, WRITE_LOCK)) {
1435		printf("WRITE lock2 succeeded! This is a locking bug\n");
1436		correct = False;
1437	} else {
1438		if (!check_error(__LINE__, cli, ERRDOS, ERRlock,
1439				 NT_STATUS_LOCK_NOT_GRANTED)) return False;
1440	}
1441
1442	if (cli_lock(cli, fnum2, 0, 4, 0, READ_LOCK)) {
1443		printf("READ lock2 succeeded! This is a locking bug\n");
1444		correct = False;
1445	} else {
1446		if (!check_error(__LINE__, cli, ERRDOS, ERRlock,
1447				 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
1448	}
1449
1450	if (!cli_lock(cli, fnum1, 100, 4, 0, WRITE_LOCK)) {
1451		printf("lock at 100 failed (%s)\n", cli_errstr(cli));
1452	}
1453	cli_setpid(cli, 2);
1454	if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1455		printf("unlock at 100 succeeded! This is a locking bug\n");
1456		correct = False;
1457	}
1458
1459	if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 0, 4))) {
1460		printf("unlock1 succeeded! This is a locking bug\n");
1461		correct = False;
1462	} else {
1463		if (!check_error(__LINE__, cli,
1464				 ERRDOS, ERRlock,
1465				 NT_STATUS_RANGE_NOT_LOCKED)) return False;
1466	}
1467
1468	if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 0, 8))) {
1469		printf("unlock2 succeeded! This is a locking bug\n");
1470		correct = False;
1471	} else {
1472		if (!check_error(__LINE__, cli,
1473				 ERRDOS, ERRlock,
1474				 NT_STATUS_RANGE_NOT_LOCKED)) return False;
1475	}
1476
1477	if (cli_lock(cli, fnum3, 0, 4, 0, WRITE_LOCK)) {
1478		printf("lock3 succeeded! This is a locking bug\n");
1479		correct = False;
1480	} else {
1481		if (!check_error(__LINE__, cli, ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) return False;
1482	}
1483
1484	cli_setpid(cli, 1);
1485
1486	if (!NT_STATUS_IS_OK(cli_close(cli, fnum1))) {
1487		printf("close1 failed (%s)\n", cli_errstr(cli));
1488		return False;
1489	}
1490
1491	if (!NT_STATUS_IS_OK(cli_close(cli, fnum2))) {
1492		printf("close2 failed (%s)\n", cli_errstr(cli));
1493		return False;
1494	}
1495
1496	if (!NT_STATUS_IS_OK(cli_close(cli, fnum3))) {
1497		printf("close3 failed (%s)\n", cli_errstr(cli));
1498		return False;
1499	}
1500
1501	if (!torture_close_connection(cli)) {
1502		correct = False;
1503	}
1504
1505	printf("locktest2 finished\n");
1506
1507	return correct;
1508}
1509
1510
1511/*
1512  This test checks that
1513
1514  1) the server supports the full offset range in lock requests
1515*/
1516static bool run_locktest3(int dummy)
1517{
1518	static struct cli_state *cli1, *cli2;
1519	const char *fname = "\\lockt3.lck";
1520	uint16_t fnum1, fnum2;
1521	int i;
1522	uint32 offset;
1523	bool correct = True;
1524
1525#define NEXT_OFFSET offset += (~(uint32)0) / torture_numops
1526
1527	if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1528		return False;
1529	}
1530	cli_sockopt(cli1, sockops);
1531	cli_sockopt(cli2, sockops);
1532
1533	printf("starting locktest3\n");
1534
1535	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
1536
1537	if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1))) {
1538		printf("open of %s failed (%s)\n", fname, cli_errstr(cli1));
1539		return False;
1540	}
1541	if (!NT_STATUS_IS_OK(cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2))) {
1542		printf("open2 of %s failed (%s)\n", fname, cli_errstr(cli2));
1543		return False;
1544	}
1545
1546	for (offset=i=0;i<torture_numops;i++) {
1547		NEXT_OFFSET;
1548		if (!cli_lock(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
1549			printf("lock1 %d failed (%s)\n",
1550			       i,
1551			       cli_errstr(cli1));
1552			return False;
1553		}
1554
1555		if (!cli_lock(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK)) {
1556			printf("lock2 %d failed (%s)\n",
1557			       i,
1558			       cli_errstr(cli1));
1559			return False;
1560		}
1561	}
1562
1563	for (offset=i=0;i<torture_numops;i++) {
1564		NEXT_OFFSET;
1565
1566		if (cli_lock(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK)) {
1567			printf("error: lock1 %d succeeded!\n", i);
1568			return False;
1569		}
1570
1571		if (cli_lock(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK)) {
1572			printf("error: lock2 %d succeeded!\n", i);
1573			return False;
1574		}
1575
1576		if (cli_lock(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
1577			printf("error: lock3 %d succeeded!\n", i);
1578			return False;
1579		}
1580
1581		if (cli_lock(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK)) {
1582			printf("error: lock4 %d succeeded!\n", i);
1583			return False;
1584		}
1585	}
1586
1587	for (offset=i=0;i<torture_numops;i++) {
1588		NEXT_OFFSET;
1589
1590		if (!NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, offset-1, 1))) {
1591			printf("unlock1 %d failed (%s)\n",
1592			       i,
1593			       cli_errstr(cli1));
1594			return False;
1595		}
1596
1597		if (!NT_STATUS_IS_OK(cli_unlock(cli2, fnum2, offset-2, 1))) {
1598			printf("unlock2 %d failed (%s)\n",
1599			       i,
1600			       cli_errstr(cli1));
1601			return False;
1602		}
1603	}
1604
1605	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
1606		printf("close1 failed (%s)\n", cli_errstr(cli1));
1607		return False;
1608	}
1609
1610	if (!NT_STATUS_IS_OK(cli_close(cli2, fnum2))) {
1611		printf("close2 failed (%s)\n", cli_errstr(cli2));
1612		return False;
1613	}
1614
1615	if (!NT_STATUS_IS_OK(cli_unlink(cli1, fname, aSYSTEM | aHIDDEN))) {
1616		printf("unlink failed (%s)\n", cli_errstr(cli1));
1617		return False;
1618	}
1619
1620	if (!torture_close_connection(cli1)) {
1621		correct = False;
1622	}
1623
1624	if (!torture_close_connection(cli2)) {
1625		correct = False;
1626	}
1627
1628	printf("finished locktest3\n");
1629
1630	return correct;
1631}
1632
1633#define EXPECTED(ret, v) if ((ret) != (v)) { \
1634        printf("** "); correct = False; \
1635        }
1636
1637/*
1638  looks at overlapping locks
1639*/
1640static bool run_locktest4(int dummy)
1641{
1642	static struct cli_state *cli1, *cli2;
1643	const char *fname = "\\lockt4.lck";
1644	uint16_t fnum1, fnum2, f;
1645	bool ret;
1646	char buf[1000];
1647	bool correct = True;
1648
1649	if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1650		return False;
1651	}
1652
1653	cli_sockopt(cli1, sockops);
1654	cli_sockopt(cli2, sockops);
1655
1656	printf("starting locktest4\n");
1657
1658	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
1659
1660	cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1661	cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1662
1663	memset(buf, 0, sizeof(buf));
1664
1665	if (cli_write(cli1, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
1666		printf("Failed to create file\n");
1667		correct = False;
1668		goto fail;
1669	}
1670
1671	ret = cli_lock(cli1, fnum1, 0, 4, 0, WRITE_LOCK) &&
1672	      cli_lock(cli1, fnum1, 2, 4, 0, WRITE_LOCK);
1673	EXPECTED(ret, False);
1674	printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1675
1676	ret = cli_lock(cli1, fnum1, 10, 4, 0, READ_LOCK) &&
1677	      cli_lock(cli1, fnum1, 12, 4, 0, READ_LOCK);
1678	EXPECTED(ret, True);
1679	printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1680
1681	ret = cli_lock(cli1, fnum1, 20, 4, 0, WRITE_LOCK) &&
1682	      cli_lock(cli2, fnum2, 22, 4, 0, WRITE_LOCK);
1683	EXPECTED(ret, False);
1684	printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1685
1686	ret = cli_lock(cli1, fnum1, 30, 4, 0, READ_LOCK) &&
1687	      cli_lock(cli2, fnum2, 32, 4, 0, READ_LOCK);
1688	EXPECTED(ret, True);
1689	printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1690
1691	ret = (cli_setpid(cli1, 1), cli_lock(cli1, fnum1, 40, 4, 0, WRITE_LOCK)) &&
1692	      (cli_setpid(cli1, 2), cli_lock(cli1, fnum1, 42, 4, 0, WRITE_LOCK));
1693	EXPECTED(ret, False);
1694	printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1695
1696	ret = (cli_setpid(cli1, 1), cli_lock(cli1, fnum1, 50, 4, 0, READ_LOCK)) &&
1697	      (cli_setpid(cli1, 2), cli_lock(cli1, fnum1, 52, 4, 0, READ_LOCK));
1698	EXPECTED(ret, True);
1699	printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1700
1701	ret = cli_lock(cli1, fnum1, 60, 4, 0, READ_LOCK) &&
1702	      cli_lock(cli1, fnum1, 60, 4, 0, READ_LOCK);
1703	EXPECTED(ret, True);
1704	printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1705
1706	ret = cli_lock(cli1, fnum1, 70, 4, 0, WRITE_LOCK) &&
1707	      cli_lock(cli1, fnum1, 70, 4, 0, WRITE_LOCK);
1708	EXPECTED(ret, False);
1709	printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1710
1711	ret = cli_lock(cli1, fnum1, 80, 4, 0, READ_LOCK) &&
1712	      cli_lock(cli1, fnum1, 80, 4, 0, WRITE_LOCK);
1713	EXPECTED(ret, False);
1714	printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
1715
1716	ret = cli_lock(cli1, fnum1, 90, 4, 0, WRITE_LOCK) &&
1717	      cli_lock(cli1, fnum1, 90, 4, 0, READ_LOCK);
1718	EXPECTED(ret, True);
1719	printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1720
1721	ret = (cli_setpid(cli1, 1), cli_lock(cli1, fnum1, 100, 4, 0, WRITE_LOCK)) &&
1722	      (cli_setpid(cli1, 2), cli_lock(cli1, fnum1, 100, 4, 0, READ_LOCK));
1723	EXPECTED(ret, False);
1724	printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1725
1726	ret = cli_lock(cli1, fnum1, 110, 4, 0, READ_LOCK) &&
1727	      cli_lock(cli1, fnum1, 112, 4, 0, READ_LOCK) &&
1728	      NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
1729	EXPECTED(ret, False);
1730	printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
1731
1732
1733	ret = cli_lock(cli1, fnum1, 120, 4, 0, WRITE_LOCK) &&
1734	      (cli_read(cli2, fnum2, buf, 120, 4) == 4);
1735	EXPECTED(ret, False);
1736	printf("this server %s strict write locking\n", ret?"doesn't do":"does");
1737
1738	ret = cli_lock(cli1, fnum1, 130, 4, 0, READ_LOCK) &&
1739	      (cli_write(cli2, fnum2, 0, buf, 130, 4) == 4);
1740	EXPECTED(ret, False);
1741	printf("this server %s strict read locking\n", ret?"doesn't do":"does");
1742
1743
1744	ret = cli_lock(cli1, fnum1, 140, 4, 0, READ_LOCK) &&
1745	      cli_lock(cli1, fnum1, 140, 4, 0, READ_LOCK) &&
1746	      NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
1747	      NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
1748	EXPECTED(ret, True);
1749	printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
1750
1751
1752	ret = cli_lock(cli1, fnum1, 150, 4, 0, WRITE_LOCK) &&
1753	      cli_lock(cli1, fnum1, 150, 4, 0, READ_LOCK) &&
1754	      NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
1755	      (cli_read(cli2, fnum2, buf, 150, 4) == 4) &&
1756	      !(cli_write(cli2, fnum2, 0, buf, 150, 4) == 4) &&
1757	      NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
1758	EXPECTED(ret, True);
1759	printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
1760
1761	ret = cli_lock(cli1, fnum1, 160, 4, 0, READ_LOCK) &&
1762	      NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
1763	      (cli_write(cli2, fnum2, 0, buf, 160, 4) == 4) &&
1764	      (cli_read(cli2, fnum2, buf, 160, 4) == 4);
1765	EXPECTED(ret, True);
1766	printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
1767
1768	ret = cli_lock(cli1, fnum1, 170, 4, 0, WRITE_LOCK) &&
1769	      NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
1770	      (cli_write(cli2, fnum2, 0, buf, 170, 4) == 4) &&
1771	      (cli_read(cli2, fnum2, buf, 170, 4) == 4);
1772	EXPECTED(ret, True);
1773	printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
1774
1775	ret = cli_lock(cli1, fnum1, 190, 4, 0, WRITE_LOCK) &&
1776	      cli_lock(cli1, fnum1, 190, 4, 0, READ_LOCK) &&
1777	      NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
1778	      !(cli_write(cli2, fnum2, 0, buf, 190, 4) == 4) &&
1779	      (cli_read(cli2, fnum2, buf, 190, 4) == 4);
1780	EXPECTED(ret, True);
1781	printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
1782
1783	cli_close(cli1, fnum1);
1784	cli_close(cli2, fnum2);
1785	cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
1786	cli_open(cli1, fname, O_RDWR, DENY_NONE, &f);
1787	ret = cli_lock(cli1, fnum1, 0, 8, 0, READ_LOCK) &&
1788	      cli_lock(cli1, f, 0, 1, 0, READ_LOCK) &&
1789	      NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
1790	      NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
1791	      cli_lock(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
1792        cli_close(cli1, f);
1793	cli_close(cli1, fnum1);
1794	EXPECTED(ret, True);
1795	printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
1796
1797 fail:
1798	cli_close(cli1, fnum1);
1799	cli_close(cli2, fnum2);
1800	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
1801	torture_close_connection(cli1);
1802	torture_close_connection(cli2);
1803
1804	printf("finished locktest4\n");
1805	return correct;
1806}
1807
1808/*
1809  looks at lock upgrade/downgrade.
1810*/
1811static bool run_locktest5(int dummy)
1812{
1813	static struct cli_state *cli1, *cli2;
1814	const char *fname = "\\lockt5.lck";
1815	uint16_t fnum1, fnum2, fnum3;
1816	bool ret;
1817	char buf[1000];
1818	bool correct = True;
1819
1820	if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1821		return False;
1822	}
1823
1824	cli_sockopt(cli1, sockops);
1825	cli_sockopt(cli2, sockops);
1826
1827	printf("starting locktest5\n");
1828
1829	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
1830
1831	cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1832	cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1833	cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
1834
1835	memset(buf, 0, sizeof(buf));
1836
1837	if (cli_write(cli1, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
1838		printf("Failed to create file\n");
1839		correct = False;
1840		goto fail;
1841	}
1842
1843	/* Check for NT bug... */
1844	ret = cli_lock(cli1, fnum1, 0, 8, 0, READ_LOCK) &&
1845		  cli_lock(cli1, fnum3, 0, 1, 0, READ_LOCK);
1846	cli_close(cli1, fnum1);
1847	cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
1848	ret = cli_lock(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
1849	EXPECTED(ret, True);
1850	printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
1851	cli_close(cli1, fnum1);
1852	cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
1853	cli_unlock(cli1, fnum3, 0, 1);
1854
1855	ret = cli_lock(cli1, fnum1, 0, 4, 0, WRITE_LOCK) &&
1856	      cli_lock(cli1, fnum1, 1, 1, 0, READ_LOCK);
1857	EXPECTED(ret, True);
1858	printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
1859
1860	ret = cli_lock(cli2, fnum2, 0, 4, 0, READ_LOCK);
1861	EXPECTED(ret, False);
1862
1863	printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
1864
1865	/* Unlock the process 2 lock. */
1866	cli_unlock(cli2, fnum2, 0, 4);
1867
1868	ret = cli_lock(cli1, fnum3, 0, 4, 0, READ_LOCK);
1869	EXPECTED(ret, False);
1870
1871	printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
1872
1873	/* Unlock the process 1 fnum3 lock. */
1874	cli_unlock(cli1, fnum3, 0, 4);
1875
1876	/* Stack 2 more locks here. */
1877	ret = cli_lock(cli1, fnum1, 0, 4, 0, READ_LOCK) &&
1878		  cli_lock(cli1, fnum1, 0, 4, 0, READ_LOCK);
1879
1880	EXPECTED(ret, True);
1881	printf("the same process %s stack read locks\n", ret?"can":"cannot");
1882
1883	/* Unlock the first process lock, then check this was the WRITE lock that was
1884		removed. */
1885
1886	ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
1887			cli_lock(cli2, fnum2, 0, 4, 0, READ_LOCK);
1888
1889	EXPECTED(ret, True);
1890	printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
1891
1892	/* Unlock the process 2 lock. */
1893	cli_unlock(cli2, fnum2, 0, 4);
1894
1895	/* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
1896
1897	ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
1898		  NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
1899		  NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
1900
1901	EXPECTED(ret, True);
1902	printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
1903
1904	/* Ensure the next unlock fails. */
1905	ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
1906	EXPECTED(ret, False);
1907	printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
1908
1909	/* Ensure connection 2 can get a write lock. */
1910	ret = cli_lock(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
1911	EXPECTED(ret, True);
1912
1913	printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
1914
1915
1916 fail:
1917	cli_close(cli1, fnum1);
1918	cli_close(cli2, fnum2);
1919	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
1920	if (!torture_close_connection(cli1)) {
1921		correct = False;
1922	}
1923	if (!torture_close_connection(cli2)) {
1924		correct = False;
1925	}
1926
1927	printf("finished locktest5\n");
1928
1929	return correct;
1930}
1931
1932/*
1933  tries the unusual lockingX locktype bits
1934*/
1935static bool run_locktest6(int dummy)
1936{
1937	static struct cli_state *cli;
1938	const char *fname[1] = { "\\lock6.txt" };
1939	int i;
1940	uint16_t fnum;
1941	NTSTATUS status;
1942
1943	if (!torture_open_connection(&cli, 0)) {
1944		return False;
1945	}
1946
1947	cli_sockopt(cli, sockops);
1948
1949	printf("starting locktest6\n");
1950
1951	for (i=0;i<1;i++) {
1952		printf("Testing %s\n", fname[i]);
1953
1954		cli_unlink(cli, fname[i], aSYSTEM | aHIDDEN);
1955
1956		cli_open(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
1957		status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
1958		cli_close(cli, fnum);
1959		printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
1960
1961		cli_open(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
1962		status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
1963		cli_close(cli, fnum);
1964		printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
1965
1966		cli_unlink(cli, fname[i], aSYSTEM | aHIDDEN);
1967	}
1968
1969	torture_close_connection(cli);
1970
1971	printf("finished locktest6\n");
1972	return True;
1973}
1974
1975static bool run_locktest7(int dummy)
1976{
1977	struct cli_state *cli1;
1978	const char *fname = "\\lockt7.lck";
1979	uint16_t fnum1;
1980	char buf[200];
1981	bool correct = False;
1982
1983	if (!torture_open_connection(&cli1, 0)) {
1984		return False;
1985	}
1986
1987	cli_sockopt(cli1, sockops);
1988
1989	printf("starting locktest7\n");
1990
1991	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
1992
1993	cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1994
1995	memset(buf, 0, sizeof(buf));
1996
1997	if (cli_write(cli1, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
1998		printf("Failed to create file\n");
1999		goto fail;
2000	}
2001
2002	cli_setpid(cli1, 1);
2003
2004	if (!cli_lock(cli1, fnum1, 130, 4, 0, READ_LOCK)) {
2005		printf("Unable to apply read lock on range 130:4, error was %s\n", cli_errstr(cli1));
2006		goto fail;
2007	} else {
2008		printf("pid1 successfully locked range 130:4 for READ\n");
2009	}
2010
2011	if (cli_read(cli1, fnum1, buf, 130, 4) != 4) {
2012		printf("pid1 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2013		goto fail;
2014	} else {
2015		printf("pid1 successfully read the range 130:4\n");
2016	}
2017
2018	if (cli_write(cli1, fnum1, 0, buf, 130, 4) != 4) {
2019		printf("pid1 unable to write to the range 130:4, error was %s\n", cli_errstr(cli1));
2020		if (NT_STATUS_V(cli_nt_error(cli1)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
2021			printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2022			goto fail;
2023		}
2024	} else {
2025		printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2026		goto fail;
2027	}
2028
2029	cli_setpid(cli1, 2);
2030
2031	if (cli_read(cli1, fnum1, buf, 130, 4) != 4) {
2032		printf("pid2 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2033	} else {
2034		printf("pid2 successfully read the range 130:4\n");
2035	}
2036
2037	if (cli_write(cli1, fnum1, 0, buf, 130, 4) != 4) {
2038		printf("pid2 unable to write to the range 130:4, error was %s\n", cli_errstr(cli1));
2039		if (NT_STATUS_V(cli_nt_error(cli1)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
2040			printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2041			goto fail;
2042		}
2043	} else {
2044		printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2045		goto fail;
2046	}
2047
2048	cli_setpid(cli1, 1);
2049	cli_unlock(cli1, fnum1, 130, 4);
2050
2051	if (!cli_lock(cli1, fnum1, 130, 4, 0, WRITE_LOCK)) {
2052		printf("Unable to apply write lock on range 130:4, error was %s\n", cli_errstr(cli1));
2053		goto fail;
2054	} else {
2055		printf("pid1 successfully locked range 130:4 for WRITE\n");
2056	}
2057
2058	if (cli_read(cli1, fnum1, buf, 130, 4) != 4) {
2059		printf("pid1 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2060		goto fail;
2061	} else {
2062		printf("pid1 successfully read the range 130:4\n");
2063	}
2064
2065	if (cli_write(cli1, fnum1, 0, buf, 130, 4) != 4) {
2066		printf("pid1 unable to write to the range 130:4, error was %s\n", cli_errstr(cli1));
2067		goto fail;
2068	} else {
2069		printf("pid1 successfully wrote to the range 130:4\n");
2070	}
2071
2072	cli_setpid(cli1, 2);
2073
2074	if (cli_read(cli1, fnum1, buf, 130, 4) != 4) {
2075		printf("pid2 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2076		if (NT_STATUS_V(cli_nt_error(cli1)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
2077			printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2078			goto fail;
2079		}
2080	} else {
2081		printf("pid2 successfully read the range 130:4 (should be denied)\n");
2082		goto fail;
2083	}
2084
2085	if (cli_write(cli1, fnum1, 0, buf, 130, 4) != 4) {
2086		printf("pid2 unable to write to the range 130:4, error was %s\n", cli_errstr(cli1));
2087		if (NT_STATUS_V(cli_nt_error(cli1)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
2088			printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2089			goto fail;
2090		}
2091	} else {
2092		printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2093		goto fail;
2094	}
2095
2096	cli_unlock(cli1, fnum1, 130, 0);
2097	correct = True;
2098
2099fail:
2100	cli_close(cli1, fnum1);
2101	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
2102	torture_close_connection(cli1);
2103
2104	printf("finished locktest7\n");
2105	return correct;
2106}
2107
2108/*
2109 * This demonstrates a problem with our use of GPFS share modes: A file
2110 * descriptor sitting in the pending close queue holding a GPFS share mode
2111 * blocks opening a file another time. Happens with Word 2007 temp files.
2112 * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2113 * open is denied with NT_STATUS_SHARING_VIOLATION.
2114 */
2115
2116static bool run_locktest8(int dummy)
2117{
2118	struct cli_state *cli1;
2119	const char *fname = "\\lockt8.lck";
2120	uint16_t fnum1, fnum2;
2121	char buf[200];
2122	bool correct = False;
2123	NTSTATUS status;
2124
2125	if (!torture_open_connection(&cli1, 0)) {
2126		return False;
2127	}
2128
2129	cli_sockopt(cli1, sockops);
2130
2131	printf("starting locktest8\n");
2132
2133	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
2134
2135	status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2136			  &fnum1);
2137	if (!NT_STATUS_IS_OK(status)) {
2138		d_fprintf(stderr, "cli_open returned %s\n", cli_errstr(cli1));
2139		return false;
2140	}
2141
2142	memset(buf, 0, sizeof(buf));
2143
2144	status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2145	if (!NT_STATUS_IS_OK(status)) {
2146		d_fprintf(stderr, "cli_open second time returned %s\n",
2147			  cli_errstr(cli1));
2148		goto fail;
2149	}
2150
2151	if (!cli_lock(cli1, fnum2, 1, 1, 0, READ_LOCK)) {
2152		printf("Unable to apply read lock on range 1:1, error was "
2153		       "%s\n", cli_errstr(cli1));
2154		goto fail;
2155	}
2156
2157	status = cli_close(cli1, fnum1);
2158	if (!NT_STATUS_IS_OK(status)) {
2159		d_fprintf(stderr, "cli_close(fnum1) %s\n", cli_errstr(cli1));
2160		goto fail;
2161	}
2162
2163	status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2164	if (!NT_STATUS_IS_OK(status)) {
2165		d_fprintf(stderr, "cli_open third time returned %s\n",
2166                          cli_errstr(cli1));
2167                goto fail;
2168        }
2169
2170	correct = true;
2171
2172fail:
2173	cli_close(cli1, fnum1);
2174	cli_close(cli1, fnum2);
2175	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
2176	torture_close_connection(cli1);
2177
2178	printf("finished locktest8\n");
2179	return correct;
2180}
2181
2182/*
2183 * This test is designed to be run in conjunction with
2184 * external NFS or POSIX locks taken in the filesystem.
2185 * It checks that the smbd server will block until the
2186 * lock is released and then acquire it. JRA.
2187 */
2188
2189static bool got_alarm;
2190static int alarm_fd;
2191
2192static void alarm_handler(int dummy)
2193{
2194        got_alarm = True;
2195}
2196
2197static void alarm_handler_parent(int dummy)
2198{
2199	close(alarm_fd);
2200}
2201
2202static void do_local_lock(int read_fd, int write_fd)
2203{
2204	int fd;
2205	char c = '\0';
2206	struct flock lock;
2207	const char *local_pathname = NULL;
2208	int ret;
2209
2210	local_pathname = talloc_asprintf(talloc_tos(),
2211			"%s/lockt9.lck", local_path);
2212	if (!local_pathname) {
2213		printf("child: alloc fail\n");
2214		exit(1);
2215	}
2216
2217	unlink(local_pathname);
2218	fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2219	if (fd == -1) {
2220		printf("child: open of %s failed %s.\n",
2221			local_pathname, strerror(errno));
2222		exit(1);
2223	}
2224
2225	/* Now take a fcntl lock. */
2226	lock.l_type = F_WRLCK;
2227	lock.l_whence = SEEK_SET;
2228	lock.l_start = 0;
2229	lock.l_len = 4;
2230	lock.l_pid = getpid();
2231
2232	ret = fcntl(fd,F_SETLK,&lock);
2233	if (ret == -1) {
2234		printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2235			local_pathname, strerror(errno));
2236		exit(1);
2237	} else {
2238		printf("child: got lock 0:4 on file %s.\n",
2239			local_pathname );
2240		fflush(stdout);
2241	}
2242
2243	CatchSignal(SIGALRM, alarm_handler);
2244	alarm(5);
2245	/* Signal the parent. */
2246	if (write(write_fd, &c, 1) != 1) {
2247		printf("child: start signal fail %s.\n",
2248			strerror(errno));
2249		exit(1);
2250	}
2251	alarm(0);
2252
2253	alarm(10);
2254	/* Wait for the parent to be ready. */
2255	if (read(read_fd, &c, 1) != 1) {
2256		printf("child: reply signal fail %s.\n",
2257			strerror(errno));
2258		exit(1);
2259	}
2260	alarm(0);
2261
2262	sleep(5);
2263	close(fd);
2264	printf("child: released lock 0:4 on file %s.\n",
2265		local_pathname );
2266	fflush(stdout);
2267	exit(0);
2268}
2269
2270static bool run_locktest9(int dummy)
2271{
2272	struct cli_state *cli1;
2273	const char *fname = "\\lockt9.lck";
2274	uint16_t fnum;
2275	bool correct = False;
2276	int pipe_in[2], pipe_out[2];
2277	pid_t child_pid;
2278	char c = '\0';
2279	int ret;
2280	double seconds;
2281	NTSTATUS status;
2282
2283	printf("starting locktest9\n");
2284
2285	if (local_path == NULL) {
2286		d_fprintf(stderr, "locktest9 must be given a local path via -l <localpath>\n");
2287		return false;
2288	}
2289
2290	if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2291		return false;
2292	}
2293
2294	child_pid = fork();
2295	if (child_pid == -1) {
2296		return false;
2297	}
2298
2299	if (child_pid == 0) {
2300		/* Child. */
2301		do_local_lock(pipe_out[0], pipe_in[1]);
2302		exit(0);
2303	}
2304
2305	close(pipe_out[0]);
2306	close(pipe_in[1]);
2307	pipe_out[0] = -1;
2308	pipe_in[1] = -1;
2309
2310	/* Parent. */
2311	ret = read(pipe_in[0], &c, 1);
2312	if (ret != 1) {
2313		d_fprintf(stderr, "failed to read start signal from child. %s\n",
2314			strerror(errno));
2315		return false;
2316	}
2317
2318	if (!torture_open_connection(&cli1, 0)) {
2319		return false;
2320	}
2321
2322	cli_sockopt(cli1, sockops);
2323
2324	status = cli_open(cli1, fname, O_RDWR, DENY_NONE,
2325			  &fnum);
2326	if (!NT_STATUS_IS_OK(status)) {
2327		d_fprintf(stderr, "cli_open returned %s\n", cli_errstr(cli1));
2328		return false;
2329	}
2330
2331	/* Ensure the child has the lock. */
2332	if (cli_lock(cli1, fnum, 0, 4, 0, WRITE_LOCK)) {
2333		d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2334		goto fail;
2335	} else {
2336		d_printf("Child has the lock.\n");
2337	}
2338
2339	/* Tell the child to wait 5 seconds then exit. */
2340	ret = write(pipe_out[1], &c, 1);
2341	if (ret != 1) {
2342		d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2343			strerror(errno));
2344		goto fail;
2345	}
2346
2347	/* Wait 20 seconds for the lock. */
2348	alarm_fd = cli1->fd;
2349	CatchSignal(SIGALRM, alarm_handler_parent);
2350	alarm(20);
2351
2352	start_timer();
2353
2354	if (!cli_lock(cli1, fnum, 0, 4, -1, WRITE_LOCK)) {
2355		d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2356		       "%s\n", cli_errstr(cli1));
2357		goto fail_nofd;
2358	}
2359	alarm(0);
2360
2361	seconds = end_timer();
2362
2363	printf("Parent got the lock after %.2f seconds.\n",
2364		seconds);
2365
2366	status = cli_close(cli1, fnum);
2367	if (!NT_STATUS_IS_OK(status)) {
2368		d_fprintf(stderr, "cli_close(fnum1) %s\n", cli_errstr(cli1));
2369		goto fail;
2370	}
2371
2372	correct = true;
2373
2374fail:
2375	cli_close(cli1, fnum);
2376	torture_close_connection(cli1);
2377
2378fail_nofd:
2379
2380	printf("finished locktest9\n");
2381	return correct;
2382}
2383
2384/*
2385test whether fnums and tids open on one VC are available on another (a major
2386security hole)
2387*/
2388static bool run_fdpasstest(int dummy)
2389{
2390	struct cli_state *cli1, *cli2;
2391	const char *fname = "\\fdpass.tst";
2392	uint16_t fnum1;
2393	char buf[1024];
2394
2395	if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2396		return False;
2397	}
2398	cli_sockopt(cli1, sockops);
2399	cli_sockopt(cli2, sockops);
2400
2401	printf("starting fdpasstest\n");
2402
2403	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
2404
2405	if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1))) {
2406		printf("open of %s failed (%s)\n", fname, cli_errstr(cli1));
2407		return False;
2408	}
2409
2410	if (cli_write(cli1, fnum1, 0, "hello world\n", 0, 13) != 13) {
2411		printf("write failed (%s)\n", cli_errstr(cli1));
2412		return False;
2413	}
2414
2415	cli2->vuid = cli1->vuid;
2416	cli2->cnum = cli1->cnum;
2417	cli2->pid = cli1->pid;
2418
2419	if (cli_read(cli2, fnum1, buf, 0, 13) == 13) {
2420		printf("read succeeded! nasty security hole [%s]\n",
2421		       buf);
2422		return False;
2423	}
2424
2425	cli_close(cli1, fnum1);
2426	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
2427
2428	torture_close_connection(cli1);
2429	torture_close_connection(cli2);
2430
2431	printf("finished fdpasstest\n");
2432	return True;
2433}
2434
2435static bool run_fdsesstest(int dummy)
2436{
2437	struct cli_state *cli;
2438	uint16 new_vuid;
2439	uint16 saved_vuid;
2440	uint16 new_cnum;
2441	uint16 saved_cnum;
2442	const char *fname = "\\fdsess.tst";
2443	const char *fname1 = "\\fdsess1.tst";
2444	uint16_t fnum1;
2445	uint16_t fnum2;
2446	char buf[1024];
2447	bool ret = True;
2448
2449	if (!torture_open_connection(&cli, 0))
2450		return False;
2451	cli_sockopt(cli, sockops);
2452
2453	if (!torture_cli_session_setup2(cli, &new_vuid))
2454		return False;
2455
2456	saved_cnum = cli->cnum;
2457	if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, share, "?????", "", 1)))
2458		return False;
2459	new_cnum = cli->cnum;
2460	cli->cnum = saved_cnum;
2461
2462	printf("starting fdsesstest\n");
2463
2464	cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
2465	cli_unlink(cli, fname1, aSYSTEM | aHIDDEN);
2466
2467	if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1))) {
2468		printf("open of %s failed (%s)\n", fname, cli_errstr(cli));
2469		return False;
2470	}
2471
2472	if (cli_write(cli, fnum1, 0, "hello world\n", 0, 13) != 13) {
2473		printf("write failed (%s)\n", cli_errstr(cli));
2474		return False;
2475	}
2476
2477	saved_vuid = cli->vuid;
2478	cli->vuid = new_vuid;
2479
2480	if (cli_read(cli, fnum1, buf, 0, 13) == 13) {
2481		printf("read succeeded with different vuid! nasty security hole [%s]\n",
2482		       buf);
2483		ret = False;
2484	}
2485	/* Try to open a file with different vuid, samba cnum. */
2486	if (NT_STATUS_IS_OK(cli_open(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
2487		printf("create with different vuid, same cnum succeeded.\n");
2488		cli_close(cli, fnum2);
2489		cli_unlink(cli, fname1, aSYSTEM | aHIDDEN);
2490	} else {
2491		printf("create with different vuid, same cnum failed.\n");
2492		printf("This will cause problems with service clients.\n");
2493		ret = False;
2494	}
2495
2496	cli->vuid = saved_vuid;
2497
2498	/* Try with same vuid, different cnum. */
2499	cli->cnum = new_cnum;
2500
2501	if (cli_read(cli, fnum1, buf, 0, 13) == 13) {
2502		printf("read succeeded with different cnum![%s]\n",
2503		       buf);
2504		ret = False;
2505	}
2506
2507	cli->cnum = saved_cnum;
2508	cli_close(cli, fnum1);
2509	cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
2510
2511	torture_close_connection(cli);
2512
2513	printf("finished fdsesstest\n");
2514	return ret;
2515}
2516
2517/*
2518  This test checks that
2519
2520  1) the server does not allow an unlink on a file that is open
2521*/
2522static bool run_unlinktest(int dummy)
2523{
2524	struct cli_state *cli;
2525	const char *fname = "\\unlink.tst";
2526	uint16_t fnum;
2527	bool correct = True;
2528
2529	if (!torture_open_connection(&cli, 0)) {
2530		return False;
2531	}
2532
2533	cli_sockopt(cli, sockops);
2534
2535	printf("starting unlink test\n");
2536
2537	cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
2538
2539	cli_setpid(cli, 1);
2540
2541	if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum))) {
2542		printf("open of %s failed (%s)\n", fname, cli_errstr(cli));
2543		return False;
2544	}
2545
2546	if (NT_STATUS_IS_OK(cli_unlink(cli, fname, aSYSTEM | aHIDDEN))) {
2547		printf("error: server allowed unlink on an open file\n");
2548		correct = False;
2549	} else {
2550		correct = check_error(__LINE__, cli, ERRDOS, ERRbadshare,
2551				      NT_STATUS_SHARING_VIOLATION);
2552	}
2553
2554	cli_close(cli, fnum);
2555	cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
2556
2557	if (!torture_close_connection(cli)) {
2558		correct = False;
2559	}
2560
2561	printf("unlink test finished\n");
2562
2563	return correct;
2564}
2565
2566
2567/*
2568test how many open files this server supports on the one socket
2569*/
2570static bool run_maxfidtest(int dummy)
2571{
2572	struct cli_state *cli;
2573	const char *ftemplate = "\\maxfid.%d.%d";
2574	fstring fname;
2575	uint16_t fnums[0x11000];
2576	int i;
2577	int retries=4;
2578	bool correct = True;
2579
2580	cli = current_cli;
2581
2582	if (retries <= 0) {
2583		printf("failed to connect\n");
2584		return False;
2585	}
2586
2587	cli_sockopt(cli, sockops);
2588
2589	for (i=0; i<0x11000; i++) {
2590		slprintf(fname,sizeof(fname)-1,ftemplate, i,(int)getpid());
2591		if (!NT_STATUS_IS_OK(cli_open(cli, fname,
2592					O_RDWR|O_CREAT|O_TRUNC, DENY_NONE, &fnums[i]))) {
2593			printf("open of %s failed (%s)\n",
2594			       fname, cli_errstr(cli));
2595			printf("maximum fnum is %d\n", i);
2596			break;
2597		}
2598		printf("%6d\r", i);
2599	}
2600	printf("%6d\n", i);
2601	i--;
2602
2603	printf("cleaning up\n");
2604	for (;i>=0;i--) {
2605		slprintf(fname,sizeof(fname)-1,ftemplate, i,(int)getpid());
2606		cli_close(cli, fnums[i]);
2607		if (!NT_STATUS_IS_OK(cli_unlink(cli, fname, aSYSTEM | aHIDDEN))) {
2608			printf("unlink of %s failed (%s)\n",
2609			       fname, cli_errstr(cli));
2610			correct = False;
2611		}
2612		printf("%6d\r", i);
2613	}
2614	printf("%6d\n", 0);
2615
2616	printf("maxfid test finished\n");
2617	if (!torture_close_connection(cli)) {
2618		correct = False;
2619	}
2620	return correct;
2621}
2622
2623/* generate a random buffer */
2624static void rand_buf(char *buf, int len)
2625{
2626	while (len--) {
2627		*buf = (char)sys_random();
2628		buf++;
2629	}
2630}
2631
2632/* send smb negprot commands, not reading the response */
2633static bool run_negprot_nowait(int dummy)
2634{
2635	int i;
2636	static struct cli_state *cli;
2637	bool correct = True;
2638
2639	printf("starting negprot nowait test\n");
2640
2641	if (!(cli = open_nbt_connection())) {
2642		return False;
2643	}
2644
2645	for (i=0;i<50000;i++) {
2646		cli_negprot_sendsync(cli);
2647	}
2648
2649	if (!torture_close_connection(cli)) {
2650		correct = False;
2651	}
2652
2653	printf("finished negprot nowait test\n");
2654
2655	return correct;
2656}
2657
2658
2659/* send random IPC commands */
2660static bool run_randomipc(int dummy)
2661{
2662	char *rparam = NULL;
2663	char *rdata = NULL;
2664	unsigned int rdrcnt,rprcnt;
2665	char param[1024];
2666	int api, param_len, i;
2667	struct cli_state *cli;
2668	bool correct = True;
2669	int count = 50000;
2670
2671	printf("starting random ipc test\n");
2672
2673	if (!torture_open_connection(&cli, 0)) {
2674		return False;
2675	}
2676
2677	for (i=0;i<count;i++) {
2678		api = sys_random() % 500;
2679		param_len = (sys_random() % 64);
2680
2681		rand_buf(param, param_len);
2682
2683		SSVAL(param,0,api);
2684
2685		cli_api(cli,
2686			param, param_len, 8,
2687			NULL, 0, BUFFER_SIZE,
2688			&rparam, &rprcnt,
2689			&rdata, &rdrcnt);
2690		if (i % 100 == 0) {
2691			printf("%d/%d\r", i,count);
2692		}
2693	}
2694	printf("%d/%d\n", i, count);
2695
2696	if (!torture_close_connection(cli)) {
2697		correct = False;
2698	}
2699
2700	printf("finished random ipc test\n");
2701
2702	return correct;
2703}
2704
2705
2706
2707static void browse_callback(const char *sname, uint32 stype,
2708			    const char *comment, void *state)
2709{
2710	printf("\t%20.20s %08x %s\n", sname, stype, comment);
2711}
2712
2713
2714
2715/*
2716  This test checks the browse list code
2717
2718*/
2719static bool run_browsetest(int dummy)
2720{
2721	static struct cli_state *cli;
2722	bool correct = True;
2723
2724	printf("starting browse test\n");
2725
2726	if (!torture_open_connection(&cli, 0)) {
2727		return False;
2728	}
2729
2730	printf("domain list:\n");
2731	cli_NetServerEnum(cli, cli->server_domain,
2732			  SV_TYPE_DOMAIN_ENUM,
2733			  browse_callback, NULL);
2734
2735	printf("machine list:\n");
2736	cli_NetServerEnum(cli, cli->server_domain,
2737			  SV_TYPE_ALL,
2738			  browse_callback, NULL);
2739
2740	if (!torture_close_connection(cli)) {
2741		correct = False;
2742	}
2743
2744	printf("browse test finished\n");
2745
2746	return correct;
2747
2748}
2749
2750
2751/*
2752  This checks how the getatr calls works
2753*/
2754static bool run_attrtest(int dummy)
2755{
2756	struct cli_state *cli;
2757	uint16_t fnum;
2758	time_t t, t2;
2759	const char *fname = "\\attrib123456789.tst";
2760	bool correct = True;
2761
2762	printf("starting attrib test\n");
2763
2764	if (!torture_open_connection(&cli, 0)) {
2765		return False;
2766	}
2767
2768	cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
2769	cli_open(cli, fname,
2770			O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
2771	cli_close(cli, fnum);
2772	if (!NT_STATUS_IS_OK(cli_getatr(cli, fname, NULL, NULL, &t))) {
2773		printf("getatr failed (%s)\n", cli_errstr(cli));
2774		correct = False;
2775	}
2776
2777	if (abs(t - time(NULL)) > 60*60*24*10) {
2778		printf("ERROR: SMBgetatr bug. time is %s",
2779		       ctime(&t));
2780		t = time(NULL);
2781		correct = True;
2782	}
2783
2784	t2 = t-60*60*24; /* 1 day ago */
2785
2786	if (!NT_STATUS_IS_OK(cli_setatr(cli, fname, 0, t2))) {
2787		printf("setatr failed (%s)\n", cli_errstr(cli));
2788		correct = True;
2789	}
2790
2791	if (!NT_STATUS_IS_OK(cli_getatr(cli, fname, NULL, NULL, &t))) {
2792		printf("getatr failed (%s)\n", cli_errstr(cli));
2793		correct = True;
2794	}
2795
2796	if (t != t2) {
2797		printf("ERROR: getatr/setatr bug. times are\n%s",
2798		       ctime(&t));
2799		printf("%s", ctime(&t2));
2800		correct = True;
2801	}
2802
2803	cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
2804
2805	if (!torture_close_connection(cli)) {
2806		correct = False;
2807	}
2808
2809	printf("attrib test finished\n");
2810
2811	return correct;
2812}
2813
2814
2815/*
2816  This checks a couple of trans2 calls
2817*/
2818static bool run_trans2test(int dummy)
2819{
2820	struct cli_state *cli;
2821	uint16_t fnum;
2822	SMB_OFF_T size;
2823	time_t c_time, a_time, m_time;
2824	struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
2825	const char *fname = "\\trans2.tst";
2826	const char *dname = "\\trans2";
2827	const char *fname2 = "\\trans2\\trans2.tst";
2828	char pname[1024];
2829	bool correct = True;
2830
2831	printf("starting trans2 test\n");
2832
2833	if (!torture_open_connection(&cli, 0)) {
2834		return False;
2835	}
2836
2837	cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
2838	cli_open(cli, fname,
2839			O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
2840	if (!cli_qfileinfo(cli, fnum, NULL, &size, &c_time_ts, &a_time_ts, &w_time_ts,
2841			   &m_time_ts, NULL)) {
2842		printf("ERROR: qfileinfo failed (%s)\n", cli_errstr(cli));
2843		correct = False;
2844	}
2845
2846	if (!cli_qfilename(cli, fnum, pname, sizeof(pname))) {
2847		printf("ERROR: qfilename failed (%s)\n", cli_errstr(cli));
2848		correct = False;
2849	}
2850
2851	if (strcmp(pname, fname)) {
2852		printf("qfilename gave different name? [%s] [%s]\n",
2853		       fname, pname);
2854		correct = False;
2855	}
2856
2857	cli_close(cli, fnum);
2858
2859	sleep(2);
2860
2861	cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
2862	if (!NT_STATUS_IS_OK(cli_open(cli, fname,
2863			O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum))) {
2864		printf("open of %s failed (%s)\n", fname, cli_errstr(cli));
2865		return False;
2866	}
2867	cli_close(cli, fnum);
2868
2869	if (!cli_qpathinfo(cli, fname, &c_time, &a_time, &m_time, &size, NULL)) {
2870		printf("ERROR: qpathinfo failed (%s)\n", cli_errstr(cli));
2871		correct = False;
2872	} else {
2873		if (c_time != m_time) {
2874			printf("create time=%s", ctime(&c_time));
2875			printf("modify time=%s", ctime(&m_time));
2876			printf("This system appears to have sticky create times\n");
2877		}
2878		if (a_time % (60*60) == 0) {
2879			printf("access time=%s", ctime(&a_time));
2880			printf("This system appears to set a midnight access time\n");
2881			correct = False;
2882		}
2883
2884		if (abs(m_time - time(NULL)) > 60*60*24*7) {
2885			printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
2886			correct = False;
2887		}
2888	}
2889
2890
2891	cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
2892	cli_open(cli, fname,
2893			O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
2894	cli_close(cli, fnum);
2895	if (!cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
2896			    &m_time_ts, &size, NULL, NULL)) {
2897		printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(cli));
2898		correct = False;
2899	} else {
2900		if (w_time_ts.tv_sec < 60*60*24*2) {
2901			printf("write time=%s", ctime(&w_time_ts.tv_sec));
2902			printf("This system appears to set a initial 0 write time\n");
2903			correct = False;
2904		}
2905	}
2906
2907	cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
2908
2909
2910	/* check if the server updates the directory modification time
2911           when creating a new file */
2912	if (!NT_STATUS_IS_OK(cli_mkdir(cli, dname))) {
2913		printf("ERROR: mkdir failed (%s)\n", cli_errstr(cli));
2914		correct = False;
2915	}
2916	sleep(3);
2917	if (!cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts, &w_time_ts,
2918			    &m_time_ts, &size, NULL, NULL)) {
2919		printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(cli));
2920		correct = False;
2921	}
2922
2923	cli_open(cli, fname2,
2924			O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
2925	cli_write(cli, fnum,  0, (char *)&fnum, 0, sizeof(fnum));
2926	cli_close(cli, fnum);
2927	if (!cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts, &w_time_ts,
2928			    &m_time2_ts, &size, NULL, NULL)) {
2929		printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(cli));
2930		correct = False;
2931	} else {
2932		if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
2933		    == 0) {
2934			printf("This system does not update directory modification times\n");
2935			correct = False;
2936		}
2937	}
2938	cli_unlink(cli, fname2, aSYSTEM | aHIDDEN);
2939	cli_rmdir(cli, dname);
2940
2941	if (!torture_close_connection(cli)) {
2942		correct = False;
2943	}
2944
2945	printf("trans2 test finished\n");
2946
2947	return correct;
2948}
2949
2950/*
2951  This checks new W2K calls.
2952*/
2953
2954static bool new_trans(struct cli_state *pcli, int fnum, int level)
2955{
2956	char *buf = NULL;
2957	uint32 len;
2958	bool correct = True;
2959
2960	if (!cli_qfileinfo_test(pcli, fnum, level, &buf, &len)) {
2961		printf("ERROR: qfileinfo (%d) failed (%s)\n", level, cli_errstr(pcli));
2962		correct = False;
2963	} else {
2964		printf("qfileinfo: level %d, len = %u\n", level, len);
2965		dump_data(0, (uint8 *)buf, len);
2966		printf("\n");
2967	}
2968	SAFE_FREE(buf);
2969	return correct;
2970}
2971
2972static bool run_w2ktest(int dummy)
2973{
2974	struct cli_state *cli;
2975	uint16_t fnum;
2976	const char *fname = "\\w2ktest\\w2k.tst";
2977	int level;
2978	bool correct = True;
2979
2980	printf("starting w2k test\n");
2981
2982	if (!torture_open_connection(&cli, 0)) {
2983		return False;
2984	}
2985
2986	cli_open(cli, fname,
2987			O_RDWR | O_CREAT , DENY_NONE, &fnum);
2988
2989	for (level = 1004; level < 1040; level++) {
2990		new_trans(cli, fnum, level);
2991	}
2992
2993	cli_close(cli, fnum);
2994
2995	if (!torture_close_connection(cli)) {
2996		correct = False;
2997	}
2998
2999	printf("w2k test finished\n");
3000
3001	return correct;
3002}
3003
3004
3005/*
3006  this is a harness for some oplock tests
3007 */
3008static bool run_oplock1(int dummy)
3009{
3010	struct cli_state *cli1;
3011	const char *fname = "\\lockt1.lck";
3012	uint16_t fnum1;
3013	bool correct = True;
3014
3015	printf("starting oplock test 1\n");
3016
3017	if (!torture_open_connection(&cli1, 0)) {
3018		return False;
3019	}
3020
3021	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3022
3023	cli_sockopt(cli1, sockops);
3024
3025	cli1->use_oplocks = True;
3026
3027	if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1))) {
3028		printf("open of %s failed (%s)\n", fname, cli_errstr(cli1));
3029		return False;
3030	}
3031
3032	cli1->use_oplocks = False;
3033
3034	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3035	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3036
3037	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3038		printf("close2 failed (%s)\n", cli_errstr(cli1));
3039		return False;
3040	}
3041
3042	if (!NT_STATUS_IS_OK(cli_unlink(cli1, fname, aSYSTEM | aHIDDEN))) {
3043		printf("unlink failed (%s)\n", cli_errstr(cli1));
3044		return False;
3045	}
3046
3047	if (!torture_close_connection(cli1)) {
3048		correct = False;
3049	}
3050
3051	printf("finished oplock test 1\n");
3052
3053	return correct;
3054}
3055
3056static bool run_oplock2(int dummy)
3057{
3058	struct cli_state *cli1, *cli2;
3059	const char *fname = "\\lockt2.lck";
3060	uint16_t fnum1, fnum2;
3061	int saved_use_oplocks = use_oplocks;
3062	char buf[4];
3063	bool correct = True;
3064	volatile bool *shared_correct;
3065
3066	shared_correct = (volatile bool *)shm_setup(sizeof(bool));
3067	*shared_correct = True;
3068
3069	use_level_II_oplocks = True;
3070	use_oplocks = True;
3071
3072	printf("starting oplock test 2\n");
3073
3074	if (!torture_open_connection(&cli1, 0)) {
3075		use_level_II_oplocks = False;
3076		use_oplocks = saved_use_oplocks;
3077		return False;
3078	}
3079
3080	cli1->use_oplocks = True;
3081	cli1->use_level_II_oplocks = True;
3082
3083	if (!torture_open_connection(&cli2, 1)) {
3084		use_level_II_oplocks = False;
3085		use_oplocks = saved_use_oplocks;
3086		return False;
3087	}
3088
3089	cli2->use_oplocks = True;
3090	cli2->use_level_II_oplocks = True;
3091
3092	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3093
3094	cli_sockopt(cli1, sockops);
3095	cli_sockopt(cli2, sockops);
3096
3097	if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1))) {
3098		printf("open of %s failed (%s)\n", fname, cli_errstr(cli1));
3099		return False;
3100	}
3101
3102	/* Don't need the globals any more. */
3103	use_level_II_oplocks = False;
3104	use_oplocks = saved_use_oplocks;
3105
3106	if (fork() == 0) {
3107		/* Child code */
3108		if (!NT_STATUS_IS_OK(cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2))) {
3109			printf("second open of %s failed (%s)\n", fname, cli_errstr(cli1));
3110			*shared_correct = False;
3111			exit(0);
3112		}
3113
3114		sleep(2);
3115
3116		if (!NT_STATUS_IS_OK(cli_close(cli2, fnum2))) {
3117			printf("close2 failed (%s)\n", cli_errstr(cli1));
3118			*shared_correct = False;
3119		}
3120
3121		exit(0);
3122	}
3123
3124	sleep(2);
3125
3126	/* Ensure cli1 processes the break. Empty file should always return 0
3127	 * bytes.  */
3128
3129	if (cli_read(cli1, fnum1, buf, 0, 4) != 0) {
3130		printf("read on fnum1 failed (%s)\n", cli_errstr(cli1));
3131		correct = False;
3132	}
3133
3134	/* Should now be at level II. */
3135	/* Test if sending a write locks causes a break to none. */
3136
3137	if (!cli_lock(cli1, fnum1, 0, 4, 0, READ_LOCK)) {
3138		printf("lock failed (%s)\n", cli_errstr(cli1));
3139		correct = False;
3140	}
3141
3142	cli_unlock(cli1, fnum1, 0, 4);
3143
3144	sleep(2);
3145
3146	if (!cli_lock(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) {
3147		printf("lock failed (%s)\n", cli_errstr(cli1));
3148		correct = False;
3149	}
3150
3151	cli_unlock(cli1, fnum1, 0, 4);
3152
3153	sleep(2);
3154
3155	cli_read(cli1, fnum1, buf, 0, 4);
3156
3157#if 0
3158	if (cli_write(cli1, fnum1, 0, buf, 0, 4) != 4) {
3159		printf("write on fnum1 failed (%s)\n", cli_errstr(cli1));
3160		correct = False;
3161	}
3162#endif
3163
3164	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3165		printf("close1 failed (%s)\n", cli_errstr(cli1));
3166		correct = False;
3167	}
3168
3169	sleep(4);
3170
3171	if (!NT_STATUS_IS_OK(cli_unlink(cli1, fname, aSYSTEM | aHIDDEN))) {
3172		printf("unlink failed (%s)\n", cli_errstr(cli1));
3173		correct = False;
3174	}
3175
3176	if (!torture_close_connection(cli1)) {
3177		correct = False;
3178	}
3179
3180	if (!*shared_correct) {
3181		correct = False;
3182	}
3183
3184	printf("finished oplock test 2\n");
3185
3186	return correct;
3187}
3188
3189/* handler for oplock 3 tests */
3190static NTSTATUS oplock3_handler(struct cli_state *cli, uint16_t fnum, unsigned char level)
3191{
3192	printf("got oplock break fnum=%d level=%d\n",
3193	       fnum, level);
3194	return cli_oplock_ack(cli, fnum, level);
3195}
3196
3197static bool run_oplock3(int dummy)
3198{
3199	struct cli_state *cli;
3200	const char *fname = "\\oplockt3.dat";
3201	uint16_t fnum;
3202	char buf[4] = "abcd";
3203	bool correct = True;
3204	volatile bool *shared_correct;
3205
3206	shared_correct = (volatile bool *)shm_setup(sizeof(bool));
3207	*shared_correct = True;
3208
3209	printf("starting oplock test 3\n");
3210
3211	if (fork() == 0) {
3212		/* Child code */
3213		use_oplocks = True;
3214		use_level_II_oplocks = True;
3215		if (!torture_open_connection(&cli, 0)) {
3216			*shared_correct = False;
3217			exit(0);
3218		}
3219		sleep(2);
3220		/* try to trigger a oplock break in parent */
3221		cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum);
3222		cli_write(cli, fnum, 0, buf, 0, 4);
3223		exit(0);
3224	}
3225
3226	/* parent code */
3227	use_oplocks = True;
3228	use_level_II_oplocks = True;
3229	if (!torture_open_connection(&cli, 1)) { /* other is forked */
3230		return False;
3231	}
3232	cli_oplock_handler(cli, oplock3_handler);
3233	cli_open(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum);
3234	cli_write(cli, fnum, 0, buf, 0, 4);
3235	cli_close(cli, fnum);
3236	cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum);
3237	cli->timeout = 20000;
3238	cli_receive_smb(cli);
3239	printf("finished oplock test 3\n");
3240
3241	return (correct && *shared_correct);
3242
3243/* What are we looking for here?  What's sucess and what's FAILURE? */
3244}
3245
3246
3247
3248/*
3249  Test delete on close semantics.
3250 */
3251static bool run_deletetest(int dummy)
3252{
3253	struct cli_state *cli1 = NULL;
3254	struct cli_state *cli2 = NULL;
3255	const char *fname = "\\delete.file";
3256	uint16_t fnum1 = (uint16_t)-1;
3257	uint16_t fnum2 = (uint16_t)-1;
3258	bool correct = True;
3259
3260	printf("starting delete test\n");
3261
3262	if (!torture_open_connection(&cli1, 0)) {
3263		return False;
3264	}
3265
3266	cli_sockopt(cli1, sockops);
3267
3268	/* Test 1 - this should delete the file on close. */
3269
3270	cli_setatr(cli1, fname, 0, 0);
3271	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3272
3273	if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
3274				   0, FILE_OVERWRITE_IF,
3275				   FILE_DELETE_ON_CLOSE, 0, &fnum1))) {
3276		printf("[1] open of %s failed (%s)\n", fname, cli_errstr(cli1));
3277		correct = False;
3278		goto fail;
3279	}
3280
3281#if 0 /* JRATEST */
3282        {
3283                uint32 *accinfo = NULL;
3284                uint32 len;
3285                cli_qfileinfo_test(cli1, fnum1, SMB_FILE_ACCESS_INFORMATION, (char **)&accinfo, &len);
3286		if (accinfo)
3287	                printf("access mode = 0x%lx\n", *accinfo);
3288                SAFE_FREE(accinfo);
3289        }
3290#endif
3291
3292	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3293		printf("[1] close failed (%s)\n", cli_errstr(cli1));
3294		correct = False;
3295		goto fail;
3296	}
3297
3298	if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1))) {
3299		printf("[1] open of %s succeeded (should fail)\n", fname);
3300		correct = False;
3301		goto fail;
3302	}
3303
3304	printf("first delete on close test succeeded.\n");
3305
3306	/* Test 2 - this should delete the file on close. */
3307
3308	cli_setatr(cli1, fname, 0, 0);
3309	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3310
3311	if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3312				   FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
3313				   FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
3314		printf("[2] open of %s failed (%s)\n", fname, cli_errstr(cli1));
3315		correct = False;
3316		goto fail;
3317	}
3318
3319	if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
3320		printf("[2] setting delete_on_close failed (%s)\n", cli_errstr(cli1));
3321		correct = False;
3322		goto fail;
3323	}
3324
3325	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3326		printf("[2] close failed (%s)\n", cli_errstr(cli1));
3327		correct = False;
3328		goto fail;
3329	}
3330
3331	if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3332		printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
3333		if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3334			printf("[2] close failed (%s)\n", cli_errstr(cli1));
3335			correct = False;
3336			goto fail;
3337		}
3338		cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3339	} else
3340		printf("second delete on close test succeeded.\n");
3341
3342	/* Test 3 - ... */
3343	cli_setatr(cli1, fname, 0, 0);
3344	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3345
3346	if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
3347				   FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
3348		printf("[3] open - 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
3349		correct = False;
3350		goto fail;
3351	}
3352
3353	/* This should fail with a sharing violation - open for delete is only compatible
3354	   with SHARE_DELETE. */
3355
3356	if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
3357			FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, 0, &fnum2))) {
3358		printf("[3] open  - 2 of %s succeeded - should have failed.\n", fname);
3359		correct = False;
3360		goto fail;
3361	}
3362
3363	/* This should succeed. */
3364
3365	if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
3366			FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0, 0, &fnum2))) {
3367		printf("[3] open  - 2 of %s failed (%s)\n", fname, cli_errstr(cli1));
3368		correct = False;
3369		goto fail;
3370	}
3371
3372	if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
3373		printf("[3] setting delete_on_close failed (%s)\n", cli_errstr(cli1));
3374		correct = False;
3375		goto fail;
3376	}
3377
3378	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3379		printf("[3] close 1 failed (%s)\n", cli_errstr(cli1));
3380		correct = False;
3381		goto fail;
3382	}
3383
3384	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
3385		printf("[3] close 2 failed (%s)\n", cli_errstr(cli1));
3386		correct = False;
3387		goto fail;
3388	}
3389
3390	/* This should fail - file should no longer be there. */
3391
3392	if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3393		printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
3394		if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3395			printf("[3] close failed (%s)\n", cli_errstr(cli1));
3396		}
3397		cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3398		correct = False;
3399		goto fail;
3400	} else
3401		printf("third delete on close test succeeded.\n");
3402
3403	/* Test 4 ... */
3404	cli_setatr(cli1, fname, 0, 0);
3405	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3406
3407	if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
3408			FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
3409		printf("[4] open of %s failed (%s)\n", fname, cli_errstr(cli1));
3410		correct = False;
3411		goto fail;
3412	}
3413
3414	/* This should succeed. */
3415	if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3416			FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0, 0, &fnum2))) {
3417		printf("[4] open  - 2 of %s failed (%s)\n", fname, cli_errstr(cli1));
3418		correct = False;
3419		goto fail;
3420	}
3421
3422	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
3423		printf("[4] close - 1 failed (%s)\n", cli_errstr(cli1));
3424		correct = False;
3425		goto fail;
3426	}
3427
3428	if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
3429		printf("[4] setting delete_on_close failed (%s)\n", cli_errstr(cli1));
3430		correct = False;
3431		goto fail;
3432	}
3433
3434	/* This should fail - no more opens once delete on close set. */
3435	if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3436				   FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3437				   FILE_OPEN, 0, 0, &fnum2))) {
3438		printf("[4] open  - 3 of %s succeeded ! Should have failed.\n", fname );
3439		correct = False;
3440		goto fail;
3441	} else
3442		printf("fourth delete on close test succeeded.\n");
3443
3444	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3445		printf("[4] close - 2 failed (%s)\n", cli_errstr(cli1));
3446		correct = False;
3447		goto fail;
3448	}
3449
3450	/* Test 5 ... */
3451	cli_setatr(cli1, fname, 0, 0);
3452	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3453
3454	if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1))) {
3455		printf("[5] open of %s failed (%s)\n", fname, cli_errstr(cli1));
3456		correct = False;
3457		goto fail;
3458	}
3459
3460	/* This should fail - only allowed on NT opens with DELETE access. */
3461
3462	if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
3463		printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
3464		correct = False;
3465		goto fail;
3466	}
3467
3468	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3469		printf("[5] close - 2 failed (%s)\n", cli_errstr(cli1));
3470		correct = False;
3471		goto fail;
3472	}
3473
3474	printf("fifth delete on close test succeeded.\n");
3475
3476	/* Test 6 ... */
3477	cli_setatr(cli1, fname, 0, 0);
3478	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3479
3480	if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
3481				   FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3482				   FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
3483		printf("[6] open of %s failed (%s)\n", fname, cli_errstr(cli1));
3484		correct = False;
3485		goto fail;
3486	}
3487
3488	/* This should fail - only allowed on NT opens with DELETE access. */
3489
3490	if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
3491		printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
3492		correct = False;
3493		goto fail;
3494	}
3495
3496	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3497		printf("[6] close - 2 failed (%s)\n", cli_errstr(cli1));
3498		correct = False;
3499		goto fail;
3500	}
3501
3502	printf("sixth delete on close test succeeded.\n");
3503
3504	/* Test 7 ... */
3505	cli_setatr(cli1, fname, 0, 0);
3506	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3507
3508	if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
3509				   FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
3510		printf("[7] open of %s failed (%s)\n", fname, cli_errstr(cli1));
3511		correct = False;
3512		goto fail;
3513	}
3514
3515	if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
3516		printf("[7] setting delete_on_close on file failed !\n");
3517		correct = False;
3518		goto fail;
3519	}
3520
3521	if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, false))) {
3522		printf("[7] unsetting delete_on_close on file failed !\n");
3523		correct = False;
3524		goto fail;
3525	}
3526
3527	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3528		printf("[7] close - 2 failed (%s)\n", cli_errstr(cli1));
3529		correct = False;
3530		goto fail;
3531	}
3532
3533	/* This next open should succeed - we reset the flag. */
3534
3535	if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3536		printf("[5] open of %s failed (%s)\n", fname, cli_errstr(cli1));
3537		correct = False;
3538		goto fail;
3539	}
3540
3541	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3542		printf("[7] close - 2 failed (%s)\n", cli_errstr(cli1));
3543		correct = False;
3544		goto fail;
3545	}
3546
3547	printf("seventh delete on close test succeeded.\n");
3548
3549	/* Test 7 ... */
3550	cli_setatr(cli1, fname, 0, 0);
3551	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3552
3553	if (!torture_open_connection(&cli2, 1)) {
3554		printf("[8] failed to open second connection.\n");
3555		correct = False;
3556		goto fail;
3557	}
3558
3559	cli_sockopt(cli1, sockops);
3560
3561	if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
3562				   FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3563				   FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
3564		printf("[8] open 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
3565		correct = False;
3566		goto fail;
3567	}
3568
3569	if (!NT_STATUS_IS_OK(cli_ntcreate(cli2, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
3570				   FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3571				   FILE_OPEN, 0, 0, &fnum2))) {
3572		printf("[8] open 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
3573		correct = False;
3574		goto fail;
3575	}
3576
3577	if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
3578		printf("[8] setting delete_on_close on file failed !\n");
3579		correct = False;
3580		goto fail;
3581	}
3582
3583	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3584		printf("[8] close - 1 failed (%s)\n", cli_errstr(cli1));
3585		correct = False;
3586		goto fail;
3587	}
3588
3589	if (!NT_STATUS_IS_OK(cli_close(cli2, fnum2))) {
3590		printf("[8] close - 2 failed (%s)\n", cli_errstr(cli2));
3591		correct = False;
3592		goto fail;
3593	}
3594
3595	/* This should fail.. */
3596	if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3597		printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
3598		goto fail;
3599		correct = False;
3600	} else
3601		printf("eighth delete on close test succeeded.\n");
3602
3603	/* This should fail - we need to set DELETE_ACCESS. */
3604	if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0,FILE_READ_DATA|FILE_WRITE_DATA,
3605				   FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE, 0, &fnum1))) {
3606		printf("[9] open of %s succeeded should have failed!\n", fname);
3607		correct = False;
3608		goto fail;
3609	}
3610
3611	printf("ninth delete on close test succeeded.\n");
3612
3613	if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
3614				   FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE, 0, &fnum1))) {
3615		printf("[10] open of %s failed (%s)\n", fname, cli_errstr(cli1));
3616		correct = False;
3617		goto fail;
3618	}
3619
3620	/* This should delete the file. */
3621	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3622		printf("[10] close failed (%s)\n", cli_errstr(cli1));
3623		correct = False;
3624		goto fail;
3625	}
3626
3627	/* This should fail.. */
3628	if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3629		printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
3630		goto fail;
3631		correct = False;
3632	} else
3633		printf("tenth delete on close test succeeded.\n");
3634
3635	cli_setatr(cli1, fname, 0, 0);
3636	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3637
3638	/* What error do we get when attempting to open a read-only file with
3639	   delete access ? */
3640
3641	/* Create a readonly file. */
3642	if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
3643				   FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
3644		printf("[11] open of %s failed (%s)\n", fname, cli_errstr(cli1));
3645		correct = False;
3646		goto fail;
3647	}
3648
3649	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3650		printf("[11] close failed (%s)\n", cli_errstr(cli1));
3651		correct = False;
3652		goto fail;
3653	}
3654
3655	/* Now try open for delete access. */
3656	if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES|DELETE_ACCESS,
3657				   0, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3658				   FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
3659		printf("[11] open of %s succeeded should have been denied with ACCESS_DENIED!\n", fname);
3660		cli_close(cli1, fnum1);
3661		goto fail;
3662		correct = False;
3663	} else {
3664		NTSTATUS nterr = cli_nt_error(cli1);
3665		if (!NT_STATUS_EQUAL(nterr,NT_STATUS_ACCESS_DENIED)) {
3666			printf("[11] open of %s should have been denied with ACCESS_DENIED! Got error %s\n", fname, nt_errstr(nterr));
3667			goto fail;
3668			correct = False;
3669		} else {
3670			printf("eleventh delete on close test succeeded.\n");
3671		}
3672	}
3673
3674	printf("finished delete test\n");
3675
3676  fail:
3677	/* FIXME: This will crash if we aborted before cli2 got
3678	 * intialized, because these functions don't handle
3679	 * uninitialized connections. */
3680
3681	if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
3682	if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
3683	cli_setatr(cli1, fname, 0, 0);
3684	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3685
3686	if (cli1 && !torture_close_connection(cli1)) {
3687		correct = False;
3688	}
3689	if (cli2 && !torture_close_connection(cli2)) {
3690		correct = False;
3691	}
3692	return correct;
3693}
3694
3695
3696/*
3697  print out server properties
3698 */
3699static bool run_properties(int dummy)
3700{
3701	struct cli_state *cli;
3702	bool correct = True;
3703
3704	printf("starting properties test\n");
3705
3706	ZERO_STRUCT(cli);
3707
3708	if (!torture_open_connection(&cli, 0)) {
3709		return False;
3710	}
3711
3712	cli_sockopt(cli, sockops);
3713
3714	d_printf("Capabilities 0x%08x\n", cli->capabilities);
3715
3716	if (!torture_close_connection(cli)) {
3717		correct = False;
3718	}
3719
3720	return correct;
3721}
3722
3723
3724
3725/* FIRST_DESIRED_ACCESS   0xf019f */
3726#define FIRST_DESIRED_ACCESS   FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
3727                               FILE_READ_EA|                           /* 0xf */ \
3728                               FILE_WRITE_EA|FILE_READ_ATTRIBUTES|     /* 0x90 */ \
3729                               FILE_WRITE_ATTRIBUTES|                  /* 0x100 */ \
3730                               DELETE_ACCESS|READ_CONTROL_ACCESS|\
3731                               WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS     /* 0xf0000 */
3732/* SECOND_DESIRED_ACCESS  0xe0080 */
3733#define SECOND_DESIRED_ACCESS  FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
3734                               READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
3735                               WRITE_OWNER_ACCESS                      /* 0xe0000 */
3736
3737#if 0
3738#define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
3739                               READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
3740                               FILE_READ_DATA|\
3741                               WRITE_OWNER_ACCESS                      /* */
3742#endif
3743
3744/*
3745  Test ntcreate calls made by xcopy
3746 */
3747static bool run_xcopy(int dummy)
3748{
3749	static struct cli_state *cli1;
3750	const char *fname = "\\test.txt";
3751	bool correct = True;
3752	uint16_t fnum1, fnum2;
3753
3754	printf("starting xcopy test\n");
3755
3756	if (!torture_open_connection(&cli1, 0)) {
3757		return False;
3758	}
3759
3760	if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0,
3761				   FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
3762				   FILE_SHARE_NONE, FILE_OVERWRITE_IF,
3763				   0x4044, 0, &fnum1))) {
3764		printf("First open failed - %s\n", cli_errstr(cli1));
3765		return False;
3766	}
3767
3768	if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0,
3769				   SECOND_DESIRED_ACCESS, 0,
3770				   FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN,
3771				   0x200000, 0, &fnum2))) {
3772		printf("second open failed - %s\n", cli_errstr(cli1));
3773		return False;
3774	}
3775
3776	if (!torture_close_connection(cli1)) {
3777		correct = False;
3778	}
3779
3780	return correct;
3781}
3782
3783/*
3784  Test rename on files open with share delete and no share delete.
3785 */
3786static bool run_rename(int dummy)
3787{
3788	static struct cli_state *cli1;
3789	const char *fname = "\\test.txt";
3790	const char *fname1 = "\\test1.txt";
3791	bool correct = True;
3792	uint16_t fnum1;
3793	NTSTATUS status;
3794
3795	printf("starting rename test\n");
3796
3797	if (!torture_open_connection(&cli1, 0)) {
3798		return False;
3799	}
3800
3801	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3802	cli_unlink(cli1, fname1, aSYSTEM | aHIDDEN);
3803	if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
3804				   FILE_SHARE_READ, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
3805		printf("First open failed - %s\n", cli_errstr(cli1));
3806		return False;
3807	}
3808
3809	if (!NT_STATUS_IS_OK(cli_rename(cli1, fname, fname1))) {
3810		printf("First rename failed (SHARE_READ) (this is correct) - %s\n", cli_errstr(cli1));
3811	} else {
3812		printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
3813		correct = False;
3814	}
3815
3816	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3817		printf("close - 1 failed (%s)\n", cli_errstr(cli1));
3818		return False;
3819	}
3820
3821	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3822	cli_unlink(cli1, fname1, aSYSTEM | aHIDDEN);
3823	status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
3824#if 0
3825			      FILE_SHARE_DELETE|FILE_SHARE_NONE,
3826#else
3827			      FILE_SHARE_DELETE|FILE_SHARE_READ,
3828#endif
3829			      FILE_OVERWRITE_IF, 0, 0, &fnum1);
3830	if (!NT_STATUS_IS_OK(status)) {
3831		printf("Second open failed - %s\n", cli_errstr(cli1));
3832		return False;
3833	}
3834
3835	if (!NT_STATUS_IS_OK(cli_rename(cli1, fname, fname1))) {
3836		printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", cli_errstr(cli1));
3837		correct = False;
3838	} else {
3839		printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
3840	}
3841
3842	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3843		printf("close - 2 failed (%s)\n", cli_errstr(cli1));
3844		return False;
3845	}
3846
3847	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3848	cli_unlink(cli1, fname1, aSYSTEM | aHIDDEN);
3849
3850	if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS, FILE_ATTRIBUTE_NORMAL,
3851				   FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
3852		printf("Third open failed - %s\n", cli_errstr(cli1));
3853		return False;
3854	}
3855
3856
3857#if 0
3858  {
3859	uint16_t fnum2;
3860
3861	if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
3862				   FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
3863		printf("Fourth open failed - %s\n", cli_errstr(cli1));
3864		return False;
3865	}
3866	if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum2, true))) {
3867		printf("[8] setting delete_on_close on file failed !\n");
3868		return False;
3869	}
3870
3871	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
3872		printf("close - 4 failed (%s)\n", cli_errstr(cli1));
3873		return False;
3874	}
3875  }
3876#endif
3877
3878	if (!NT_STATUS_IS_OK(cli_rename(cli1, fname, fname1))) {
3879		printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", cli_errstr(cli1));
3880		correct = False;
3881	} else {
3882		printf("Third rename succeeded (SHARE_NONE)\n");
3883	}
3884
3885	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3886		printf("close - 3 failed (%s)\n", cli_errstr(cli1));
3887		return False;
3888	}
3889
3890	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3891	cli_unlink(cli1, fname1, aSYSTEM | aHIDDEN);
3892
3893        /*----*/
3894
3895	if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
3896				   FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
3897		printf("Fourth open failed - %s\n", cli_errstr(cli1));
3898		return False;
3899	}
3900
3901	if (!NT_STATUS_IS_OK(cli_rename(cli1, fname, fname1))) {
3902		printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", cli_errstr(cli1));
3903	} else {
3904		printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
3905		correct = False;
3906	}
3907
3908	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3909		printf("close - 4 failed (%s)\n", cli_errstr(cli1));
3910		return False;
3911	}
3912
3913	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3914	cli_unlink(cli1, fname1, aSYSTEM | aHIDDEN);
3915
3916        /*--*/
3917
3918	if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
3919				   FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
3920		printf("Fifth open failed - %s\n", cli_errstr(cli1));
3921		return False;
3922	}
3923
3924	if (!NT_STATUS_IS_OK(cli_rename(cli1, fname, fname1))) {
3925		printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n",
3926			cli_errstr(cli1));
3927		correct = False;
3928	} else {
3929		printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", cli_errstr(cli1));
3930	}
3931
3932        /*
3933         * Now check if the first name still exists ...
3934         */
3935
3936        /* if (!NT_STATUS_OP(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
3937				   FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
3938          printf("Opening original file after rename of open file fails: %s\n",
3939              cli_errstr(cli1));
3940        }
3941        else {
3942          printf("Opening original file after rename of open file works ...\n");
3943          (void)cli_close(cli1, fnum2);
3944          } */
3945
3946        /*--*/
3947
3948
3949	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3950		printf("close - 5 failed (%s)\n", cli_errstr(cli1));
3951		return False;
3952	}
3953
3954	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3955	cli_unlink(cli1, fname1, aSYSTEM | aHIDDEN);
3956
3957	if (!torture_close_connection(cli1)) {
3958		correct = False;
3959	}
3960
3961	return correct;
3962}
3963
3964static bool run_pipe_number(int dummy)
3965{
3966	struct cli_state *cli1;
3967	const char *pipe_name = "\\SPOOLSS";
3968	uint16_t fnum;
3969	int num_pipes = 0;
3970
3971	printf("starting pipenumber test\n");
3972	if (!torture_open_connection(&cli1, 0)) {
3973		return False;
3974	}
3975
3976	cli_sockopt(cli1, sockops);
3977	while(1) {
3978		if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
3979				   FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN_IF, 0, 0, &fnum))) {
3980			printf("Open of pipe %s failed with error (%s)\n", pipe_name, cli_errstr(cli1));
3981			break;
3982		}
3983		num_pipes++;
3984		printf("\r%6d", num_pipes);
3985	}
3986
3987	printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
3988	torture_close_connection(cli1);
3989	return True;
3990}
3991
3992/*
3993  Test open mode returns on read-only files.
3994 */
3995static bool run_opentest(int dummy)
3996{
3997	static struct cli_state *cli1;
3998	static struct cli_state *cli2;
3999	const char *fname = "\\readonly.file";
4000	uint16_t fnum1, fnum2;
4001	char buf[20];
4002	SMB_OFF_T fsize;
4003	bool correct = True;
4004	char *tmp_path;
4005
4006	printf("starting open test\n");
4007
4008	if (!torture_open_connection(&cli1, 0)) {
4009		return False;
4010	}
4011
4012	cli_setatr(cli1, fname, 0, 0);
4013	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4014
4015	cli_sockopt(cli1, sockops);
4016
4017	if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1))) {
4018		printf("open of %s failed (%s)\n", fname, cli_errstr(cli1));
4019		return False;
4020	}
4021
4022	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4023		printf("close2 failed (%s)\n", cli_errstr(cli1));
4024		return False;
4025	}
4026
4027	if (!NT_STATUS_IS_OK(cli_setatr(cli1, fname, aRONLY, 0))) {
4028		printf("cli_setatr failed (%s)\n", cli_errstr(cli1));
4029		return False;
4030	}
4031
4032	if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1))) {
4033		printf("open of %s failed (%s)\n", fname, cli_errstr(cli1));
4034		return False;
4035	}
4036
4037	/* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
4038	cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4039
4040        if (check_error(__LINE__, cli1, ERRDOS, ERRnoaccess,
4041			NT_STATUS_ACCESS_DENIED)) {
4042		printf("correct error code ERRDOS/ERRnoaccess returned\n");
4043	}
4044
4045	printf("finished open test 1\n");
4046
4047	cli_close(cli1, fnum1);
4048
4049	/* Now try not readonly and ensure ERRbadshare is returned. */
4050
4051	cli_setatr(cli1, fname, 0, 0);
4052
4053	if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1))) {
4054		printf("open of %s failed (%s)\n", fname, cli_errstr(cli1));
4055		return False;
4056	}
4057
4058	/* This will fail - but the error should be ERRshare. */
4059	cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4060
4061	if (check_error(__LINE__, cli1, ERRDOS, ERRbadshare,
4062			NT_STATUS_SHARING_VIOLATION)) {
4063		printf("correct error code ERRDOS/ERRbadshare returned\n");
4064	}
4065
4066	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4067		printf("close2 failed (%s)\n", cli_errstr(cli1));
4068		return False;
4069	}
4070
4071	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4072
4073	printf("finished open test 2\n");
4074
4075	/* Test truncate open disposition on file opened for read. */
4076
4077	if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1))) {
4078		printf("(3) open (1) of %s failed (%s)\n", fname, cli_errstr(cli1));
4079		return False;
4080	}
4081
4082	/* write 20 bytes. */
4083
4084	memset(buf, '\0', 20);
4085
4086	if (cli_write(cli1, fnum1, 0, buf, 0, 20) != 20) {
4087		printf("write failed (%s)\n", cli_errstr(cli1));
4088		correct = False;
4089	}
4090
4091	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4092		printf("(3) close1 failed (%s)\n", cli_errstr(cli1));
4093		return False;
4094	}
4095
4096	/* Ensure size == 20. */
4097	if (!NT_STATUS_IS_OK(cli_getatr(cli1, fname, NULL, &fsize, NULL))) {
4098		printf("(3) getatr failed (%s)\n", cli_errstr(cli1));
4099		return False;
4100	}
4101
4102	if (fsize != 20) {
4103		printf("(3) file size != 20\n");
4104		return False;
4105	}
4106
4107	/* Now test if we can truncate a file opened for readonly. */
4108
4109	if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1))) {
4110		printf("(3) open (2) of %s failed (%s)\n", fname, cli_errstr(cli1));
4111		return False;
4112	}
4113
4114	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4115		printf("close2 failed (%s)\n", cli_errstr(cli1));
4116		return False;
4117	}
4118
4119	/* Ensure size == 0. */
4120	if (!NT_STATUS_IS_OK(cli_getatr(cli1, fname, NULL, &fsize, NULL))) {
4121		printf("(3) getatr failed (%s)\n", cli_errstr(cli1));
4122		return False;
4123	}
4124
4125	if (fsize != 0) {
4126		printf("(3) file size != 0\n");
4127		return False;
4128	}
4129	printf("finished open test 3\n");
4130
4131	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4132
4133
4134	printf("testing ctemp\n");
4135	if (!NT_STATUS_IS_OK(cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path))) {
4136		printf("ctemp failed (%s)\n", cli_errstr(cli1));
4137		return False;
4138	}
4139	printf("ctemp gave path %s\n", tmp_path);
4140	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4141		printf("close of temp failed (%s)\n", cli_errstr(cli1));
4142	}
4143	if (!NT_STATUS_IS_OK(cli_unlink(cli1, tmp_path, aSYSTEM | aHIDDEN))) {
4144		printf("unlink of temp failed (%s)\n", cli_errstr(cli1));
4145	}
4146
4147	/* Test the non-io opens... */
4148
4149	if (!torture_open_connection(&cli2, 1)) {
4150		return False;
4151	}
4152
4153	cli_setatr(cli2, fname, 0, 0);
4154	cli_unlink(cli2, fname, aSYSTEM | aHIDDEN);
4155
4156	cli_sockopt(cli2, sockops);
4157
4158	printf("TEST #1 testing 2 non-io opens (no delete)\n");
4159
4160	if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4161				   FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4162		printf("test 1 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4163		return False;
4164	}
4165
4166	if (!NT_STATUS_IS_OK(cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4167				   FILE_SHARE_NONE, FILE_OPEN_IF, 0, 0, &fnum2))) {
4168		printf("test 1 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4169		return False;
4170	}
4171
4172	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4173		printf("test 1 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4174		return False;
4175	}
4176	if (!NT_STATUS_IS_OK(cli_close(cli2, fnum2))) {
4177		printf("test 1 close 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4178		return False;
4179	}
4180
4181	printf("non-io open test #1 passed.\n");
4182
4183	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4184
4185	printf("TEST #2 testing 2 non-io opens (first with delete)\n");
4186
4187	if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4188				   FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4189		printf("test 2 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4190		return False;
4191	}
4192
4193	if (!NT_STATUS_IS_OK(cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4194				   FILE_SHARE_NONE, FILE_OPEN_IF, 0, 0, &fnum2))) {
4195		printf("test 2 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4196		return False;
4197	}
4198
4199	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4200		printf("test 1 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4201		return False;
4202	}
4203	if (!NT_STATUS_IS_OK(cli_close(cli2, fnum2))) {
4204		printf("test 1 close 2 of %s failed (%s)\n", fname, cli_errstr(cli1));
4205		return False;
4206	}
4207
4208	printf("non-io open test #2 passed.\n");
4209
4210	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4211
4212	printf("TEST #3 testing 2 non-io opens (second with delete)\n");
4213
4214	if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4215				   FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4216		printf("test 3 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4217		return False;
4218	}
4219
4220	if (!NT_STATUS_IS_OK(cli_ntcreate(cli2, fname, 0, DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4221				   FILE_SHARE_NONE, FILE_OPEN_IF, 0, 0, &fnum2))) {
4222		printf("test 3 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4223		return False;
4224	}
4225
4226	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4227		printf("test 3 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4228		return False;
4229	}
4230	if (!NT_STATUS_IS_OK(cli_close(cli2, fnum2))) {
4231		printf("test 3 close 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4232		return False;
4233	}
4234
4235	printf("non-io open test #3 passed.\n");
4236
4237	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4238
4239	printf("TEST #4 testing 2 non-io opens (both with delete)\n");
4240
4241	if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4242				   FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4243		printf("test 4 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4244		return False;
4245	}
4246
4247	if (NT_STATUS_IS_OK(cli_ntcreate(cli2, fname, 0, DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4248				   FILE_SHARE_NONE, FILE_OPEN_IF, 0, 0, &fnum2))) {
4249		printf("test 4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, cli_errstr(cli2));
4250		return False;
4251	}
4252
4253	printf("test 3 open 2 of %s gave %s (correct error should be %s)\n", fname, cli_errstr(cli2), "sharing violation");
4254
4255	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4256		printf("test 4 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4257		return False;
4258	}
4259
4260	printf("non-io open test #4 passed.\n");
4261
4262	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4263
4264	printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
4265
4266	if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4267				   FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4268		printf("test 5 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4269		return False;
4270	}
4271
4272	if (!NT_STATUS_IS_OK(cli_ntcreate(cli2, fname, 0, DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4273				   FILE_SHARE_DELETE, FILE_OPEN_IF, 0, 0, &fnum2))) {
4274		printf("test 5 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4275		return False;
4276	}
4277
4278	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4279		printf("test 5 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4280		return False;
4281	}
4282
4283	if (!NT_STATUS_IS_OK(cli_close(cli2, fnum2))) {
4284		printf("test 5 close 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4285		return False;
4286	}
4287
4288	printf("non-io open test #5 passed.\n");
4289
4290	printf("TEST #6 testing 1 non-io open, one io open\n");
4291
4292	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4293
4294	if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
4295				   FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4296		printf("test 6 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4297		return False;
4298	}
4299
4300	if (!NT_STATUS_IS_OK(cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4301				   FILE_SHARE_READ, FILE_OPEN_IF, 0, 0, &fnum2))) {
4302		printf("test 6 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4303		return False;
4304	}
4305
4306	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4307		printf("test 6 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4308		return False;
4309	}
4310
4311	if (!NT_STATUS_IS_OK(cli_close(cli2, fnum2))) {
4312		printf("test 6 close 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4313		return False;
4314	}
4315
4316	printf("non-io open test #6 passed.\n");
4317
4318	printf("TEST #7 testing 1 non-io open, one io open with delete\n");
4319
4320	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4321
4322	if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
4323				   FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4324		printf("test 7 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4325		return False;
4326	}
4327
4328	if (NT_STATUS_IS_OK(cli_ntcreate(cli2, fname, 0, DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4329				   FILE_SHARE_READ|FILE_SHARE_DELETE, FILE_OPEN_IF, 0, 0, &fnum2))) {
4330		printf("test 7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, cli_errstr(cli2));
4331		return False;
4332	}
4333
4334	printf("test 7 open 2 of %s gave %s (correct error should be %s)\n", fname, cli_errstr(cli2), "sharing violation");
4335
4336	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4337		printf("test 7 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4338		return False;
4339	}
4340
4341	printf("non-io open test #7 passed.\n");
4342
4343	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4344
4345	if (!torture_close_connection(cli1)) {
4346		correct = False;
4347	}
4348	if (!torture_close_connection(cli2)) {
4349		correct = False;
4350	}
4351
4352	return correct;
4353}
4354
4355/*
4356  Test POSIX open /mkdir calls.
4357 */
4358static bool run_simple_posix_open_test(int dummy)
4359{
4360	static struct cli_state *cli1;
4361	const char *fname = "posix:file";
4362	const char *hname = "posix:hlink";
4363	const char *sname = "posix:symlink";
4364	const char *dname = "posix:dir";
4365	char buf[10];
4366	char namebuf[11];
4367	uint16 major, minor;
4368	uint32 caplow, caphigh;
4369	uint16_t fnum1 = (uint16_t)-1;
4370	SMB_STRUCT_STAT sbuf;
4371	bool correct = false;
4372	NTSTATUS status;
4373
4374	printf("Starting simple POSIX open test\n");
4375
4376	if (!torture_open_connection(&cli1, 0)) {
4377		return false;
4378	}
4379
4380	cli_sockopt(cli1, sockops);
4381
4382	if (!SERVER_HAS_UNIX_CIFS(cli1)) {
4383		printf("Server doesn't support UNIX CIFS extensions.\n");
4384		return false;
4385	}
4386
4387	status = cli_unix_extensions_version(cli1, &major, &minor, &caplow,
4388					     &caphigh);
4389	if (!NT_STATUS_IS_OK(status)) {
4390		printf("Server didn't return UNIX CIFS extensions: %s\n",
4391		       nt_errstr(status));
4392		return false;
4393	}
4394
4395	if (!cli_set_unix_extensions_capabilities(cli1,
4396			major, minor, caplow, caphigh)) {
4397		printf("Server doesn't support setting UNIX CIFS extensions.\n");
4398		return false;
4399        }
4400
4401	cli_setatr(cli1, fname, 0, 0);
4402	cli_posix_unlink(cli1, fname);
4403	cli_setatr(cli1, dname, 0, 0);
4404	cli_posix_rmdir(cli1, dname);
4405	cli_setatr(cli1, hname, 0, 0);
4406	cli_posix_unlink(cli1, hname);
4407	cli_setatr(cli1, sname, 0, 0);
4408	cli_posix_unlink(cli1, sname);
4409
4410	/* Create a directory. */
4411	if (!NT_STATUS_IS_OK(cli_posix_mkdir(cli1, dname, 0777))) {
4412		printf("POSIX mkdir of %s failed (%s)\n", dname, cli_errstr(cli1));
4413		goto out;
4414	}
4415
4416	if (!NT_STATUS_IS_OK(cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1))) {
4417		printf("POSIX create of %s failed (%s)\n", fname, cli_errstr(cli1));
4418		goto out;
4419	}
4420
4421	/* Test ftruncate - set file size. */
4422	if (!NT_STATUS_IS_OK(cli_ftruncate(cli1, fnum1, 1000))) {
4423		printf("ftruncate failed (%s)\n", cli_errstr(cli1));
4424		goto out;
4425	}
4426
4427	/* Ensure st_size == 1000 */
4428	if (!NT_STATUS_IS_OK(cli_posix_stat(cli1, fname, &sbuf))) {
4429		printf("stat failed (%s)\n", cli_errstr(cli1));
4430		goto out;
4431	}
4432
4433	if (sbuf.st_ex_size != 1000) {
4434		printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
4435		goto out;
4436	}
4437
4438	/* Test ftruncate - set file size back to zero. */
4439	if (!NT_STATUS_IS_OK(cli_ftruncate(cli1, fnum1, 0))) {
4440		printf("ftruncate failed (%s)\n", cli_errstr(cli1));
4441		goto out;
4442	}
4443
4444	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4445		printf("close failed (%s)\n", cli_errstr(cli1));
4446		goto out;
4447	}
4448
4449	/* Now open the file again for read only. */
4450	if (!NT_STATUS_IS_OK(cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1))) {
4451		printf("POSIX open of %s failed (%s)\n", fname, cli_errstr(cli1));
4452		goto out;
4453	}
4454
4455	/* Now unlink while open. */
4456	if (!NT_STATUS_IS_OK(cli_posix_unlink(cli1, fname))) {
4457		printf("POSIX unlink of %s failed (%s)\n", fname, cli_errstr(cli1));
4458		goto out;
4459	}
4460
4461	if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4462		printf("close(2) failed (%s)\n", cli_errstr(cli1));
4463		goto out;
4464	}
4465
4466	/* Ensure the file has gone. */
4467	if (NT_STATUS_IS_OK(cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1))) {
4468		printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
4469		goto out;
4470	}
4471
4472	/* What happens when we try and POSIX open a directory ? */
4473	if (NT_STATUS_IS_OK(cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1))) {
4474		printf("POSIX open of directory %s succeeded, should have failed.\n", fname);
4475		goto out;
4476	} else {
4477		if (!check_error(__LINE__, cli1, ERRDOS, EISDIR,
4478				NT_STATUS_FILE_IS_A_DIRECTORY)) {
4479			goto out;
4480		}
4481	}
4482
4483	/* Create the file. */
4484	if (!NT_STATUS_IS_OK(cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1))) {
4485		printf("POSIX create of %s failed (%s)\n", fname, cli_errstr(cli1));
4486		goto out;
4487	}
4488
4489	/* Write some data into it. */
4490	if (cli_write(cli1, fnum1, 0, "TEST DATA\n", 0, 10) != 10) {
4491		printf("cli_write failed: %s\n", cli_errstr(cli1));
4492		goto out;
4493	}
4494
4495	cli_close(cli1, fnum1);
4496
4497	/* Now create a hardlink. */
4498	if (!NT_STATUS_IS_OK(cli_posix_hardlink(cli1, fname, hname))) {
4499		printf("POSIX hardlink of %s failed (%s)\n", hname, cli_errstr(cli1));
4500		goto out;
4501	}
4502
4503	/* Now create a symlink. */
4504	if (!NT_STATUS_IS_OK(cli_posix_symlink(cli1, fname, sname))) {
4505		printf("POSIX symlink of %s failed (%s)\n", sname, cli_errstr(cli1));
4506		goto out;
4507	}
4508
4509	/* Open the hardlink for read. */
4510	if (!NT_STATUS_IS_OK(cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1))) {
4511		printf("POSIX open of %s failed (%s)\n", hname, cli_errstr(cli1));
4512		goto out;
4513	}
4514
4515	if (cli_read(cli1, fnum1, buf, 0, 10) != 10) {
4516		printf("POSIX read of %s failed (%s)\n", hname, cli_errstr(cli1));
4517		goto out;
4518	}
4519
4520	if (memcmp(buf, "TEST DATA\n", 10)) {
4521		printf("invalid data read from hardlink\n");
4522		goto out;
4523	}
4524
4525	/* Do a POSIX lock/unlock. */
4526	if (!NT_STATUS_IS_OK(cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK))) {
4527		printf("POSIX lock failed %s\n", cli_errstr(cli1));
4528		goto out;
4529	}
4530
4531	/* Punch a hole in the locked area. */
4532	if (!NT_STATUS_IS_OK(cli_posix_unlock(cli1, fnum1, 10, 80))) {
4533		printf("POSIX unlock failed %s\n", cli_errstr(cli1));
4534		goto out;
4535	}
4536
4537	cli_close(cli1, fnum1);
4538
4539	/* Open the symlink for read - this should fail. A POSIX
4540	   client should not be doing opens on a symlink. */
4541	if (NT_STATUS_IS_OK(cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1))) {
4542		printf("POSIX open of %s succeeded (should have failed)\n", sname);
4543		goto out;
4544	} else {
4545		if (!check_error(__LINE__, cli1, ERRDOS, ERRbadpath,
4546				NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
4547			printf("POSIX open of %s should have failed "
4548				"with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
4549				"failed with %s instead.\n",
4550				sname, cli_errstr(cli1));
4551			goto out;
4552		}
4553	}
4554
4555	if (!NT_STATUS_IS_OK(cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf)))) {
4556		printf("POSIX readlink on %s failed (%s)\n", sname, cli_errstr(cli1));
4557		goto out;
4558	}
4559
4560	if (strcmp(namebuf, fname) != 0) {
4561		printf("POSIX readlink on %s failed to match name %s (read %s)\n",
4562			sname, fname, namebuf);
4563		goto out;
4564	}
4565
4566	if (!NT_STATUS_IS_OK(cli_posix_rmdir(cli1, dname))) {
4567		printf("POSIX rmdir failed (%s)\n", cli_errstr(cli1));
4568		goto out;
4569	}
4570
4571	printf("Simple POSIX open test passed\n");
4572	correct = true;
4573
4574  out:
4575
4576	if (fnum1 != (uint16_t)-1) {
4577		cli_close(cli1, fnum1);
4578		fnum1 = (uint16_t)-1;
4579	}
4580
4581	cli_setatr(cli1, sname, 0, 0);
4582	cli_posix_unlink(cli1, sname);
4583	cli_setatr(cli1, hname, 0, 0);
4584	cli_posix_unlink(cli1, hname);
4585	cli_setatr(cli1, fname, 0, 0);
4586	cli_posix_unlink(cli1, fname);
4587	cli_setatr(cli1, dname, 0, 0);
4588	cli_posix_rmdir(cli1, dname);
4589
4590	if (!torture_close_connection(cli1)) {
4591		correct = false;
4592	}
4593
4594	return correct;
4595}
4596
4597
4598static uint32 open_attrs_table[] = {
4599		FILE_ATTRIBUTE_NORMAL,
4600		FILE_ATTRIBUTE_ARCHIVE,
4601		FILE_ATTRIBUTE_READONLY,
4602		FILE_ATTRIBUTE_HIDDEN,
4603		FILE_ATTRIBUTE_SYSTEM,
4604
4605		FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
4606		FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
4607		FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
4608		FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
4609		FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
4610		FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
4611
4612		FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
4613		FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
4614		FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
4615		FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
4616};
4617
4618struct trunc_open_results {
4619	unsigned int num;
4620	uint32 init_attr;
4621	uint32 trunc_attr;
4622	uint32 result_attr;
4623};
4624
4625static struct trunc_open_results attr_results[] = {
4626	{ 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
4627	{ 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
4628	{ 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
4629	{ 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
4630	{ 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
4631	{ 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
4632	{ 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
4633	{ 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
4634	{ 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
4635	{ 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
4636	{ 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
4637	{ 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
4638	{ 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
4639	{ 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
4640	{ 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 },
4641	{ 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
4642	{ 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
4643	{ 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 },
4644	{ 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 },
4645	{ 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 },
4646	{ 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
4647	{ 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
4648	{ 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
4649	{ 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
4650	{ 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
4651	{ 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
4652};
4653
4654static bool run_openattrtest(int dummy)
4655{
4656	static struct cli_state *cli1;
4657	const char *fname = "\\openattr.file";
4658	uint16_t fnum1;
4659	bool correct = True;
4660	uint16 attr;
4661	unsigned int i, j, k, l;
4662
4663	printf("starting open attr test\n");
4664
4665	if (!torture_open_connection(&cli1, 0)) {
4666		return False;
4667	}
4668
4669	cli_sockopt(cli1, sockops);
4670
4671	for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32); i++) {
4672		cli_setatr(cli1, fname, 0, 0);
4673		cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4674		if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, open_attrs_table[i],
4675				   FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4676			printf("open %d (1) of %s failed (%s)\n", i, fname, cli_errstr(cli1));
4677			return False;
4678		}
4679
4680		if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4681			printf("close %d (1) of %s failed (%s)\n", i, fname, cli_errstr(cli1));
4682			return False;
4683		}
4684
4685		for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32); j++) {
4686			if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA, open_attrs_table[j],
4687					   FILE_SHARE_NONE, FILE_OVERWRITE, 0, 0, &fnum1))) {
4688				for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
4689					if (attr_results[l].num == k) {
4690						printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
4691								k, open_attrs_table[i],
4692								open_attrs_table[j],
4693								fname, NT_STATUS_V(cli_nt_error(cli1)), cli_errstr(cli1));
4694						correct = False;
4695					}
4696				}
4697				if (NT_STATUS_V(cli_nt_error(cli1)) != NT_STATUS_V(NT_STATUS_ACCESS_DENIED)) {
4698					printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
4699							k, open_attrs_table[i], open_attrs_table[j],
4700							cli_errstr(cli1));
4701					correct = False;
4702				}
4703#if 0
4704				printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
4705#endif
4706				k++;
4707				continue;
4708			}
4709
4710			if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4711				printf("close %d (2) of %s failed (%s)\n", j, fname, cli_errstr(cli1));
4712				return False;
4713			}
4714
4715			if (!NT_STATUS_IS_OK(cli_getatr(cli1, fname, &attr, NULL, NULL))) {
4716				printf("getatr(2) failed (%s)\n", cli_errstr(cli1));
4717				return False;
4718			}
4719
4720#if 0
4721			printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
4722					k,  open_attrs_table[i],  open_attrs_table[j], attr );
4723#endif
4724
4725			for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
4726				if (attr_results[l].num == k) {
4727					if (attr != attr_results[l].result_attr ||
4728							open_attrs_table[i] != attr_results[l].init_attr ||
4729							open_attrs_table[j] != attr_results[l].trunc_attr) {
4730						printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
4731						open_attrs_table[i],
4732						open_attrs_table[j],
4733						(unsigned int)attr,
4734						attr_results[l].result_attr);
4735						correct = False;
4736					}
4737					break;
4738				}
4739			}
4740			k++;
4741		}
4742	}
4743
4744	cli_setatr(cli1, fname, 0, 0);
4745	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4746
4747	printf("open attr test %s.\n", correct ? "passed" : "failed");
4748
4749	if (!torture_close_connection(cli1)) {
4750		correct = False;
4751	}
4752	return correct;
4753}
4754
4755static void list_fn(const char *mnt, file_info *finfo, const char *name, void *state)
4756{
4757
4758}
4759
4760/*
4761  test directory listing speed
4762 */
4763static bool run_dirtest(int dummy)
4764{
4765	int i;
4766	static struct cli_state *cli;
4767	uint16_t fnum;
4768	double t1;
4769	bool correct = True;
4770
4771	printf("starting directory test\n");
4772
4773	if (!torture_open_connection(&cli, 0)) {
4774		return False;
4775	}
4776
4777	cli_sockopt(cli, sockops);
4778
4779	srandom(0);
4780	for (i=0;i<torture_numops;i++) {
4781		fstring fname;
4782		slprintf(fname, sizeof(fname), "\\%x", (int)random());
4783		if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
4784			fprintf(stderr,"Failed to open %s\n", fname);
4785			return False;
4786		}
4787		cli_close(cli, fnum);
4788	}
4789
4790	t1 = end_timer();
4791
4792	printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
4793	printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
4794	printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
4795
4796	printf("dirtest core %g seconds\n", end_timer() - t1);
4797
4798	srandom(0);
4799	for (i=0;i<torture_numops;i++) {
4800		fstring fname;
4801		slprintf(fname, sizeof(fname), "\\%x", (int)random());
4802		cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
4803	}
4804
4805	if (!torture_close_connection(cli)) {
4806		correct = False;
4807	}
4808
4809	printf("finished dirtest\n");
4810
4811	return correct;
4812}
4813
4814static void del_fn(const char *mnt, file_info *finfo, const char *mask, void *state)
4815{
4816	struct cli_state *pcli = (struct cli_state *)state;
4817	fstring fname;
4818	slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
4819
4820	if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
4821		return;
4822
4823	if (finfo->mode & aDIR) {
4824		if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
4825			printf("del_fn: failed to rmdir %s\n,", fname );
4826	} else {
4827		if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, aSYSTEM | aHIDDEN)))
4828			printf("del_fn: failed to unlink %s\n,", fname );
4829	}
4830}
4831
4832
4833/*
4834  sees what IOCTLs are supported
4835 */
4836bool torture_ioctl_test(int dummy)
4837{
4838	static struct cli_state *cli;
4839	uint16_t device, function;
4840	uint16_t fnum;
4841	const char *fname = "\\ioctl.dat";
4842	DATA_BLOB blob;
4843	NTSTATUS status;
4844
4845	if (!torture_open_connection(&cli, 0)) {
4846		return False;
4847	}
4848
4849	printf("starting ioctl test\n");
4850
4851	cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
4852
4853	if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum))) {
4854		printf("open of %s failed (%s)\n", fname, cli_errstr(cli));
4855		return False;
4856	}
4857
4858	status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
4859	printf("ioctl device info: %s\n", cli_errstr(cli));
4860
4861	status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
4862	printf("ioctl job info: %s\n", cli_errstr(cli));
4863
4864	for (device=0;device<0x100;device++) {
4865		printf("testing device=0x%x\n", device);
4866		for (function=0;function<0x100;function++) {
4867			uint32 code = (device<<16) | function;
4868
4869			status = cli_raw_ioctl(cli, fnum, code, &blob);
4870
4871			if (NT_STATUS_IS_OK(status)) {
4872				printf("ioctl 0x%x OK : %d bytes\n", (int)code,
4873				       (int)blob.length);
4874				data_blob_free(&blob);
4875			}
4876		}
4877	}
4878
4879	if (!torture_close_connection(cli)) {
4880		return False;
4881	}
4882
4883	return True;
4884}
4885
4886
4887/*
4888  tries varients of chkpath
4889 */
4890bool torture_chkpath_test(int dummy)
4891{
4892	static struct cli_state *cli;
4893	uint16_t fnum;
4894	bool ret;
4895
4896	if (!torture_open_connection(&cli, 0)) {
4897		return False;
4898	}
4899
4900	printf("starting chkpath test\n");
4901
4902	/* cleanup from an old run */
4903	cli_rmdir(cli, "\\chkpath.dir\\dir2");
4904	cli_unlink(cli, "\\chkpath.dir\\*", aSYSTEM | aHIDDEN);
4905	cli_rmdir(cli, "\\chkpath.dir");
4906
4907	if (!NT_STATUS_IS_OK(cli_mkdir(cli, "\\chkpath.dir"))) {
4908		printf("mkdir1 failed : %s\n", cli_errstr(cli));
4909		return False;
4910	}
4911
4912	if (!NT_STATUS_IS_OK(cli_mkdir(cli, "\\chkpath.dir\\dir2"))) {
4913		printf("mkdir2 failed : %s\n", cli_errstr(cli));
4914		return False;
4915	}
4916
4917	if (!NT_STATUS_IS_OK(cli_open(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum))) {
4918		printf("open1 failed (%s)\n", cli_errstr(cli));
4919		return False;
4920	}
4921	cli_close(cli, fnum);
4922
4923	if (!NT_STATUS_IS_OK(cli_chkpath(cli, "\\chkpath.dir"))) {
4924		printf("chkpath1 failed: %s\n", cli_errstr(cli));
4925		ret = False;
4926	}
4927
4928	if (!NT_STATUS_IS_OK(cli_chkpath(cli, "\\chkpath.dir\\dir2"))) {
4929		printf("chkpath2 failed: %s\n", cli_errstr(cli));
4930		ret = False;
4931	}
4932
4933	if (!NT_STATUS_IS_OK(cli_chkpath(cli, "\\chkpath.dir\\foo.txt"))) {
4934		ret = check_error(__LINE__, cli, ERRDOS, ERRbadpath,
4935				  NT_STATUS_NOT_A_DIRECTORY);
4936	} else {
4937		printf("* chkpath on a file should fail\n");
4938		ret = False;
4939	}
4940
4941	if (!NT_STATUS_IS_OK(cli_chkpath(cli, "\\chkpath.dir\\bar.txt"))) {
4942		ret = check_error(__LINE__, cli, ERRDOS, ERRbadfile,
4943				  NT_STATUS_OBJECT_NAME_NOT_FOUND);
4944	} else {
4945		printf("* chkpath on a non existant file should fail\n");
4946		ret = False;
4947	}
4948
4949	if (!NT_STATUS_IS_OK(cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt"))) {
4950		ret = check_error(__LINE__, cli, ERRDOS, ERRbadpath,
4951				  NT_STATUS_OBJECT_PATH_NOT_FOUND);
4952	} else {
4953		printf("* chkpath on a non existent component should fail\n");
4954		ret = False;
4955	}
4956
4957	cli_rmdir(cli, "\\chkpath.dir\\dir2");
4958	cli_unlink(cli, "\\chkpath.dir\\*", aSYSTEM | aHIDDEN);
4959	cli_rmdir(cli, "\\chkpath.dir");
4960
4961	if (!torture_close_connection(cli)) {
4962		return False;
4963	}
4964
4965	return ret;
4966}
4967
4968static bool run_eatest(int dummy)
4969{
4970	static struct cli_state *cli;
4971	const char *fname = "\\eatest.txt";
4972	bool correct = True;
4973	uint16_t fnum;
4974	int i;
4975	size_t num_eas;
4976	struct ea_struct *ea_list = NULL;
4977	TALLOC_CTX *mem_ctx = talloc_init("eatest");
4978
4979	printf("starting eatest\n");
4980
4981	if (!torture_open_connection(&cli, 0)) {
4982		talloc_destroy(mem_ctx);
4983		return False;
4984	}
4985
4986	cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
4987	if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0,
4988				   FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
4989				   FILE_SHARE_NONE, FILE_OVERWRITE_IF,
4990				   0x4044, 0, &fnum))) {
4991		printf("open failed - %s\n", cli_errstr(cli));
4992		talloc_destroy(mem_ctx);
4993		return False;
4994	}
4995
4996	for (i = 0; i < 10; i++) {
4997		fstring ea_name, ea_val;
4998
4999		slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
5000		memset(ea_val, (char)i+1, i+1);
5001		if (!cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1)) {
5002			printf("ea_set of name %s failed - %s\n", ea_name, cli_errstr(cli));
5003			talloc_destroy(mem_ctx);
5004			return False;
5005		}
5006	}
5007
5008	cli_close(cli, fnum);
5009	for (i = 0; i < 10; i++) {
5010		fstring ea_name, ea_val;
5011
5012		slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
5013		memset(ea_val, (char)i+1, i+1);
5014		if (!cli_set_ea_path(cli, fname, ea_name, ea_val, i+1)) {
5015			printf("ea_set of name %s failed - %s\n", ea_name, cli_errstr(cli));
5016			talloc_destroy(mem_ctx);
5017			return False;
5018		}
5019	}
5020
5021	if (!cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list)) {
5022		printf("ea_get list failed - %s\n", cli_errstr(cli));
5023		correct = False;
5024	}
5025
5026	printf("num_eas = %d\n", (int)num_eas);
5027
5028	if (num_eas != 20) {
5029		printf("Should be 20 EA's stored... failing.\n");
5030		correct = False;
5031	}
5032
5033	for (i = 0; i < num_eas; i++) {
5034		printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
5035		dump_data(0, ea_list[i].value.data,
5036			  ea_list[i].value.length);
5037	}
5038
5039	/* Setting EA's to zero length deletes them. Test this */
5040	printf("Now deleting all EA's - case indepenent....\n");
5041
5042#if 1
5043	cli_set_ea_path(cli, fname, "", "", 0);
5044#else
5045	for (i = 0; i < 20; i++) {
5046		fstring ea_name;
5047		slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
5048		if (!cli_set_ea_path(cli, fname, ea_name, "", 0)) {
5049			printf("ea_set of name %s failed - %s\n", ea_name, cli_errstr(cli));
5050			talloc_destroy(mem_ctx);
5051			return False;
5052		}
5053	}
5054#endif
5055
5056	if (!cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list)) {
5057		printf("ea_get list failed - %s\n", cli_errstr(cli));
5058		correct = False;
5059	}
5060
5061	printf("num_eas = %d\n", (int)num_eas);
5062	for (i = 0; i < num_eas; i++) {
5063		printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
5064		dump_data(0, ea_list[i].value.data,
5065			  ea_list[i].value.length);
5066	}
5067
5068	if (num_eas != 0) {
5069		printf("deleting EA's failed.\n");
5070		correct = False;
5071	}
5072
5073	/* Try and delete a non existant EA. */
5074	if (!cli_set_ea_path(cli, fname, "foo", "", 0)) {
5075		printf("deleting non-existant EA 'foo' should succeed. %s\n", cli_errstr(cli));
5076		correct = False;
5077	}
5078
5079	talloc_destroy(mem_ctx);
5080	if (!torture_close_connection(cli)) {
5081		correct = False;
5082	}
5083
5084	return correct;
5085}
5086
5087static bool run_dirtest1(int dummy)
5088{
5089	int i;
5090	static struct cli_state *cli;
5091	uint16_t fnum;
5092	int num_seen;
5093	bool correct = True;
5094
5095	printf("starting directory test\n");
5096
5097	if (!torture_open_connection(&cli, 0)) {
5098		return False;
5099	}
5100
5101	cli_sockopt(cli, sockops);
5102
5103	cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
5104	cli_list(cli, "\\LISTDIR\\*", aDIR, del_fn, cli);
5105	cli_rmdir(cli, "\\LISTDIR");
5106	cli_mkdir(cli, "\\LISTDIR");
5107
5108	/* Create 1000 files and 1000 directories. */
5109	for (i=0;i<1000;i++) {
5110		fstring fname;
5111		slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
5112		if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
5113				   FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum))) {
5114			fprintf(stderr,"Failed to open %s\n", fname);
5115			return False;
5116		}
5117		cli_close(cli, fnum);
5118	}
5119	for (i=0;i<1000;i++) {
5120		fstring fname;
5121		slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
5122		if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
5123			fprintf(stderr,"Failed to open %s\n", fname);
5124			return False;
5125		}
5126	}
5127
5128	/* Now ensure that doing an old list sees both files and directories. */
5129	num_seen = cli_list_old(cli, "\\LISTDIR\\*", aDIR, list_fn, NULL);
5130	printf("num_seen = %d\n", num_seen );
5131	/* We should see 100 files + 1000 directories + . and .. */
5132	if (num_seen != 2002)
5133		correct = False;
5134
5135	/* Ensure if we have the "must have" bits we only see the
5136	 * relevent entries.
5137	 */
5138	num_seen = cli_list_old(cli, "\\LISTDIR\\*", (aDIR<<8)|aDIR, list_fn, NULL);
5139	printf("num_seen = %d\n", num_seen );
5140	if (num_seen != 1002)
5141		correct = False;
5142
5143	num_seen = cli_list_old(cli, "\\LISTDIR\\*", (aARCH<<8)|aDIR, list_fn, NULL);
5144	printf("num_seen = %d\n", num_seen );
5145	if (num_seen != 1000)
5146		correct = False;
5147
5148	/* Delete everything. */
5149	cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
5150	cli_list(cli, "\\LISTDIR\\*", aDIR, del_fn, cli);
5151	cli_rmdir(cli, "\\LISTDIR");
5152
5153#if 0
5154	printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
5155	printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
5156	printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
5157#endif
5158
5159	if (!torture_close_connection(cli)) {
5160		correct = False;
5161	}
5162
5163	printf("finished dirtest1\n");
5164
5165	return correct;
5166}
5167
5168static bool run_error_map_extract(int dummy) {
5169
5170	static struct cli_state *c_dos;
5171	static struct cli_state *c_nt;
5172	NTSTATUS status;
5173
5174	uint32 error;
5175
5176	uint32 flgs2, errnum;
5177        uint8 errclass;
5178
5179	NTSTATUS nt_status;
5180
5181	fstring user;
5182
5183	/* NT-Error connection */
5184
5185	if (!(c_nt = open_nbt_connection())) {
5186		return False;
5187	}
5188
5189	c_nt->use_spnego = False;
5190
5191	status = cli_negprot(c_nt);
5192
5193	if (!NT_STATUS_IS_OK(status)) {
5194		printf("%s rejected the NT-error negprot (%s)\n", host,
5195		       nt_errstr(status));
5196		cli_shutdown(c_nt);
5197		return False;
5198	}
5199
5200	if (!NT_STATUS_IS_OK(cli_session_setup(c_nt, "", "", 0, "", 0,
5201					       workgroup))) {
5202		printf("%s rejected the NT-error initial session setup (%s)\n",host, cli_errstr(c_nt));
5203		return False;
5204	}
5205
5206	/* DOS-Error connection */
5207
5208	if (!(c_dos = open_nbt_connection())) {
5209		return False;
5210	}
5211
5212	c_dos->use_spnego = False;
5213	c_dos->force_dos_errors = True;
5214
5215	status = cli_negprot(c_dos);
5216	if (!NT_STATUS_IS_OK(status)) {
5217		printf("%s rejected the DOS-error negprot (%s)\n", host,
5218		       nt_errstr(status));
5219		cli_shutdown(c_dos);
5220		return False;
5221	}
5222
5223	if (!NT_STATUS_IS_OK(cli_session_setup(c_dos, "", "", 0, "", 0,
5224					       workgroup))) {
5225		printf("%s rejected the DOS-error initial session setup (%s)\n",host, cli_errstr(c_dos));
5226		return False;
5227	}
5228
5229	for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
5230		fstr_sprintf(user, "%X", error);
5231
5232		if (NT_STATUS_IS_OK(cli_session_setup(c_nt, user,
5233						      password, strlen(password),
5234						      password, strlen(password),
5235						      workgroup))) {
5236			printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
5237		}
5238
5239		flgs2 = SVAL(c_nt->inbuf,smb_flg2);
5240
5241		/* Case #1: 32-bit NT errors */
5242		if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) {
5243			nt_status = NT_STATUS(IVAL(c_nt->inbuf,smb_rcls));
5244		} else {
5245			printf("/** Dos error on NT connection! (%s) */\n",
5246			       cli_errstr(c_nt));
5247			nt_status = NT_STATUS(0xc0000000);
5248		}
5249
5250		if (NT_STATUS_IS_OK(cli_session_setup(c_dos, user,
5251						      password, strlen(password),
5252						      password, strlen(password),
5253						      workgroup))) {
5254			printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
5255		}
5256		flgs2 = SVAL(c_dos->inbuf,smb_flg2), errnum;
5257
5258		/* Case #1: 32-bit NT errors */
5259		if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) {
5260			printf("/** NT error on DOS connection! (%s) */\n",
5261			       cli_errstr(c_nt));
5262			errnum = errclass = 0;
5263		} else {
5264			cli_dos_error(c_dos, &errclass, &errnum);
5265		}
5266
5267		if (NT_STATUS_V(nt_status) != error) {
5268			printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
5269			       get_nt_error_c_code(NT_STATUS(error)),
5270			       get_nt_error_c_code(nt_status));
5271		}
5272
5273		printf("\t{%s,\t%s,\t%s},\n",
5274		       smb_dos_err_class(errclass),
5275		       smb_dos_err_name(errclass, errnum),
5276		       get_nt_error_c_code(NT_STATUS(error)));
5277	}
5278	return True;
5279}
5280
5281static bool run_sesssetup_bench(int dummy)
5282{
5283	static struct cli_state *c;
5284	const char *fname = "\\file.dat";
5285	uint16_t fnum;
5286	NTSTATUS status;
5287	int i;
5288
5289	if (!torture_open_connection(&c, 0)) {
5290		return false;
5291	}
5292
5293	if (!NT_STATUS_IS_OK(cli_ntcreate(
5294			c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5295			FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5296			FILE_DELETE_ON_CLOSE, 0, &fnum))) {
5297		d_printf("open %s failed: %s\n", fname, cli_errstr(c));
5298		return false;
5299	}
5300
5301	for (i=0; i<torture_numops; i++) {
5302		status = cli_session_setup(
5303			c, username,
5304			password, strlen(password),
5305			password, strlen(password),
5306			workgroup);
5307		if (!NT_STATUS_IS_OK(status)) {
5308			d_printf("(%s) cli_session_setup failed: %s\n",
5309				 __location__, nt_errstr(status));
5310			return false;
5311		}
5312
5313		d_printf("\r%d   ", (int)c->vuid);
5314
5315		if (!cli_ulogoff(c)) {
5316			d_printf("(%s) cli_ulogoff failed: %s\n",
5317				 __location__, cli_errstr(c));
5318			return false;
5319		}
5320		c->vuid = 0;
5321	}
5322
5323	return true;
5324}
5325
5326static bool subst_test(const char *str, const char *user, const char *domain,
5327		       uid_t uid, gid_t gid, const char *expected)
5328{
5329	char *subst;
5330	bool result = true;
5331
5332	subst = talloc_sub_specified(talloc_tos(), str, user, domain, uid, gid);
5333
5334	if (strcmp(subst, expected) != 0) {
5335		printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
5336		       "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
5337		       expected);
5338		result = false;
5339	}
5340
5341	TALLOC_FREE(subst);
5342	return result;
5343}
5344
5345static void chain1_open_completion(struct tevent_req *req)
5346{
5347	uint16_t fnum;
5348	NTSTATUS status;
5349	status = cli_open_recv(req, &fnum);
5350	TALLOC_FREE(req);
5351
5352	d_printf("cli_open_recv returned %s: %d\n",
5353		 nt_errstr(status),
5354		 NT_STATUS_IS_OK(status) ? fnum : -1);
5355}
5356
5357static void chain1_write_completion(struct tevent_req *req)
5358{
5359	size_t written;
5360	NTSTATUS status;
5361	status = cli_write_andx_recv(req, &written);
5362	TALLOC_FREE(req);
5363
5364	d_printf("cli_write_andx_recv returned %s: %d\n",
5365		 nt_errstr(status),
5366		 NT_STATUS_IS_OK(status) ? (int)written : -1);
5367}
5368
5369static void chain1_close_completion(struct tevent_req *req)
5370{
5371	NTSTATUS status;
5372	bool *done = (bool *)tevent_req_callback_data_void(req);
5373
5374	status = cli_close_recv(req);
5375	*done = true;
5376
5377	TALLOC_FREE(req);
5378
5379	d_printf("cli_close returned %s\n", nt_errstr(status));
5380}
5381
5382static bool run_chain1(int dummy)
5383{
5384	struct cli_state *cli1;
5385	struct event_context *evt = event_context_init(NULL);
5386	struct tevent_req *reqs[3], *smbreqs[3];
5387	bool done = false;
5388	const char *str = "foobar";
5389	NTSTATUS status;
5390
5391	printf("starting chain1 test\n");
5392	if (!torture_open_connection(&cli1, 0)) {
5393		return False;
5394	}
5395
5396	cli_sockopt(cli1, sockops);
5397
5398	reqs[0] = cli_open_create(talloc_tos(), evt, cli1, "\\test",
5399				  O_CREAT|O_RDWR, 0, &smbreqs[0]);
5400	if (reqs[0] == NULL) return false;
5401	tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
5402
5403
5404	reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
5405					(uint8_t *)str, 0, strlen(str)+1,
5406					smbreqs, 1, &smbreqs[1]);
5407	if (reqs[1] == NULL) return false;
5408	tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
5409
5410	reqs[2] = cli_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
5411	if (reqs[2] == NULL) return false;
5412	tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
5413
5414	status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
5415	if (!NT_STATUS_IS_OK(status)) {
5416		return false;
5417	}
5418
5419	while (!done) {
5420		event_loop_once(evt);
5421	}
5422
5423	torture_close_connection(cli1);
5424	return True;
5425}
5426
5427static void chain2_sesssetup_completion(struct tevent_req *req)
5428{
5429	NTSTATUS status;
5430	status = cli_session_setup_guest_recv(req);
5431	d_printf("sesssetup returned %s\n", nt_errstr(status));
5432}
5433
5434static void chain2_tcon_completion(struct tevent_req *req)
5435{
5436	bool *done = (bool *)tevent_req_callback_data_void(req);
5437	NTSTATUS status;
5438	status = cli_tcon_andx_recv(req);
5439	d_printf("tcon_and_x returned %s\n", nt_errstr(status));
5440	*done = true;
5441}
5442
5443static bool run_chain2(int dummy)
5444{
5445	struct cli_state *cli1;
5446	struct event_context *evt = event_context_init(NULL);
5447	struct tevent_req *reqs[2], *smbreqs[2];
5448	bool done = false;
5449	NTSTATUS status;
5450
5451	printf("starting chain2 test\n");
5452	status = cli_start_connection(&cli1, global_myname(), host, NULL,
5453				      port_to_use, Undefined, 0, NULL);
5454	if (!NT_STATUS_IS_OK(status)) {
5455		return False;
5456	}
5457
5458	cli_sockopt(cli1, sockops);
5459
5460	reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
5461						 &smbreqs[0]);
5462	if (reqs[0] == NULL) return false;
5463	tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
5464
5465	reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
5466				       "?????", NULL, 0, &smbreqs[1]);
5467	if (reqs[1] == NULL) return false;
5468	tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
5469
5470	status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
5471	if (!NT_STATUS_IS_OK(status)) {
5472		return false;
5473	}
5474
5475	while (!done) {
5476		event_loop_once(evt);
5477	}
5478
5479	torture_close_connection(cli1);
5480	return True;
5481}
5482
5483
5484struct torture_createdel_state {
5485	struct tevent_context *ev;
5486	struct cli_state *cli;
5487};
5488
5489static void torture_createdel_created(struct tevent_req *subreq);
5490static void torture_createdel_closed(struct tevent_req *subreq);
5491
5492static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
5493						 struct tevent_context *ev,
5494						 struct cli_state *cli,
5495						 const char *name)
5496{
5497	struct tevent_req *req, *subreq;
5498	struct torture_createdel_state *state;
5499
5500	req = tevent_req_create(mem_ctx, &state,
5501				struct torture_createdel_state);
5502	if (req == NULL) {
5503		return NULL;
5504	}
5505	state->ev = ev;
5506	state->cli = cli;
5507
5508	subreq = cli_ntcreate_send(
5509		state, ev, cli, name, 0,
5510		FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5511		FILE_ATTRIBUTE_NORMAL,
5512		FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5513		FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
5514
5515	if (tevent_req_nomem(subreq, req)) {
5516		return tevent_req_post(req, ev);
5517	}
5518	tevent_req_set_callback(subreq, torture_createdel_created, req);
5519	return req;
5520}
5521
5522static void torture_createdel_created(struct tevent_req *subreq)
5523{
5524	struct tevent_req *req = tevent_req_callback_data(
5525		subreq, struct tevent_req);
5526	struct torture_createdel_state *state = tevent_req_data(
5527		req, struct torture_createdel_state);
5528	NTSTATUS status;
5529	uint16_t fnum;
5530
5531	status = cli_ntcreate_recv(subreq, &fnum);
5532	TALLOC_FREE(subreq);
5533	if (!NT_STATUS_IS_OK(status)) {
5534		DEBUG(10, ("cli_ntcreate_recv returned %s\n",
5535			   nt_errstr(status)));
5536		tevent_req_nterror(req, status);
5537		return;
5538	}
5539
5540	subreq = cli_close_send(state, state->ev, state->cli, fnum);
5541	if (tevent_req_nomem(subreq, req)) {
5542		return;
5543	}
5544	tevent_req_set_callback(subreq, torture_createdel_closed, req);
5545}
5546
5547static void torture_createdel_closed(struct tevent_req *subreq)
5548{
5549	struct tevent_req *req = tevent_req_callback_data(
5550		subreq, struct tevent_req);
5551	NTSTATUS status;
5552
5553	status = cli_close_recv(subreq);
5554	if (!NT_STATUS_IS_OK(status)) {
5555		DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
5556		tevent_req_nterror(req, status);
5557		return;
5558	}
5559	tevent_req_done(req);
5560}
5561
5562static NTSTATUS torture_createdel_recv(struct tevent_req *req)
5563{
5564	return tevent_req_simple_recv_ntstatus(req);
5565}
5566
5567struct torture_createdels_state {
5568	struct tevent_context *ev;
5569	struct cli_state *cli;
5570	const char *base_name;
5571	int sent;
5572	int received;
5573	int num_files;
5574	struct tevent_req **reqs;
5575};
5576
5577static void torture_createdels_done(struct tevent_req *subreq);
5578
5579static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
5580						  struct tevent_context *ev,
5581						  struct cli_state *cli,
5582						  const char *base_name,
5583						  int num_parallel,
5584						  int num_files)
5585{
5586	struct tevent_req *req;
5587	struct torture_createdels_state *state;
5588	int i;
5589
5590	req = tevent_req_create(mem_ctx, &state,
5591				struct torture_createdels_state);
5592	if (req == NULL) {
5593		return NULL;
5594	}
5595	state->ev = ev;
5596	state->cli = cli;
5597	state->base_name = talloc_strdup(state, base_name);
5598	if (tevent_req_nomem(state->base_name, req)) {
5599		return tevent_req_post(req, ev);
5600	}
5601	state->num_files = MAX(num_parallel, num_files);
5602	state->sent = 0;
5603	state->received = 0;
5604
5605	state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
5606	if (tevent_req_nomem(state->reqs, req)) {
5607		return tevent_req_post(req, ev);
5608	}
5609
5610	for (i=0; i<num_parallel; i++) {
5611		char *name;
5612
5613		name = talloc_asprintf(state, "%s%8.8d", state->base_name,
5614				       state->sent);
5615		if (tevent_req_nomem(name, req)) {
5616			return tevent_req_post(req, ev);
5617		}
5618		state->reqs[i] = torture_createdel_send(
5619			state->reqs, state->ev, state->cli, name);
5620		if (tevent_req_nomem(state->reqs[i], req)) {
5621			return tevent_req_post(req, ev);
5622		}
5623		name = talloc_move(state->reqs[i], &name);
5624		tevent_req_set_callback(state->reqs[i],
5625					torture_createdels_done, req);
5626		state->sent += 1;
5627	}
5628	return req;
5629}
5630
5631static void torture_createdels_done(struct tevent_req *subreq)
5632{
5633	struct tevent_req *req = tevent_req_callback_data(
5634		subreq, struct tevent_req);
5635	struct torture_createdels_state *state = tevent_req_data(
5636		req, struct torture_createdels_state);
5637	size_t num_parallel = talloc_array_length(state->reqs);
5638	NTSTATUS status;
5639	char *name;
5640	int i;
5641
5642	status = torture_createdel_recv(subreq);
5643	if (!NT_STATUS_IS_OK(status)){
5644		DEBUG(10, ("torture_createdel_recv returned %s\n",
5645			   nt_errstr(status)));
5646		TALLOC_FREE(subreq);
5647		tevent_req_nterror(req, status);
5648		return;
5649	}
5650
5651	for (i=0; i<num_parallel; i++) {
5652		if (subreq == state->reqs[i]) {
5653			break;
5654		}
5655	}
5656	if (i == num_parallel) {
5657		DEBUG(10, ("received something we did not send\n"));
5658		tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
5659		return;
5660	}
5661	TALLOC_FREE(state->reqs[i]);
5662
5663	if (state->sent >= state->num_files) {
5664		tevent_req_done(req);
5665		return;
5666	}
5667
5668	name = talloc_asprintf(state, "%s%8.8d", state->base_name,
5669			       state->sent);
5670	if (tevent_req_nomem(name, req)) {
5671		return;
5672	}
5673	state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
5674						state->cli, name);
5675	if (tevent_req_nomem(state->reqs[i], req)) {
5676		return;
5677	}
5678	name = talloc_move(state->reqs[i], &name);
5679	tevent_req_set_callback(state->reqs[i],	torture_createdels_done, req);
5680	state->sent += 1;
5681}
5682
5683static NTSTATUS torture_createdels_recv(struct tevent_req *req)
5684{
5685	return tevent_req_simple_recv_ntstatus(req);
5686}
5687
5688struct swallow_notify_state {
5689	struct tevent_context *ev;
5690	struct cli_state *cli;
5691	uint16_t fnum;
5692	uint32_t completion_filter;
5693	bool recursive;
5694	bool (*fn)(uint32_t action, const char *name, void *priv);
5695	void *priv;
5696};
5697
5698static void swallow_notify_done(struct tevent_req *subreq);
5699
5700static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
5701					      struct tevent_context *ev,
5702					      struct cli_state *cli,
5703					      uint16_t fnum,
5704					      uint32_t completion_filter,
5705					      bool recursive,
5706					      bool (*fn)(uint32_t action,
5707							 const char *name,
5708							 void *priv),
5709					      void *priv)
5710{
5711	struct tevent_req *req, *subreq;
5712	struct swallow_notify_state *state;
5713
5714	req = tevent_req_create(mem_ctx, &state,
5715				struct swallow_notify_state);
5716	if (req == NULL) {
5717		return NULL;
5718	}
5719	state->ev = ev;
5720	state->cli = cli;
5721	state->fnum = fnum;
5722	state->completion_filter = completion_filter;
5723	state->recursive = recursive;
5724	state->fn = fn;
5725	state->priv = priv;
5726
5727	subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
5728				 0xffff, state->completion_filter,
5729				 state->recursive);
5730	if (tevent_req_nomem(subreq, req)) {
5731		return tevent_req_post(req, ev);
5732	}
5733	tevent_req_set_callback(subreq, swallow_notify_done, req);
5734	return req;
5735}
5736
5737static void swallow_notify_done(struct tevent_req *subreq)
5738{
5739	struct tevent_req *req = tevent_req_callback_data(
5740		subreq, struct tevent_req);
5741	struct swallow_notify_state *state = tevent_req_data(
5742		req, struct swallow_notify_state);
5743	NTSTATUS status;
5744	uint32_t i, num_changes;
5745	struct notify_change *changes;
5746
5747	status = cli_notify_recv(subreq, state, &num_changes, &changes);
5748	TALLOC_FREE(subreq);
5749	if (!NT_STATUS_IS_OK(status)) {
5750		DEBUG(10, ("cli_notify_recv returned %s\n",
5751			   nt_errstr(status)));
5752		tevent_req_nterror(req, status);
5753		return;
5754	}
5755
5756	for (i=0; i<num_changes; i++) {
5757		state->fn(changes[i].action, changes[i].name, state->priv);
5758	}
5759	TALLOC_FREE(changes);
5760
5761	subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
5762				 0xffff, state->completion_filter,
5763				 state->recursive);
5764	if (tevent_req_nomem(subreq, req)) {
5765		return;
5766	}
5767	tevent_req_set_callback(subreq, swallow_notify_done, req);
5768}
5769
5770static bool print_notifies(uint32_t action, const char *name, void *priv)
5771{
5772	if (DEBUGLEVEL > 5) {
5773		d_printf("%d %s\n", (int)action, name);
5774	}
5775	return true;
5776}
5777
5778static void notify_bench_done(struct tevent_req *req)
5779{
5780	int *num_finished = (int *)tevent_req_callback_data_void(req);
5781	*num_finished += 1;
5782}
5783
5784static bool run_notify_bench(int dummy)
5785{
5786	const char *dname = "\\notify-bench";
5787	struct tevent_context *ev;
5788	NTSTATUS status;
5789	uint16_t dnum;
5790	struct tevent_req *req1, *req2;
5791	int i, num_unc_names;
5792	int num_finished = 0;
5793
5794	printf("starting notify-bench test\n");
5795
5796	if (use_multishare_conn) {
5797		char **unc_list;
5798		unc_list = file_lines_load(multishare_conn_fname,
5799					   &num_unc_names, 0, NULL);
5800		if (!unc_list || num_unc_names <= 0) {
5801			d_printf("Failed to load unc names list from '%s'\n",
5802				 multishare_conn_fname);
5803			return false;
5804		}
5805		TALLOC_FREE(unc_list);
5806	} else {
5807		num_unc_names = 1;
5808	}
5809
5810	ev = tevent_context_init(talloc_tos());
5811	if (ev == NULL) {
5812		d_printf("tevent_context_init failed\n");
5813		return false;
5814	}
5815
5816	for (i=0; i<num_unc_names; i++) {
5817		struct cli_state *cli;
5818		char *base_fname;
5819
5820		base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
5821					     dname, i);
5822		if (base_fname == NULL) {
5823			return false;
5824		}
5825
5826		if (!torture_open_connection(&cli, i)) {
5827			return false;
5828		}
5829
5830		status = cli_ntcreate(cli, dname, 0,
5831				      MAXIMUM_ALLOWED_ACCESS,
5832				      0, FILE_SHARE_READ|FILE_SHARE_WRITE|
5833				      FILE_SHARE_DELETE,
5834				      FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
5835				      &dnum);
5836
5837		if (!NT_STATUS_IS_OK(status)) {
5838			d_printf("Could not create %s: %s\n", dname,
5839				 nt_errstr(status));
5840			return false;
5841		}
5842
5843		req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
5844					   FILE_NOTIFY_CHANGE_FILE_NAME |
5845					   FILE_NOTIFY_CHANGE_DIR_NAME |
5846					   FILE_NOTIFY_CHANGE_ATTRIBUTES |
5847					   FILE_NOTIFY_CHANGE_LAST_WRITE,
5848					   false, print_notifies, NULL);
5849		if (req1 == NULL) {
5850			d_printf("Could not create notify request\n");
5851			return false;
5852		}
5853
5854		req2 = torture_createdels_send(talloc_tos(), ev, cli,
5855					       base_fname, 10, torture_numops);
5856		if (req2 == NULL) {
5857			d_printf("Could not create createdels request\n");
5858			return false;
5859		}
5860		TALLOC_FREE(base_fname);
5861
5862		tevent_req_set_callback(req2, notify_bench_done,
5863					&num_finished);
5864	}
5865
5866	while (num_finished < num_unc_names) {
5867		int ret;
5868		ret = tevent_loop_once(ev);
5869		if (ret != 0) {
5870			d_printf("tevent_loop_once failed\n");
5871			return false;
5872		}
5873	}
5874
5875	if (!tevent_req_poll(req2, ev)) {
5876		d_printf("tevent_req_poll failed\n");
5877	}
5878
5879	status = torture_createdels_recv(req2);
5880	d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
5881
5882	return true;
5883}
5884
5885static bool run_mangle1(int dummy)
5886{
5887	struct cli_state *cli;
5888	const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
5889	uint16_t fnum;
5890	fstring alt_name;
5891	NTSTATUS status;
5892	time_t change_time, access_time, write_time;
5893	SMB_OFF_T size;
5894	uint16_t mode;
5895
5896	printf("starting mangle1 test\n");
5897	if (!torture_open_connection(&cli, 0)) {
5898		return False;
5899	}
5900
5901	cli_sockopt(cli, sockops);
5902
5903	if (!NT_STATUS_IS_OK(cli_ntcreate(
5904			cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5905			FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF, 0, 0, &fnum))) {
5906		d_printf("open %s failed: %s\n", fname, cli_errstr(cli));
5907		return false;
5908	}
5909	cli_close(cli, fnum);
5910
5911	status = cli_qpathinfo_alt_name(cli, fname, alt_name);
5912	if (!NT_STATUS_IS_OK(status)) {
5913		d_printf("cli_qpathinfo_alt_name failed: %s\n",
5914			 nt_errstr(status));
5915		return false;
5916	}
5917	d_printf("alt_name: %s\n", alt_name);
5918
5919	if (!NT_STATUS_IS_OK(cli_open(cli, alt_name, O_RDONLY, DENY_NONE, &fnum))) {
5920		d_printf("cli_open(%s) failed: %s\n", alt_name,
5921			 cli_errstr(cli));
5922		return false;
5923	}
5924	cli_close(cli, fnum);
5925
5926	if (!cli_qpathinfo(cli, alt_name, &change_time, &access_time,
5927			   &write_time, &size, &mode)) {
5928		d_printf("cli_qpathinfo(%s) failed: %s\n", alt_name,
5929			 cli_errstr(cli));
5930		return false;
5931	}
5932
5933	return true;
5934}
5935
5936static size_t null_source(uint8_t *buf, size_t n, void *priv)
5937{
5938	size_t *to_pull = (size_t *)priv;
5939	size_t thistime = *to_pull;
5940
5941	thistime = MIN(thistime, n);
5942	if (thistime == 0) {
5943		return 0;
5944	}
5945
5946	memset(buf, 0, thistime);
5947	*to_pull -= thistime;
5948	return thistime;
5949}
5950
5951static bool run_windows_write(int dummy)
5952{
5953	struct cli_state *cli1;
5954	uint16_t fnum;
5955	int i;
5956	bool ret = false;
5957	const char *fname = "\\writetest.txt";
5958	double seconds;
5959	double kbytes;
5960
5961	printf("starting windows_write test\n");
5962	if (!torture_open_connection(&cli1, 0)) {
5963		return False;
5964	}
5965
5966	if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum))) {
5967		printf("open failed (%s)\n", cli_errstr(cli1));
5968		return False;
5969	}
5970
5971	cli_sockopt(cli1, sockops);
5972
5973	start_timer();
5974
5975	for (i=0; i<torture_numops; i++) {
5976		char c = 0;
5977		off_t start = i * torture_blocksize;
5978		NTSTATUS status;
5979		size_t to_pull = torture_blocksize - 1;
5980
5981		if (cli_write(cli1, fnum, 0, &c,
5982			      start + torture_blocksize - 1, 1) != 1) {
5983			printf("cli_write failed: %s\n", cli_errstr(cli1));
5984			goto fail;
5985		}
5986
5987		status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
5988				  null_source, &to_pull);
5989		if (!NT_STATUS_IS_OK(status)) {
5990			printf("cli_push returned: %s\n", nt_errstr(status));
5991			goto fail;
5992		}
5993	}
5994
5995	seconds = end_timer();
5996	kbytes = (double)torture_blocksize * torture_numops;
5997	kbytes /= 1024;
5998
5999	printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
6000	       (double)seconds, (int)(kbytes/seconds));
6001
6002	ret = true;
6003 fail:
6004	cli_close(cli1, fnum);
6005	cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
6006	torture_close_connection(cli1);
6007	return ret;
6008}
6009
6010static bool run_cli_echo(int dummy)
6011{
6012	struct cli_state *cli;
6013	NTSTATUS status;
6014
6015	printf("starting cli_echo test\n");
6016	if (!torture_open_connection(&cli, 0)) {
6017		return false;
6018	}
6019	cli_sockopt(cli, sockops);
6020
6021	status = cli_echo(cli, 5, data_blob_const("hello", 5));
6022
6023	d_printf("cli_echo returned %s\n", nt_errstr(status));
6024
6025	torture_close_connection(cli);
6026	return NT_STATUS_IS_OK(status);
6027}
6028
6029static bool run_uid_regression_test(int dummy)
6030{
6031	static struct cli_state *cli;
6032	int16_t old_vuid;
6033	int16_t old_cnum;
6034	bool correct = True;
6035
6036	printf("starting uid regression test\n");
6037
6038	if (!torture_open_connection(&cli, 0)) {
6039		return False;
6040	}
6041
6042	cli_sockopt(cli, sockops);
6043
6044	/* Ok - now save then logoff our current user. */
6045	old_vuid = cli->vuid;
6046
6047	if (!cli_ulogoff(cli)) {
6048		d_printf("(%s) cli_ulogoff failed: %s\n",
6049			__location__, cli_errstr(cli));
6050		correct = false;
6051		goto out;
6052	}
6053
6054	cli->vuid = old_vuid;
6055
6056	/* Try an operation. */
6057	if (!NT_STATUS_IS_OK(cli_mkdir(cli, "\\uid_reg_test"))) {
6058		/* We expect bad uid. */
6059		if (!check_error(__LINE__, cli, ERRSRV, ERRbaduid,
6060				NT_STATUS_NO_SUCH_USER)) {
6061			return False;
6062		}
6063	}
6064
6065	old_cnum = cli->cnum;
6066
6067	/* Now try a SMBtdis with the invald vuid set to zero. */
6068	cli->vuid = 0;
6069
6070	/* This should succeed. */
6071	if (cli_tdis(cli)) {
6072		printf("First tdis with invalid vuid should succeed.\n");
6073	} else {
6074		printf("First tdis failed (%s)\n", cli_errstr(cli));
6075	}
6076
6077	cli->vuid = old_vuid;
6078	cli->cnum = old_cnum;
6079
6080	/* This should fail. */
6081	if (cli_tdis(cli)) {
6082		printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
6083	} else {
6084		/* Should be bad tid. */
6085		if (!check_error(__LINE__, cli, ERRSRV, ERRinvnid,
6086				NT_STATUS_NETWORK_NAME_DELETED)) {
6087			return False;
6088		}
6089	}
6090
6091	cli_rmdir(cli, "\\uid_reg_test");
6092
6093  out:
6094
6095	cli_shutdown(cli);
6096	return correct;
6097}
6098
6099
6100static const char *illegal_chars = "*\\/?<>|\":";
6101static char force_shortname_chars[] = " +,.[];=\177";
6102
6103static void shortname_del_fn(const char *mnt, file_info *finfo, const char *mask, void *state)
6104{
6105	struct cli_state *pcli = (struct cli_state *)state;
6106	fstring fname;
6107	slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
6108
6109	if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
6110		return;
6111
6112	if (finfo->mode & aDIR) {
6113		if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
6114			printf("del_fn: failed to rmdir %s\n,", fname );
6115	} else {
6116		if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, aSYSTEM | aHIDDEN)))
6117			printf("del_fn: failed to unlink %s\n,", fname );
6118	}
6119}
6120
6121struct sn_state {
6122	int i;
6123	bool val;
6124};
6125
6126static void shortname_list_fn(const char *mnt, file_info *finfo, const char *name, void *state)
6127{
6128	struct sn_state *s = (struct sn_state  *)state;
6129	int i = s->i;
6130
6131#if 0
6132	printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
6133		i, finfo->name, finfo->short_name);
6134#endif
6135
6136	if (strchr(force_shortname_chars, i)) {
6137		if (!finfo->short_name[0]) {
6138			/* Shortname not created when it should be. */
6139			d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
6140				__location__, finfo->name, i);
6141			s->val = true;
6142		}
6143	} else if (finfo->short_name[0]){
6144		/* Shortname created when it should not be. */
6145		d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
6146			__location__, finfo->short_name, finfo->name);
6147		s->val = true;
6148	}
6149}
6150
6151static bool run_shortname_test(int dummy)
6152{
6153	static struct cli_state *cli;
6154	bool correct = True;
6155	int i;
6156	struct sn_state s;
6157	char fname[20];
6158
6159	printf("starting shortname test\n");
6160
6161	if (!torture_open_connection(&cli, 0)) {
6162		return False;
6163	}
6164
6165	cli_sockopt(cli, sockops);
6166
6167	cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
6168	cli_list(cli, "\\shortname\\*", aDIR, shortname_del_fn, cli);
6169	cli_rmdir(cli, "\\shortname");
6170
6171	if (!NT_STATUS_IS_OK(cli_mkdir(cli, "\\shortname"))) {
6172		d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
6173			__location__, cli_errstr(cli));
6174		correct = false;
6175		goto out;
6176	}
6177
6178	strlcpy(fname, "\\shortname\\", sizeof(fname));
6179	strlcat(fname, "test .txt", sizeof(fname));
6180
6181	s.val = false;
6182
6183	for (i = 32; i < 128; i++) {
6184		NTSTATUS status;
6185		uint16_t fnum = (uint16_t)-1;
6186
6187		s.i = i;
6188
6189		if (strchr(illegal_chars, i)) {
6190			continue;
6191		}
6192		fname[15] = i;
6193
6194		status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
6195                                   FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum);
6196		if (!NT_STATUS_IS_OK(status)) {
6197			d_printf("(%s) cli_nt_create of %s failed: %s\n",
6198				__location__, fname, cli_errstr(cli));
6199			correct = false;
6200			goto out;
6201		}
6202		cli_close(cli, fnum);
6203		if (cli_list(cli, "\\shortname\\test*.*", 0, shortname_list_fn, &s) != 1) {
6204			d_printf("(%s) failed to list %s: %s\n",
6205				__location__, fname, cli_errstr(cli));
6206			correct = false;
6207			goto out;
6208		}
6209		if (!NT_STATUS_IS_OK(cli_unlink(cli, fname, aSYSTEM | aHIDDEN))) {
6210			d_printf("(%s) failed to delete %s: %s\n",
6211				__location__, fname, cli_errstr(cli));
6212			correct = false;
6213			goto out;
6214		}
6215
6216		if (s.val) {
6217			correct = false;
6218			goto out;
6219		}
6220	}
6221
6222  out:
6223
6224	cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
6225	cli_list(cli, "\\shortname\\*", aDIR, shortname_del_fn, cli);
6226	cli_rmdir(cli, "\\shortname");
6227	torture_close_connection(cli);
6228	return correct;
6229}
6230
6231static void pagedsearch_cb(struct tevent_req *req)
6232{
6233	int rc;
6234	struct tldap_message *msg;
6235	char *dn;
6236
6237	rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
6238	if (rc != TLDAP_SUCCESS) {
6239		d_printf("tldap_search_paged_recv failed: %s\n",
6240			 tldap_err2string(rc));
6241		return;
6242	}
6243	if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
6244		TALLOC_FREE(msg);
6245		return;
6246	}
6247	if (!tldap_entry_dn(msg, &dn)) {
6248		d_printf("tldap_entry_dn failed\n");
6249		return;
6250	}
6251	d_printf("%s\n", dn);
6252	TALLOC_FREE(msg);
6253}
6254
6255static bool run_tldap(int dummy)
6256{
6257	struct tldap_context *ld;
6258	int fd, rc;
6259	NTSTATUS status;
6260	struct sockaddr_storage addr;
6261	struct tevent_context *ev;
6262	struct tevent_req *req;
6263	char *basedn;
6264
6265	if (!resolve_name(host, &addr, 0, false)) {
6266		d_printf("could not find host %s\n", host);
6267		return false;
6268	}
6269	status = open_socket_out(&addr, 389, 9999, &fd);
6270	if (!NT_STATUS_IS_OK(status)) {
6271		d_printf("open_socket_out failed: %s\n", nt_errstr(status));
6272		return false;
6273	}
6274
6275	ld = tldap_context_create(talloc_tos(), fd);
6276	if (ld == NULL) {
6277		close(fd);
6278		d_printf("tldap_context_create failed\n");
6279		return false;
6280	}
6281
6282	rc = tldap_fetch_rootdse(ld);
6283	if (rc != TLDAP_SUCCESS) {
6284		d_printf("tldap_fetch_rootdse failed: %s\n",
6285			 tldap_errstr(talloc_tos(), ld, rc));
6286		return false;
6287	}
6288
6289	basedn = tldap_talloc_single_attribute(
6290		tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
6291	if (basedn == NULL) {
6292		d_printf("no defaultNamingContext\n");
6293		return false;
6294	}
6295	d_printf("defaultNamingContext: %s\n", basedn);
6296
6297	ev = tevent_context_init(talloc_tos());
6298	if (ev == NULL) {
6299		d_printf("tevent_context_init failed\n");
6300		return false;
6301	}
6302
6303	req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
6304				      TLDAP_SCOPE_SUB, "(objectclass=*)",
6305				      NULL, 0, 0,
6306				      NULL, 0, NULL, 0, 0, 0, 0, 5);
6307	if (req == NULL) {
6308		d_printf("tldap_search_paged_send failed\n");
6309		return false;
6310	}
6311	tevent_req_set_callback(req, pagedsearch_cb, NULL);
6312
6313	tevent_req_poll(req, ev);
6314
6315	TALLOC_FREE(req);
6316
6317	TALLOC_FREE(ld);
6318	return true;
6319}
6320
6321static bool run_streamerror(int dummy)
6322{
6323	struct cli_state *cli;
6324	const char *dname = "\\testdir";
6325	const char *streamname =
6326		"testdir:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
6327	NTSTATUS status;
6328	time_t change_time, access_time, write_time;
6329	SMB_OFF_T size;
6330	uint16_t mode, fnum;
6331	bool ret = true;
6332
6333	if (!torture_open_connection(&cli, 0)) {
6334		return false;
6335	}
6336
6337	cli_rmdir(cli, dname);
6338
6339	status = cli_mkdir(cli, dname);
6340	if (!NT_STATUS_IS_OK(status)) {
6341		printf("mkdir failed: %s\n", nt_errstr(status));
6342		return false;
6343	}
6344
6345	cli_qpathinfo(cli, streamname, &change_time, &access_time, &write_time,
6346		      &size, &mode);
6347	status = cli_nt_error(cli);
6348
6349	if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6350		printf("pathinfo returned %s, expected "
6351		       "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
6352		       nt_errstr(status));
6353		ret = false;
6354	}
6355
6356	status = cli_ntcreate(cli, streamname, 0x16,
6357			      FILE_READ_DATA|FILE_READ_EA|
6358			      FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
6359			      FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6360			      FILE_OPEN, 0, 0, &fnum);
6361
6362	if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6363		printf("ntcreate returned %s, expected "
6364		       "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
6365		       nt_errstr(status));
6366		ret = false;
6367	}
6368
6369
6370	cli_rmdir(cli, dname);
6371	return ret;
6372}
6373
6374static bool run_local_substitute(int dummy)
6375{
6376	bool ok = true;
6377
6378	ok &= subst_test("%U", "bla", "", -1, -1, "bla");
6379	ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
6380	ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
6381	ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
6382	ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
6383	ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
6384	ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
6385	ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
6386
6387	/* Different captialization rules in sub_basic... */
6388
6389	ok &=  (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
6390		       "blaDOM") == 0);
6391
6392	return ok;
6393}
6394
6395static bool run_local_base64(int dummy)
6396{
6397	int i;
6398	bool ret = true;
6399
6400	for (i=1; i<2000; i++) {
6401		DATA_BLOB blob1, blob2;
6402		char *b64;
6403
6404		blob1.data = talloc_array(talloc_tos(), uint8_t, i);
6405		blob1.length = i;
6406		generate_random_buffer(blob1.data, blob1.length);
6407
6408		b64 = base64_encode_data_blob(talloc_tos(), blob1);
6409		if (b64 == NULL) {
6410			d_fprintf(stderr, "base64_encode_data_blob failed "
6411				  "for %d bytes\n", i);
6412			ret = false;
6413		}
6414		blob2 = base64_decode_data_blob(b64);
6415		TALLOC_FREE(b64);
6416
6417		if (data_blob_cmp(&blob1, &blob2)) {
6418			d_fprintf(stderr, "data_blob_cmp failed for %d "
6419				  "bytes\n", i);
6420			ret = false;
6421		}
6422		TALLOC_FREE(blob1.data);
6423		data_blob_free(&blob2);
6424	}
6425	return ret;
6426}
6427
6428static bool run_local_gencache(int dummy)
6429{
6430	char *val;
6431	time_t tm;
6432	DATA_BLOB blob;
6433
6434	if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
6435		d_printf("%s: gencache_set() failed\n", __location__);
6436		return False;
6437	}
6438
6439	if (!gencache_get("foo", NULL, NULL)) {
6440		d_printf("%s: gencache_get() failed\n", __location__);
6441		return False;
6442	}
6443
6444	if (!gencache_get("foo", &val, &tm)) {
6445		d_printf("%s: gencache_get() failed\n", __location__);
6446		return False;
6447	}
6448
6449	if (strcmp(val, "bar") != 0) {
6450		d_printf("%s: gencache_get() returned %s, expected %s\n",
6451			 __location__, val, "bar");
6452		SAFE_FREE(val);
6453		return False;
6454	}
6455
6456	SAFE_FREE(val);
6457
6458	if (!gencache_del("foo")) {
6459		d_printf("%s: gencache_del() failed\n", __location__);
6460		return False;
6461	}
6462	if (gencache_del("foo")) {
6463		d_printf("%s: second gencache_del() succeeded\n",
6464			 __location__);
6465		return False;
6466	}
6467
6468	if (gencache_get("foo", &val, &tm)) {
6469		d_printf("%s: gencache_get() on deleted entry "
6470			 "succeeded\n", __location__);
6471		return False;
6472	}
6473
6474	blob = data_blob_string_const_null("bar");
6475	tm = time(NULL) + 60;
6476
6477	if (!gencache_set_data_blob("foo", &blob, tm)) {
6478		d_printf("%s: gencache_set_data_blob() failed\n", __location__);
6479		return False;
6480	}
6481
6482	if (!gencache_get_data_blob("foo", &blob, NULL, NULL)) {
6483		d_printf("%s: gencache_get_data_blob() failed\n", __location__);
6484		return False;
6485	}
6486
6487	if (strcmp((const char *)blob.data, "bar") != 0) {
6488		d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
6489			 __location__, (const char *)blob.data, "bar");
6490		data_blob_free(&blob);
6491		return False;
6492	}
6493
6494	data_blob_free(&blob);
6495
6496	if (!gencache_del("foo")) {
6497		d_printf("%s: gencache_del() failed\n", __location__);
6498		return False;
6499	}
6500	if (gencache_del("foo")) {
6501		d_printf("%s: second gencache_del() succeeded\n",
6502			 __location__);
6503		return False;
6504	}
6505
6506	if (gencache_get_data_blob("foo", &blob, NULL, NULL)) {
6507		d_printf("%s: gencache_get_data_blob() on deleted entry "
6508			 "succeeded\n", __location__);
6509		return False;
6510	}
6511
6512	return True;
6513}
6514
6515static bool rbt_testval(struct db_context *db, const char *key,
6516			const char *value)
6517{
6518	struct db_record *rec;
6519	TDB_DATA data = string_tdb_data(value);
6520	bool ret = false;
6521	NTSTATUS status;
6522
6523	rec = db->fetch_locked(db, db, string_tdb_data(key));
6524	if (rec == NULL) {
6525		d_fprintf(stderr, "fetch_locked failed\n");
6526		goto done;
6527	}
6528	status = rec->store(rec, data, 0);
6529	if (!NT_STATUS_IS_OK(status)) {
6530		d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
6531		goto done;
6532	}
6533	TALLOC_FREE(rec);
6534
6535	rec = db->fetch_locked(db, db, string_tdb_data(key));
6536	if (rec == NULL) {
6537		d_fprintf(stderr, "second fetch_locked failed\n");
6538		goto done;
6539	}
6540	if ((rec->value.dsize != data.dsize)
6541	    || (memcmp(rec->value.dptr, data.dptr, data.dsize) != 0)) {
6542		d_fprintf(stderr, "Got wrong data back\n");
6543		goto done;
6544	}
6545
6546	ret = true;
6547 done:
6548	TALLOC_FREE(rec);
6549	return ret;
6550}
6551
6552static bool run_local_rbtree(int dummy)
6553{
6554	struct db_context *db;
6555	bool ret = false;
6556	int i;
6557
6558	db = db_open_rbt(NULL);
6559
6560	if (db == NULL) {
6561		d_fprintf(stderr, "db_open_rbt failed\n");
6562		return false;
6563	}
6564
6565	for (i=0; i<1000; i++) {
6566		char *key, *value;
6567
6568		if (asprintf(&key, "key%ld", random()) == -1) {
6569			goto done;
6570		}
6571		if (asprintf(&value, "value%ld", random()) == -1) {
6572			SAFE_FREE(key);
6573			goto done;
6574		}
6575
6576		if (!rbt_testval(db, key, value)) {
6577			SAFE_FREE(key);
6578			SAFE_FREE(value);
6579			goto done;
6580		}
6581
6582		SAFE_FREE(value);
6583		if (asprintf(&value, "value%ld", random()) == -1) {
6584			SAFE_FREE(key);
6585			goto done;
6586		}
6587
6588		if (!rbt_testval(db, key, value)) {
6589			SAFE_FREE(key);
6590			SAFE_FREE(value);
6591			goto done;
6592		}
6593
6594		SAFE_FREE(key);
6595		SAFE_FREE(value);
6596	}
6597
6598	ret = true;
6599
6600 done:
6601	TALLOC_FREE(db);
6602	return ret;
6603}
6604
6605struct talloc_dict_test {
6606	int content;
6607};
6608
6609static int talloc_dict_traverse_fn(DATA_BLOB key, void *data, void *priv)
6610{
6611	int *count = (int *)priv;
6612	*count += 1;
6613	return 0;
6614}
6615
6616static bool run_local_talloc_dict(int dummy)
6617{
6618	struct talloc_dict *dict;
6619	struct talloc_dict_test *t;
6620	int key, count;
6621
6622	dict = talloc_dict_init(talloc_tos());
6623	if (dict == NULL) {
6624		return false;
6625	}
6626
6627	t = talloc(talloc_tos(), struct talloc_dict_test);
6628	if (t == NULL) {
6629		return false;
6630	}
6631
6632	key = 1;
6633	t->content = 1;
6634	if (!talloc_dict_set(dict, data_blob_const(&key, sizeof(key)), t)) {
6635		return false;
6636	}
6637
6638	count = 0;
6639	if (talloc_dict_traverse(dict, talloc_dict_traverse_fn, &count) != 0) {
6640		return false;
6641	}
6642
6643	if (count != 1) {
6644		return false;
6645	}
6646
6647	TALLOC_FREE(dict);
6648
6649	return true;
6650}
6651
6652/* Split a path name into filename and stream name components. Canonicalise
6653 * such that an implicit $DATA token is always explicit.
6654 *
6655 * The "specification" of this function can be found in the
6656 * run_local_stream_name() function in torture.c, I've tried those
6657 * combinations against a W2k3 server.
6658 */
6659
6660static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
6661				       char **pbase, char **pstream)
6662{
6663	char *base = NULL;
6664	char *stream = NULL;
6665	char *sname; /* stream name */
6666	const char *stype; /* stream type */
6667
6668	DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
6669
6670	sname = strchr_m(fname, ':');
6671
6672	if (lp_posix_pathnames() || (sname == NULL)) {
6673		if (pbase != NULL) {
6674			base = talloc_strdup(mem_ctx, fname);
6675			NT_STATUS_HAVE_NO_MEMORY(base);
6676		}
6677		goto done;
6678	}
6679
6680	if (pbase != NULL) {
6681		base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
6682		NT_STATUS_HAVE_NO_MEMORY(base);
6683	}
6684
6685	sname += 1;
6686
6687	stype = strchr_m(sname, ':');
6688
6689	if (stype == NULL) {
6690		sname = talloc_strdup(mem_ctx, sname);
6691		stype = "$DATA";
6692	}
6693	else {
6694		if (StrCaseCmp(stype, ":$DATA") != 0) {
6695			/*
6696			 * If there is an explicit stream type, so far we only
6697			 * allow $DATA. Is there anything else allowed? -- vl
6698			 */
6699			DEBUG(10, ("[%s] is an invalid stream type\n", stype));
6700			TALLOC_FREE(base);
6701			return NT_STATUS_OBJECT_NAME_INVALID;
6702		}
6703		sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
6704		stype += 1;
6705	}
6706
6707	if (sname == NULL) {
6708		TALLOC_FREE(base);
6709		return NT_STATUS_NO_MEMORY;
6710	}
6711
6712	if (sname[0] == '\0') {
6713		/*
6714		 * no stream name, so no stream
6715		 */
6716		goto done;
6717	}
6718
6719	if (pstream != NULL) {
6720		stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
6721		if (stream == NULL) {
6722			TALLOC_FREE(sname);
6723			TALLOC_FREE(base);
6724			return NT_STATUS_NO_MEMORY;
6725		}
6726		/*
6727		 * upper-case the type field
6728		 */
6729		strupper_m(strchr_m(stream, ':')+1);
6730	}
6731
6732 done:
6733	if (pbase != NULL) {
6734		*pbase = base;
6735	}
6736	if (pstream != NULL) {
6737		*pstream = stream;
6738	}
6739	return NT_STATUS_OK;
6740}
6741
6742static bool test_stream_name(const char *fname, const char *expected_base,
6743			     const char *expected_stream,
6744			     NTSTATUS expected_status)
6745{
6746	NTSTATUS status;
6747	char *base = NULL;
6748	char *stream = NULL;
6749
6750	status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
6751	if (!NT_STATUS_EQUAL(status, expected_status)) {
6752		goto error;
6753	}
6754
6755	if (!NT_STATUS_IS_OK(status)) {
6756		return true;
6757	}
6758
6759	if (base == NULL) goto error;
6760
6761	if (strcmp(expected_base, base) != 0) goto error;
6762
6763	if ((expected_stream != NULL) && (stream == NULL)) goto error;
6764	if ((expected_stream == NULL) && (stream != NULL)) goto error;
6765
6766	if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
6767		goto error;
6768
6769	TALLOC_FREE(base);
6770	TALLOC_FREE(stream);
6771	return true;
6772
6773 error:
6774	d_fprintf(stderr, "test_stream(%s, %s, %s, %s)\n",
6775		  fname, expected_base ? expected_base : "<NULL>",
6776		  expected_stream ? expected_stream : "<NULL>",
6777		  nt_errstr(expected_status));
6778	d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
6779		  base ? base : "<NULL>", stream ? stream : "<NULL>",
6780		  nt_errstr(status));
6781	TALLOC_FREE(base);
6782	TALLOC_FREE(stream);
6783	return false;
6784}
6785
6786static bool run_local_stream_name(int dummy)
6787{
6788	bool ret = true;
6789
6790	ret &= test_stream_name(
6791		"bla", "bla", NULL, NT_STATUS_OK);
6792	ret &= test_stream_name(
6793		"bla::$DATA", "bla", NULL, NT_STATUS_OK);
6794	ret &= test_stream_name(
6795		"bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
6796	ret &= test_stream_name(
6797		"bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
6798	ret &= test_stream_name(
6799		"bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
6800	ret &= test_stream_name(
6801		"bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
6802	ret &= test_stream_name(
6803		"bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
6804	ret &= test_stream_name(
6805		"bla:x", "bla", "x:$DATA", NT_STATUS_OK);
6806
6807	return ret;
6808}
6809
6810static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
6811{
6812	if (a.length != b.length) {
6813		printf("a.length=%d != b.length=%d\n",
6814		       (int)a.length, (int)b.length);
6815		return false;
6816	}
6817	if (memcmp(a.data, b.data, a.length) != 0) {
6818		printf("a.data and b.data differ\n");
6819		return false;
6820	}
6821	return true;
6822}
6823
6824static bool run_local_memcache(int dummy)
6825{
6826	struct memcache *cache;
6827	DATA_BLOB k1, k2;
6828	DATA_BLOB d1, d2, d3;
6829	DATA_BLOB v1, v2, v3;
6830
6831	TALLOC_CTX *mem_ctx;
6832	char *str1, *str2;
6833	size_t size1, size2;
6834	bool ret = false;
6835
6836	cache = memcache_init(NULL, 100);
6837
6838	if (cache == NULL) {
6839		printf("memcache_init failed\n");
6840		return false;
6841	}
6842
6843	d1 = data_blob_const("d1", 2);
6844	d2 = data_blob_const("d2", 2);
6845	d3 = data_blob_const("d3", 2);
6846
6847	k1 = data_blob_const("d1", 2);
6848	k2 = data_blob_const("d2", 2);
6849
6850	memcache_add(cache, STAT_CACHE, k1, d1);
6851	memcache_add(cache, GETWD_CACHE, k2, d2);
6852
6853	if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
6854		printf("could not find k1\n");
6855		return false;
6856	}
6857	if (!data_blob_equal(d1, v1)) {
6858		return false;
6859	}
6860
6861	if (!memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
6862		printf("could not find k2\n");
6863		return false;
6864	}
6865	if (!data_blob_equal(d2, v2)) {
6866		return false;
6867	}
6868
6869	memcache_add(cache, STAT_CACHE, k1, d3);
6870
6871	if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
6872		printf("could not find replaced k1\n");
6873		return false;
6874	}
6875	if (!data_blob_equal(d3, v3)) {
6876		return false;
6877	}
6878
6879	memcache_add(cache, GETWD_CACHE, k1, d1);
6880
6881	if (memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
6882		printf("Did find k2, should have been purged\n");
6883		return false;
6884	}
6885
6886	TALLOC_FREE(cache);
6887
6888	cache = memcache_init(NULL, 0);
6889
6890	mem_ctx = talloc_init("foo");
6891
6892	str1 = talloc_strdup(mem_ctx, "string1");
6893	str2 = talloc_strdup(mem_ctx, "string2");
6894
6895	memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
6896			    data_blob_string_const("torture"), &str1);
6897	size1 = talloc_total_size(cache);
6898
6899	memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
6900			    data_blob_string_const("torture"), &str2);
6901	size2 = talloc_total_size(cache);
6902
6903	printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
6904
6905	if (size2 > size1) {
6906		printf("memcache leaks memory!\n");
6907		goto fail;
6908	}
6909
6910	ret = true;
6911 fail:
6912	TALLOC_FREE(cache);
6913	return ret;
6914}
6915
6916static void wbclient_done(struct tevent_req *req)
6917{
6918	wbcErr wbc_err;
6919	struct winbindd_response *wb_resp;
6920	int *i = (int *)tevent_req_callback_data_void(req);
6921
6922	wbc_err = wb_trans_recv(req, req, &wb_resp);
6923	TALLOC_FREE(req);
6924	*i += 1;
6925	d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
6926}
6927
6928static bool run_local_wbclient(int dummy)
6929{
6930	struct event_context *ev;
6931	struct wb_context **wb_ctx;
6932	struct winbindd_request wb_req;
6933	bool result = false;
6934	int i, j;
6935
6936	BlockSignals(True, SIGPIPE);
6937
6938	ev = tevent_context_init_byname(talloc_tos(), "epoll");
6939	if (ev == NULL) {
6940		goto fail;
6941	}
6942
6943	wb_ctx = TALLOC_ARRAY(ev, struct wb_context *, nprocs);
6944	if (wb_ctx == NULL) {
6945		goto fail;
6946	}
6947
6948	ZERO_STRUCT(wb_req);
6949	wb_req.cmd = WINBINDD_PING;
6950
6951	d_printf("nprocs=%d, numops=%d\n", (int)nprocs, (int)torture_numops);
6952
6953	for (i=0; i<nprocs; i++) {
6954		wb_ctx[i] = wb_context_init(ev, NULL);
6955		if (wb_ctx[i] == NULL) {
6956			goto fail;
6957		}
6958		for (j=0; j<torture_numops; j++) {
6959			struct tevent_req *req;
6960			req = wb_trans_send(ev, ev, wb_ctx[i],
6961					    (j % 2) == 0, &wb_req);
6962			if (req == NULL) {
6963				goto fail;
6964			}
6965			tevent_req_set_callback(req, wbclient_done, &i);
6966		}
6967	}
6968
6969	i = 0;
6970
6971	while (i < nprocs * torture_numops) {
6972		event_loop_once(ev);
6973	}
6974
6975	result = true;
6976 fail:
6977	TALLOC_FREE(ev);
6978	return result;
6979}
6980
6981static void getaddrinfo_finished(struct tevent_req *req)
6982{
6983	char *name = (char *)tevent_req_callback_data_void(req);
6984	struct addrinfo *ainfo;
6985	int res;
6986
6987	res = getaddrinfo_recv(req, &ainfo);
6988	if (res != 0) {
6989		d_printf("gai(%s) returned %s\n", name, gai_strerror(res));
6990		return;
6991	}
6992	d_printf("gai(%s) succeeded\n", name);
6993	freeaddrinfo(ainfo);
6994}
6995
6996static bool run_getaddrinfo_send(int dummy)
6997{
6998	TALLOC_CTX *frame = talloc_stackframe();
6999	struct fncall_context *ctx;
7000	struct tevent_context *ev;
7001	bool result = false;
7002	const char *names[4] = { "www.samba.org", "notfound.samba.org",
7003				 "www.slashdot.org", "heise.de" };
7004	struct tevent_req *reqs[4];
7005	int i;
7006
7007	ev = event_context_init(frame);
7008	if (ev == NULL) {
7009		goto fail;
7010	}
7011
7012	ctx = fncall_context_init(frame, 4);
7013
7014	for (i=0; i<ARRAY_SIZE(names); i++) {
7015		reqs[i] = getaddrinfo_send(frame, ev, ctx, names[i], NULL,
7016					   NULL);
7017		if (reqs[i] == NULL) {
7018			goto fail;
7019		}
7020		tevent_req_set_callback(reqs[i], getaddrinfo_finished,
7021					(void *)names[i]);
7022	}
7023
7024	for (i=0; i<ARRAY_SIZE(reqs); i++) {
7025		tevent_loop_once(ev);
7026	}
7027
7028	result = true;
7029fail:
7030	TALLOC_FREE(frame);
7031	return result;
7032}
7033
7034static bool dbtrans_inc(struct db_context *db)
7035{
7036	struct db_record *rec;
7037	uint32_t *val;
7038	bool ret = false;
7039	NTSTATUS status;
7040
7041	rec = db->fetch_locked(db, db, string_term_tdb_data("transtest"));
7042	if (rec == NULL) {
7043		printf(__location__ "fetch_lock failed\n");
7044		return false;
7045	}
7046
7047	if (rec->value.dsize != sizeof(uint32_t)) {
7048		printf(__location__ "value.dsize = %d\n",
7049		       (int)rec->value.dsize);
7050		goto fail;
7051	}
7052
7053	val = (uint32_t *)rec->value.dptr;
7054	*val += 1;
7055
7056	status = rec->store(rec, make_tdb_data((uint8_t *)val,
7057					       sizeof(uint32_t)),
7058			    0);
7059	if (!NT_STATUS_IS_OK(status)) {
7060		printf(__location__ "store failed: %s\n",
7061		       nt_errstr(status));
7062		goto fail;
7063	}
7064
7065	ret = true;
7066fail:
7067	TALLOC_FREE(rec);
7068	return ret;
7069}
7070
7071static bool run_local_dbtrans(int dummy)
7072{
7073	struct db_context *db;
7074	struct db_record *rec;
7075	NTSTATUS status;
7076	uint32_t initial;
7077	int res;
7078
7079	db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
7080		     O_RDWR|O_CREAT, 0600);
7081	if (db == NULL) {
7082		printf("Could not open transtest.db\n");
7083		return false;
7084	}
7085
7086	res = db->transaction_start(db);
7087	if (res == -1) {
7088		printf(__location__ "transaction_start failed\n");
7089		return false;
7090	}
7091
7092	rec = db->fetch_locked(db, db, string_term_tdb_data("transtest"));
7093	if (rec == NULL) {
7094		printf(__location__ "fetch_lock failed\n");
7095		return false;
7096	}
7097
7098	if (rec->value.dptr == NULL) {
7099		initial = 0;
7100		status = rec->store(
7101			rec, make_tdb_data((uint8_t *)&initial,
7102					   sizeof(initial)),
7103			0);
7104		if (!NT_STATUS_IS_OK(status)) {
7105			printf(__location__ "store returned %s\n",
7106			       nt_errstr(status));
7107			return false;
7108		}
7109	}
7110
7111	TALLOC_FREE(rec);
7112
7113	res = db->transaction_commit(db);
7114	if (res == -1) {
7115		printf(__location__ "transaction_commit failed\n");
7116		return false;
7117	}
7118
7119	while (true) {
7120		uint32_t val, val2;
7121		int i;
7122
7123		res = db->transaction_start(db);
7124		if (res == -1) {
7125			printf(__location__ "transaction_start failed\n");
7126			break;
7127		}
7128
7129		if (!dbwrap_fetch_uint32(db, "transtest", &val)) {
7130			printf(__location__ "dbwrap_fetch_uint32 failed\n");
7131			break;
7132		}
7133
7134		for (i=0; i<10; i++) {
7135			if (!dbtrans_inc(db)) {
7136				return false;
7137			}
7138		}
7139
7140		if (!dbwrap_fetch_uint32(db, "transtest", &val2)) {
7141			printf(__location__ "dbwrap_fetch_uint32 failed\n");
7142			break;
7143		}
7144
7145		if (val2 != val + 10) {
7146			printf(__location__ "val=%d, val2=%d\n",
7147			       (int)val, (int)val2);
7148			break;
7149		}
7150
7151		printf("val2=%d\r", val2);
7152
7153		res = db->transaction_commit(db);
7154		if (res == -1) {
7155			printf(__location__ "transaction_commit failed\n");
7156			break;
7157		}
7158	}
7159
7160	TALLOC_FREE(db);
7161	return true;
7162}
7163
7164static double create_procs(bool (*fn)(int), bool *result)
7165{
7166	int i, status;
7167	volatile pid_t *child_status;
7168	volatile bool *child_status_out;
7169	int synccount;
7170	int tries = 8;
7171
7172	synccount = 0;
7173
7174	child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*nprocs);
7175	if (!child_status) {
7176		printf("Failed to setup shared memory\n");
7177		return -1;
7178	}
7179
7180	child_status_out = (volatile bool *)shm_setup(sizeof(bool)*nprocs);
7181	if (!child_status_out) {
7182		printf("Failed to setup result status shared memory\n");
7183		return -1;
7184	}
7185
7186	for (i = 0; i < nprocs; i++) {
7187		child_status[i] = 0;
7188		child_status_out[i] = True;
7189	}
7190
7191	start_timer();
7192
7193	for (i=0;i<nprocs;i++) {
7194		procnum = i;
7195		if (fork() == 0) {
7196			pid_t mypid = getpid();
7197			sys_srandom(((int)mypid) ^ ((int)time(NULL)));
7198
7199			slprintf(myname,sizeof(myname),"CLIENT%d", i);
7200
7201			while (1) {
7202				if (torture_open_connection(&current_cli, i)) break;
7203				if (tries-- == 0) {
7204					printf("pid %d failed to start\n", (int)getpid());
7205					_exit(1);
7206				}
7207				smb_msleep(10);
7208			}
7209
7210			child_status[i] = getpid();
7211
7212			while (child_status[i] && end_timer() < 5) smb_msleep(2);
7213
7214			child_status_out[i] = fn(i);
7215			_exit(0);
7216		}
7217	}
7218
7219	do {
7220		synccount = 0;
7221		for (i=0;i<nprocs;i++) {
7222			if (child_status[i]) synccount++;
7223		}
7224		if (synccount == nprocs) break;
7225		smb_msleep(10);
7226	} while (end_timer() < 30);
7227
7228	if (synccount != nprocs) {
7229		printf("FAILED TO START %d CLIENTS (started %d)\n", nprocs, synccount);
7230		*result = False;
7231		return end_timer();
7232	}
7233
7234	/* start the client load */
7235	start_timer();
7236
7237	for (i=0;i<nprocs;i++) {
7238		child_status[i] = 0;
7239	}
7240
7241	printf("%d clients started\n", nprocs);
7242
7243	for (i=0;i<nprocs;i++) {
7244		while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
7245	}
7246
7247	printf("\n");
7248
7249	for (i=0;i<nprocs;i++) {
7250		if (!child_status_out[i]) {
7251			*result = False;
7252		}
7253	}
7254	return end_timer();
7255}
7256
7257#define FLAG_MULTIPROC 1
7258
7259static struct {
7260	const char *name;
7261	bool (*fn)(int);
7262	unsigned flags;
7263} torture_ops[] = {
7264	{"FDPASS", run_fdpasstest, 0},
7265	{"LOCK1",  run_locktest1,  0},
7266	{"LOCK2",  run_locktest2,  0},
7267	{"LOCK3",  run_locktest3,  0},
7268	{"LOCK4",  run_locktest4,  0},
7269	{"LOCK5",  run_locktest5,  0},
7270	{"LOCK6",  run_locktest6,  0},
7271	{"LOCK7",  run_locktest7,  0},
7272	{"LOCK8",  run_locktest8,  0},
7273	{"LOCK9",  run_locktest9,  0},
7274	{"UNLINK", run_unlinktest, 0},
7275	{"BROWSE", run_browsetest, 0},
7276	{"ATTR",   run_attrtest,   0},
7277	{"TRANS2", run_trans2test, 0},
7278	{"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
7279	{"TORTURE",run_torture,    FLAG_MULTIPROC},
7280	{"RANDOMIPC", run_randomipc, 0},
7281	{"NEGNOWAIT", run_negprot_nowait, 0},
7282	{"NBENCH",  run_nbench, 0},
7283	{"OPLOCK1",  run_oplock1, 0},
7284	{"OPLOCK2",  run_oplock2, 0},
7285	{"OPLOCK3",  run_oplock3, 0},
7286	{"DIR",  run_dirtest, 0},
7287	{"DIR1",  run_dirtest1, 0},
7288	{"DENY1",  torture_denytest1, 0},
7289	{"DENY2",  torture_denytest2, 0},
7290	{"TCON",  run_tcon_test, 0},
7291	{"TCONDEV",  run_tcon_devtype_test, 0},
7292	{"RW1",  run_readwritetest, 0},
7293	{"RW2",  run_readwritemulti, FLAG_MULTIPROC},
7294	{"RW3",  run_readwritelarge, 0},
7295	{"OPEN", run_opentest, 0},
7296	{"POSIX", run_simple_posix_open_test, 0},
7297	{ "UID-REGRESSION-TEST", run_uid_regression_test, 0},
7298	{ "SHORTNAME-TEST", run_shortname_test, 0},
7299#if 1
7300	{"OPENATTR", run_openattrtest, 0},
7301#endif
7302	{"XCOPY", run_xcopy, 0},
7303	{"RENAME", run_rename, 0},
7304	{"DELETE", run_deletetest, 0},
7305	{"PROPERTIES", run_properties, 0},
7306	{"MANGLE", torture_mangle, 0},
7307	{"MANGLE1", run_mangle1, 0},
7308	{"W2K", run_w2ktest, 0},
7309	{"TRANS2SCAN", torture_trans2_scan, 0},
7310	{"NTTRANSSCAN", torture_nttrans_scan, 0},
7311	{"UTABLE", torture_utable, 0},
7312	{"CASETABLE", torture_casetable, 0},
7313	{"ERRMAPEXTRACT", run_error_map_extract, 0},
7314	{"PIPE_NUMBER", run_pipe_number, 0},
7315	{"TCON2",  run_tcon2_test, 0},
7316	{"IOCTL",  torture_ioctl_test, 0},
7317	{"CHKPATH",  torture_chkpath_test, 0},
7318	{"FDSESS", run_fdsesstest, 0},
7319	{ "EATEST", run_eatest, 0},
7320	{ "SESSSETUP_BENCH", run_sesssetup_bench, 0},
7321	{ "CHAIN1", run_chain1, 0},
7322	{ "CHAIN2", run_chain2, 0},
7323	{ "WINDOWS-WRITE", run_windows_write, 0},
7324	{ "CLI_ECHO", run_cli_echo, 0},
7325	{ "GETADDRINFO", run_getaddrinfo_send, 0},
7326	{ "TLDAP", run_tldap },
7327	{ "STREAMERROR", run_streamerror },
7328	{ "NOTIFY-BENCH", run_notify_bench },
7329	{ "LOCAL-SUBSTITUTE", run_local_substitute, 0},
7330	{ "LOCAL-GENCACHE", run_local_gencache, 0},
7331	{ "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0},
7332	{ "LOCAL-BASE64", run_local_base64, 0},
7333	{ "LOCAL-RBTREE", run_local_rbtree, 0},
7334	{ "LOCAL-MEMCACHE", run_local_memcache, 0},
7335	{ "LOCAL-STREAM-NAME", run_local_stream_name, 0},
7336	{ "LOCAL-WBCLIENT", run_local_wbclient, 0},
7337	{ "LOCAL-DBTRANS", run_local_dbtrans, 0},
7338	{NULL, NULL, 0}};
7339
7340
7341
7342/****************************************************************************
7343run a specified test or "ALL"
7344****************************************************************************/
7345static bool run_test(const char *name)
7346{
7347	bool ret = True;
7348	bool result = True;
7349	bool found = False;
7350	int i;
7351	double t;
7352	if (strequal(name,"ALL")) {
7353		for (i=0;torture_ops[i].name;i++) {
7354			run_test(torture_ops[i].name);
7355		}
7356		found = True;
7357	}
7358
7359	for (i=0;torture_ops[i].name;i++) {
7360		fstr_sprintf(randomfname, "\\XX%x",
7361			 (unsigned)random());
7362
7363		if (strequal(name, torture_ops[i].name)) {
7364			found = True;
7365			printf("Running %s\n", name);
7366			if (torture_ops[i].flags & FLAG_MULTIPROC) {
7367				t = create_procs(torture_ops[i].fn, &result);
7368				if (!result) {
7369					ret = False;
7370					printf("TEST %s FAILED!\n", name);
7371				}
7372			} else {
7373				start_timer();
7374				if (!torture_ops[i].fn(0)) {
7375					ret = False;
7376					printf("TEST %s FAILED!\n", name);
7377				}
7378				t = end_timer();
7379			}
7380			printf("%s took %g secs\n\n", name, t);
7381		}
7382	}
7383
7384	if (!found) {
7385		printf("Did not find a test named %s\n", name);
7386		ret = False;
7387	}
7388
7389	return ret;
7390}
7391
7392
7393static void usage(void)
7394{
7395	int i;
7396
7397	printf("WARNING samba4 test suite is much more complete nowadays.\n");
7398	printf("Please use samba4 torture.\n\n");
7399
7400	printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
7401
7402	printf("\t-d debuglevel\n");
7403	printf("\t-U user%%pass\n");
7404	printf("\t-k               use kerberos\n");
7405	printf("\t-N numprocs\n");
7406	printf("\t-n my_netbios_name\n");
7407	printf("\t-W workgroup\n");
7408	printf("\t-o num_operations\n");
7409	printf("\t-O socket_options\n");
7410	printf("\t-m maximum protocol\n");
7411	printf("\t-L use oplocks\n");
7412	printf("\t-c CLIENT.TXT   specify client load file for NBENCH\n");
7413	printf("\t-A showall\n");
7414	printf("\t-p port\n");
7415	printf("\t-s seed\n");
7416	printf("\t-b unclist_filename   specify multiple shares for multiple connections\n");
7417	printf("\n\n");
7418
7419	printf("tests are:");
7420	for (i=0;torture_ops[i].name;i++) {
7421		printf(" %s", torture_ops[i].name);
7422	}
7423	printf("\n");
7424
7425	printf("default test is ALL\n");
7426
7427	exit(1);
7428}
7429
7430/****************************************************************************
7431  main program
7432****************************************************************************/
7433 int main(int argc,char *argv[])
7434{
7435	int opt, i;
7436	char *p;
7437	int gotuser = 0;
7438	int gotpass = 0;
7439	bool correct = True;
7440	TALLOC_CTX *frame = talloc_stackframe();
7441	int seed = time(NULL);
7442
7443	dbf = x_stdout;
7444
7445#ifdef HAVE_SETBUFFER
7446	setbuffer(stdout, NULL, 0);
7447#endif
7448
7449	load_case_tables();
7450
7451	setup_logging("smbtorture", true);
7452
7453	if (is_default_dyn_CONFIGFILE()) {
7454		if(getenv("SMB_CONF_PATH")) {
7455			set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
7456		}
7457	}
7458	lp_load(get_dyn_CONFIGFILE(),True,False,False,True);
7459	load_interfaces();
7460
7461	if (argc < 2) {
7462		usage();
7463	}
7464
7465        for(p = argv[1]; *p; p++)
7466          if(*p == '\\')
7467            *p = '/';
7468
7469	if (strncmp(argv[1], "//", 2)) {
7470		usage();
7471	}
7472
7473	fstrcpy(host, &argv[1][2]);
7474	p = strchr_m(&host[2],'/');
7475	if (!p) {
7476		usage();
7477	}
7478	*p = 0;
7479	fstrcpy(share, p+1);
7480
7481	fstrcpy(myname, get_myname(talloc_tos()));
7482	if (!*myname) {
7483		fprintf(stderr, "Failed to get my hostname.\n");
7484		return 1;
7485	}
7486
7487	if (*username == 0 && getenv("LOGNAME")) {
7488	  fstrcpy(username,getenv("LOGNAME"));
7489	}
7490
7491	argc--;
7492	argv++;
7493
7494	fstrcpy(workgroup, lp_workgroup());
7495
7496	while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:")) != EOF) {
7497		switch (opt) {
7498		case 'p':
7499			port_to_use = atoi(optarg);
7500			break;
7501		case 's':
7502			seed = atoi(optarg);
7503			break;
7504		case 'W':
7505			fstrcpy(workgroup,optarg);
7506			break;
7507		case 'm':
7508			max_protocol = interpret_protocol(optarg, max_protocol);
7509			break;
7510		case 'N':
7511			nprocs = atoi(optarg);
7512			break;
7513		case 'o':
7514			torture_numops = atoi(optarg);
7515			break;
7516		case 'd':
7517			DEBUGLEVEL = atoi(optarg);
7518			break;
7519		case 'O':
7520			sockops = optarg;
7521			break;
7522		case 'L':
7523			use_oplocks = True;
7524			break;
7525		case 'l':
7526			local_path = optarg;
7527			break;
7528		case 'A':
7529			torture_showall = True;
7530			break;
7531		case 'n':
7532			fstrcpy(myname, optarg);
7533			break;
7534		case 'c':
7535			client_txt = optarg;
7536			break;
7537		case 'e':
7538			do_encrypt = true;
7539			break;
7540		case 'k':
7541#ifdef HAVE_KRB5
7542			use_kerberos = True;
7543#else
7544			d_printf("No kerberos support compiled in\n");
7545			exit(1);
7546#endif
7547			break;
7548		case 'U':
7549			gotuser = 1;
7550			fstrcpy(username,optarg);
7551			p = strchr_m(username,'%');
7552			if (p) {
7553				*p = 0;
7554				fstrcpy(password, p+1);
7555				gotpass = 1;
7556			}
7557			break;
7558		case 'b':
7559			fstrcpy(multishare_conn_fname, optarg);
7560			use_multishare_conn = True;
7561			break;
7562		case 'B':
7563			torture_blocksize = atoi(optarg);
7564			break;
7565		default:
7566			printf("Unknown option %c (%d)\n", (char)opt, opt);
7567			usage();
7568		}
7569	}
7570
7571	d_printf("using seed %d\n", seed);
7572
7573	srandom(seed);
7574
7575	if(use_kerberos && !gotuser) gotpass = True;
7576
7577	while (!gotpass) {
7578		p = getpass("Password:");
7579		if (p) {
7580			fstrcpy(password, p);
7581			gotpass = 1;
7582		}
7583	}
7584
7585	printf("host=%s share=%s user=%s myname=%s\n",
7586	       host, share, username, myname);
7587
7588	if (argc == optind) {
7589		correct = run_test("ALL");
7590	} else {
7591		for (i=optind;i<argc;i++) {
7592			if (!run_test(argv[i])) {
7593				correct = False;
7594			}
7595		}
7596	}
7597
7598	TALLOC_FREE(frame);
7599
7600	if (correct) {
7601		return(0);
7602	} else {
7603		return(1);
7604	}
7605}
7606