add WITH_SENDFILE profiling data (from Pierre Belanger)
[Samba.git] / source / utils / torture.c
blobac3416188c71faa5fa7f2a36913767862a9bdea2
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 SMB torture tester
5 Copyright (C) Andrew Tridgell 1997-1998
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 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #define NO_SYSLOG
24 #include "includes.h"
26 #define MAX_USERS 10
27 #define MAX_TIDS 10
28 #define MAX_FIDS_PER_TID MAX_USERS
30 struct cli_state *seed;
32 typedef struct test_vuser {
34 struct cli_state cli;
36 fstring username;
37 fstring password;
38 BOOL gotpass;
39 fstring fname;
41 int vuid;
42 BOOL vuid_valid;
43 BOOL files_valid;
45 struct {
47 int tid;
48 int tid_valid;
50 int fnum[MAX_FIDS_PER_TID];
51 int backup_fnum[MAX_FIDS_PER_TID];
52 } per_tid[MAX_TIDS];
54 } TEST_VUSERS;
56 #if 0
57 static struct {
58 fstring *first;
59 fstring *last;
60 } errtab; /*keep a list of known errors to reduce noise*/
61 #endif
63 static fstring shares[MAX_TIDS];
64 static TEST_VUSERS vusers[MAX_USERS];
66 static fstring host, workgroup, myname;
67 static char *username = vusers[0].username;
68 static char *password = vusers[0].password;
69 static char *share = shares[0];
71 static int max_protocol = PROTOCOL_NT1;
72 static char *sockops="TCP_NODELAY";
73 static int nprocs=1, numops=100;
74 static int nusers=1, nshares=0;
75 static int procnum; /* records process count number when forking */
76 static struct cli_state current_cli;
77 static fstring randomfname;
78 static BOOL use_oplocks;
79 static BOOL use_level_II_oplocks;
81 static double create_procs(BOOL (*fn)(int), BOOL *result);
83 static struct timeval tp1,tp2;
85 static void start_timer(void)
87 gettimeofday(&tp1,NULL);
90 static double end_timer(void)
92 gettimeofday(&tp2,NULL);
93 return((tp2.tv_sec - tp1.tv_sec) +
94 (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
98 /* return a pointer to a anonymous shared memory segment of size "size"
99 which will persist across fork() but will disappear when all processes
100 exit
102 The memory is not zeroed
104 This function uses system5 shared memory. It takes advantage of a property
105 that the memory is not destroyed if it is attached when the id is removed
107 static void *shm_setup(int size)
109 int shmid;
110 void *ret;
112 shmid = shmget(IPC_PRIVATE, size, SHM_R | SHM_W);
113 if (shmid == -1) {
114 printf("can't get shared memory\n");
115 exit(1);
117 ret = (void *)shmat(shmid, 0, 0);
118 if (!ret || ret == (void *)-1) {
119 printf("can't attach to shared memory\n");
120 return NULL;
122 /* the following releases the ipc, but note that this process
123 and all its children will still have access to the memory, its
124 just that the shmid is no longer valid for other shm calls. This
125 means we don't leave behind lots of shm segments after we exit
127 See Stevens "advanced programming in unix env" for details
129 shmctl(shmid, IPC_RMID, 0);
131 return ret;
134 static BOOL open_nbt_connection(struct cli_state *c)
136 struct nmb_name called, calling;
137 struct in_addr ip;
139 ZERO_STRUCTP(c);
141 make_nmb_name(&calling, myname, 0x0);
142 make_nmb_name(&called , host, 0x20);
144 zero_ip(&ip);
146 if (!cli_initialise(c) || !cli_connect(c, host, &ip)) {
147 printf("Failed to connect with %s\n", host);
148 return False;
151 c->timeout = 120000; /* set a really long timeout (2 minutes) */
152 if (use_oplocks) c->use_oplocks = True;
153 if (use_level_II_oplocks) c->use_level_II_oplocks = True;
155 if (!cli_session_request(c, &calling, &called)) {
156 printf("%s rejected the session\n",host);
157 cli_shutdown(c);
158 return False;
161 return True;
164 static BOOL open_connection(struct cli_state *c)
166 ZERO_STRUCTP(c);
168 if (!open_nbt_connection(c)) {
169 return False;
172 if (!cli_negprot(c)) {
173 printf("%s rejected the negprot (%s)\n",host, cli_errstr(c));
174 cli_shutdown(c);
175 return False;
178 if (!cli_session_setup(c, username,
179 password, strlen(password),
180 password, strlen(password),
181 workgroup)) {
182 printf("%s rejected the sessionsetup (%s)\n", host, cli_errstr(c));
183 cli_shutdown(c);
184 return False;
187 if (!cli_send_tconX(c, share, "?????",
188 password, strlen(password)+1)) {
189 printf("%s refused tree connect (%s)\n", host, cli_errstr(c));
190 cli_shutdown(c);
191 return False;
194 return True;
197 static BOOL close_connection(struct cli_state *c)
199 BOOL ret = True;
200 if (!cli_tdis(c)) {
201 printf("tdis failed (%s)\n", cli_errstr(c));
202 ret = False;
205 cli_shutdown(c);
207 return ret;
211 /* check if the server produced the expected error code */
212 static BOOL check_error(struct cli_state *c,
213 uint8 eclass, uint32 ecode, uint32 nterr)
215 uint8 class;
216 uint32 num;
218 (void)cli_dos_error(c, &class, &num);
219 if ((eclass != class || ecode != num) &&
220 num != (nterr&0xFFFFFF)) {
221 printf("unexpected error code class=%d code=%d\n",
222 (int)class, (int)num);
223 printf(" expected %d/%d %d\n",
224 (int)eclass, (int)ecode, (int)nterr);
225 return False;
227 return True;
231 static BOOL wait_lock(struct cli_state *c, int fnum, uint32 offset, uint32 len)
233 while (!cli_lock(c, fnum, offset, len, -1, WRITE_LOCK)) {
234 if (!check_error(c, ERRDOS, ERRlock, 0)) return False;
236 return True;
240 static BOOL rw_torture(struct cli_state *c)
242 char *lockfname = "\\torture.lck";
243 fstring fname;
244 int fnum;
245 int fnum2;
246 pid_t pid2, pid = getpid();
247 int i, j;
248 char buf[1024];
249 BOOL correct = True;
251 fnum2 = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
252 DENY_NONE);
253 if (fnum2 == -1)
254 fnum2 = cli_open(c, lockfname, O_RDWR, DENY_NONE);
255 if (fnum2 == -1) {
256 printf("open of %s failed (%s)\n", lockfname, cli_errstr(c));
257 return False;
261 for (i=0;i<numops;i++) {
262 unsigned n = (unsigned)sys_random()%10;
263 if (i % 10 == 0) {
264 printf("%d\r", i); fflush(stdout);
266 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
268 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
269 return False;
272 fnum = cli_open(c, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL);
273 if (fnum == -1) {
274 printf("open failed (%s)\n", cli_errstr(c));
275 correct = False;
276 break;
279 if (cli_write(c, fnum, 0, (char *)&pid, 0, sizeof(pid)) != sizeof(pid)) {
280 printf("write failed (%s)\n", cli_errstr(c));
281 correct = False;
284 for (j=0;j<50;j++) {
285 if (cli_write(c, fnum, 0, (char *)buf,
286 sizeof(pid)+(j*sizeof(buf)),
287 sizeof(buf)) != sizeof(buf)) {
288 printf("write failed (%s)\n", cli_errstr(c));
289 correct = False;
293 pid2 = 0;
295 if (cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid)) != sizeof(pid)) {
296 printf("read failed (%s)\n", cli_errstr(c));
297 correct = False;
300 if (pid2 != pid) {
301 printf("data corruption!\n");
302 correct = False;
305 if (!cli_close(c, fnum)) {
306 printf("close failed (%s)\n", cli_errstr(c));
307 correct = False;
310 if (!cli_unlink(c, fname)) {
311 printf("unlink failed (%s)\n", cli_errstr(c));
312 correct = False;
315 if (!cli_unlock(c, fnum2, n*sizeof(int), sizeof(int))) {
316 printf("unlock failed (%s)\n", cli_errstr(c));
317 correct = False;
321 cli_close(c, fnum2);
322 cli_unlink(c, lockfname);
324 printf("%d\n", i);
326 return correct;
329 static BOOL run_torture(int dummy)
331 struct cli_state cli;
332 BOOL ret;
334 cli = current_cli;
336 cli_sockopt(&cli, sockops);
338 ret = rw_torture(&cli);
340 if (!close_connection(&cli)) {
341 ret = False;
344 return ret;
347 static BOOL rw_torture3(struct cli_state *c, char *lockfname)
349 int fnum = -1;
350 int i = 0;
351 char buf[131072];
352 char buf_rd[131072];
353 unsigned count;
354 unsigned countprev = 0;
355 unsigned sent = 0;
356 BOOL correct = True;
358 srandom(1);
359 for (i = 0; i < sizeof(buf); i += sizeof(uint32))
361 SIVAL(buf, i, sys_random());
364 if (procnum == 0)
366 fnum = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
367 DENY_NONE);
368 if (fnum == -1) {
369 printf("first open read/write of %s failed (%s)\n",
370 lockfname, cli_errstr(c));
371 return False;
374 else
376 for (i = 0; i < 500 && fnum == -1; i++)
378 fnum = cli_open(c, lockfname, O_RDONLY,
379 DENY_NONE);
380 msleep(10);
382 if (fnum == -1) {
383 printf("second open read-only of %s failed (%s)\n",
384 lockfname, cli_errstr(c));
385 return False;
389 i = 0;
390 for (count = 0; count < sizeof(buf); count += sent)
392 if (count >= countprev) {
393 printf("%d %8d\r", i, count);
394 fflush(stdout);
395 i++;
396 countprev += (sizeof(buf) / 20);
399 if (procnum == 0)
401 sent = ((unsigned)sys_random()%(20))+ 1;
402 if (sent > sizeof(buf) - count)
404 sent = sizeof(buf) - count;
407 if (cli_write(c, fnum, 0, buf+count, count, sent) != sent) {
408 printf("write failed (%s)\n", cli_errstr(c));
409 correct = False;
412 else
414 sent = cli_read(c, fnum, buf_rd+count, count,
415 sizeof(buf)-count);
416 if (sent < 0)
418 printf("read failed offset:%d size:%d (%s)\n",
419 count, sizeof(buf)-count,
420 cli_errstr(c));
421 correct = False;
422 sent = 0;
424 if (sent > 0)
426 if (memcmp(buf_rd+count, buf+count, sent) != 0)
428 printf("read/write compare failed\n");
429 printf("offset: %d req %d recvd %d\n",
430 count, sizeof(buf)-count, sent);
431 correct = False;
432 break;
439 if (!cli_close(c, fnum)) {
440 printf("close failed (%s)\n", cli_errstr(c));
441 correct = False;
444 return correct;
447 static BOOL rw_torture2(struct cli_state *c1, struct cli_state *c2)
449 char *lockfname = "\\torture.lck";
450 int fnum1;
451 int fnum2;
452 int i;
453 char buf[131072];
454 char buf_rd[131072];
455 BOOL correct = True;
456 ssize_t bytes_read;
458 if (!cli_unlink(c1, lockfname)) {
459 printf("unlink failed (%s) (normal, this file should not exist)\n", cli_errstr(c1));
462 fnum1 = cli_open(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
463 DENY_NONE);
464 if (fnum1 == -1) {
465 printf("first open read/write of %s failed (%s)\n",
466 lockfname, cli_errstr(c1));
467 return False;
469 fnum2 = cli_open(c2, lockfname, O_RDONLY,
470 DENY_NONE);
471 if (fnum2 == -1) {
472 printf("second open read-only of %s failed (%s)\n",
473 lockfname, cli_errstr(c2));
474 cli_close(c1, fnum1);
475 return False;
478 for (i=0;i<numops;i++)
480 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
481 if (i % 10 == 0) {
482 printf("%d\r", i); fflush(stdout);
485 generate_random_buffer(buf, buf_size, False);
487 if (cli_write(c1, fnum1, 0, buf, 0, buf_size) != buf_size) {
488 printf("write failed (%s)\n", cli_errstr(c1));
489 correct = False;
492 if ((bytes_read = cli_read(c2, fnum2, buf_rd, 0, buf_size)) != buf_size) {
493 printf("read failed (%s)\n", cli_errstr(c2));
494 printf("read %d, expected %d\n", bytes_read, buf_size);
495 correct = False;
498 if (memcmp(buf_rd, buf, buf_size) != 0)
500 printf("read/write compare failed\n");
501 correct = False;
505 if (!cli_close(c2, fnum2)) {
506 printf("close failed (%s)\n", cli_errstr(c2));
507 correct = False;
509 if (!cli_close(c1, fnum1)) {
510 printf("close failed (%s)\n", cli_errstr(c1));
511 correct = False;
514 if (!cli_unlink(c1, lockfname)) {
515 printf("unlink failed (%s)\n", cli_errstr(c1));
516 correct = False;
519 return correct;
522 static BOOL run_readwritetest(int dummy)
524 static struct cli_state cli1, cli2;
525 BOOL test1, test2;
527 if (!open_connection(&cli1) || !open_connection(&cli2)) {
528 return False;
530 cli_sockopt(&cli1, sockops);
531 cli_sockopt(&cli2, sockops);
533 printf("starting readwritetest\n");
535 test1 = rw_torture2(&cli1, &cli2);
536 printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
538 test2 = rw_torture2(&cli1, &cli1);
539 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
541 if (!close_connection(&cli1)) {
542 test1 = False;
545 if (!close_connection(&cli2)) {
546 test2 = False;
549 return (test1 && test2);
552 static BOOL run_readwritemulti(int dummy)
554 static struct cli_state cli;
555 BOOL test;
557 cli = current_cli;
559 cli_sockopt(&cli, sockops);
561 printf("run_readwritemulti: fname %s\n", randomfname);
562 test = rw_torture3(&cli, randomfname);
564 if (!close_connection(&cli)) {
565 test = False;
568 return test;
571 static BOOL run_readwritelarge(int dummy)
573 static struct cli_state cli1;
574 int fnum1;
575 char *lockfname = "\\large.dat";
576 size_t fsize;
577 char buf[0x10000];
578 BOOL correct = True;
580 if (!open_connection(&cli1)) {
581 return False;
583 cli_sockopt(&cli1, sockops);
584 memset(buf,'\0',sizeof(buf));
586 cli1.max_xmit = 0x11000;
588 printf("starting readwritelarge\n");
590 cli_unlink(&cli1, lockfname);
592 fnum1 = cli_open(&cli1, lockfname, O_RDWR | O_CREAT | O_EXCL, DENY_NONE);
593 if (fnum1 == -1) {
594 printf("open read/write of %s failed (%s)\n", lockfname, cli_errstr(&cli1));
595 return False;
598 cli_write(&cli1, fnum1, 0, buf, 0, sizeof(buf));
600 if (!cli_close(&cli1, fnum1)) {
601 printf("close failed (%s)\n", cli_errstr(&cli1));
602 correct = False;
605 if (!cli_qpathinfo(&cli1, lockfname, NULL, NULL, NULL, &fsize, NULL)) {
606 printf("qpathinfo failed (%s)\n", cli_errstr(&cli1));
607 correct = False;
610 if (fsize == sizeof(buf))
611 printf("readwritelarge test 1 succeeded (size = %x)\n", fsize);
612 else {
613 printf("readwritelarge test 1 failed (size = %x)\n", fsize);
614 correct = False;
617 if (!cli_unlink(&cli1, lockfname)) {
618 printf("unlink failed (%s)\n", cli_errstr(&cli1));
619 correct = False;
622 fnum1 = cli_open(&cli1, lockfname, O_RDWR | O_CREAT | O_EXCL, DENY_NONE);
623 if (fnum1 == -1) {
624 printf("open read/write of %s failed (%s)\n", lockfname, cli_errstr(&cli1));
625 return False;
628 cli_smbwrite(&cli1, fnum1, buf, 0, sizeof(buf));
630 if (!cli_close(&cli1, fnum1)) {
631 printf("close failed (%s)\n", cli_errstr(&cli1));
632 correct = False;
635 if (!close_connection(&cli1)) {
636 correct = False;
638 return correct;
641 int line_count = 0;
643 /* run a test that simulates an approximate netbench client load */
644 static BOOL run_netbench(int client)
646 struct cli_state cli;
647 int i;
648 fstring fname;
649 pstring line;
650 char cname[20];
651 FILE *f;
652 char *params[20];
653 BOOL correct = True;
655 cli = current_cli;
657 cli_sockopt(&cli, sockops);
659 nb_setup(&cli);
661 slprintf(cname,sizeof(fname), "CLIENT%d", client);
663 f = fopen("client.txt", "r");
665 if (!f) {
666 perror("client.txt");
667 return False;
670 while (fgets(line, sizeof(line)-1, f)) {
671 line_count++;
673 line[strlen(line)-1] = 0;
675 /* printf("[%d] %s\n", line_count, line); */
677 all_string_sub(line,"CLIENT1", cname, sizeof(line));
679 for (i=0;i<20;i++) params[i] = "";
681 /* parse the command parameters */
682 params[0] = strtok(line," ");
683 i = 0;
684 while (params[i]) params[++i] = strtok(NULL," ");
686 params[i] = "";
688 if (i < 2) continue;
690 if (strcmp(params[1],"REQUEST") == 0) {
691 if (!strcmp(params[0],"SMBopenX")) {
692 fstrcpy(fname, params[5]);
693 } else if (!strcmp(params[0],"SMBclose")) {
694 nb_close(atoi(params[3]));
695 } else if (!strcmp(params[0],"SMBmkdir")) {
696 nb_mkdir(params[3]);
697 } else if (!strcmp(params[0],"CREATE")) {
698 nb_create(params[3], atoi(params[5]));
699 } else if (!strcmp(params[0],"SMBrmdir")) {
700 nb_rmdir(params[3]);
701 } else if (!strcmp(params[0],"SMBunlink")) {
702 fstrcpy(fname, params[3]);
703 } else if (!strcmp(params[0],"SMBmv")) {
704 nb_rename(params[3], params[5]);
705 } else if (!strcmp(params[0],"SMBgetatr")) {
706 fstrcpy(fname, params[3]);
707 } else if (!strcmp(params[0],"SMBwrite")) {
708 nb_write(atoi(params[3]),
709 atoi(params[5]), atoi(params[7]));
710 } else if (!strcmp(params[0],"SMBwritebraw")) {
711 nb_write(atoi(params[3]),
712 atoi(params[7]), atoi(params[5]));
713 } else if (!strcmp(params[0],"SMBreadbraw")) {
714 nb_read(atoi(params[3]),
715 atoi(params[7]), atoi(params[5]));
716 } else if (!strcmp(params[0],"SMBread")) {
717 nb_read(atoi(params[3]),
718 atoi(params[5]), atoi(params[7]));
720 } else {
721 if (!strcmp(params[0],"SMBopenX")) {
722 if (!strncmp(params[2], "ERR", 3)) continue;
723 nb_open(fname, atoi(params[3]), atoi(params[5]));
724 } else if (!strcmp(params[0],"SMBgetatr")) {
725 if (!strncmp(params[2], "ERR", 3)) continue;
726 nb_stat(fname, atoi(params[3]));
727 } else if (!strcmp(params[0],"SMBunlink")) {
728 if (!strncmp(params[2], "ERR", 3)) continue;
729 nb_unlink(fname);
733 fclose(f);
735 slprintf(fname,sizeof(fname), "CLIENTS/CLIENT%d", client);
736 rmdir(fname);
737 rmdir("CLIENTS");
739 printf("+");
741 if (!close_connection(&cli)) {
742 correct = False;
745 return correct;
749 /* run a test that simulates an approximate netbench w9X client load */
750 static BOOL run_nbw95(int dummy)
752 double t;
753 BOOL correct = True;
754 t = create_procs(run_netbench, &correct);
755 /* to produce a netbench result we scale accoding to the
756 netbench measured throughput for the run that produced the
757 sniff that was used to produce client.txt. That run used 2
758 clients and ran for 660 seconds to produce a result of
759 4MBit/sec. */
760 printf("Throughput %g MB/sec (NB=%g MB/sec %g MBit/sec)\n",
761 132*nprocs/t, 0.5*0.5*nprocs*660/t, 2*nprocs*660/t);
762 return correct;
765 /* run a test that simulates an approximate netbench wNT client load */
766 static BOOL run_nbwnt(int dummy)
768 double t;
769 BOOL correct = True;
770 t = create_procs(run_netbench, &correct);
771 printf("Throughput %g MB/sec (NB=%g MB/sec %g MBit/sec)\n",
772 132*nprocs/t, 0.5*0.5*nprocs*660/t, 2*nprocs*660/t);
773 return correct;
779 This test checks for two things:
781 1) correct support for retaining locks over a close (ie. the server
782 must not use posix semantics)
783 2) support for lock timeouts
785 static BOOL run_locktest1(int dummy)
787 static struct cli_state cli1, cli2;
788 char *fname = "\\lockt1.lck";
789 int fnum1, fnum2, fnum3;
790 time_t t1, t2;
792 if (!open_connection(&cli1) || !open_connection(&cli2)) {
793 return False;
795 cli_sockopt(&cli1, sockops);
796 cli_sockopt(&cli2, sockops);
798 printf("starting locktest1\n");
800 cli_unlink(&cli1, fname);
802 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
803 if (fnum1 == -1) {
804 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
805 return False;
807 fnum2 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
808 if (fnum2 == -1) {
809 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli1));
810 return False;
812 fnum3 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
813 if (fnum3 == -1) {
814 printf("open3 of %s failed (%s)\n", fname, cli_errstr(&cli2));
815 return False;
818 if (!cli_lock(&cli1, fnum1, 0, 4, 0, WRITE_LOCK)) {
819 printf("lock1 failed (%s)\n", cli_errstr(&cli1));
820 return False;
824 if (cli_lock(&cli2, fnum3, 0, 4, 0, WRITE_LOCK)) {
825 printf("lock2 succeeded! This is a locking bug\n");
826 return False;
827 } else {
828 if (!check_error(&cli2, ERRDOS, ERRlock, 0)) return False;
832 printf("Testing lock timeouts\n");
833 t1 = time(NULL);
834 if (cli_lock(&cli2, fnum3, 0, 4, 10*1000, WRITE_LOCK)) {
835 printf("lock3 succeeded! This is a locking bug\n");
836 return False;
837 } else {
838 if (!check_error(&cli2, ERRDOS, ERRlock, 0)) return False;
840 t2 = time(NULL);
842 if (t2 - t1 < 5) {
843 printf("error: This server appears not to support timed lock requests\n");
846 if (!cli_close(&cli1, fnum2)) {
847 printf("close1 failed (%s)\n", cli_errstr(&cli1));
848 return False;
851 if (cli_lock(&cli2, fnum3, 0, 4, 0, WRITE_LOCK)) {
852 printf("lock4 succeeded! This is a locking bug\n");
853 return False;
854 } else {
855 if (!check_error(&cli2, ERRDOS, ERRlock, 0)) return False;
858 if (!cli_close(&cli1, fnum1)) {
859 printf("close2 failed (%s)\n", cli_errstr(&cli1));
860 return False;
863 if (!cli_close(&cli2, fnum3)) {
864 printf("close3 failed (%s)\n", cli_errstr(&cli2));
865 return False;
868 if (!cli_unlink(&cli1, fname)) {
869 printf("unlink failed (%s)\n", cli_errstr(&cli1));
870 return False;
874 if (!close_connection(&cli1)) {
875 return False;
878 if (!close_connection(&cli2)) {
879 return False;
882 printf("Passed locktest1\n");
883 return True;
887 checks for correct tconX support
889 static BOOL run_tcon_test(int dummy)
891 static struct cli_state cli1;
892 char *fname = "\\tcontest.tmp";
893 int fnum1;
894 uint16 cnum;
895 char buf[4];
897 if (!open_connection(&cli1)) {
898 return False;
900 cli_sockopt(&cli1, sockops);
902 printf("starting tcontest\n");
904 cli_unlink(&cli1, fname);
906 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
907 if (fnum1 == -1)
909 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
910 return False;
913 cnum = cli1.cnum;
915 if (cli_write(&cli1, fnum1, 0, buf, 130, 4) != 4)
917 printf("write failed (%s)", cli_errstr(&cli1));
918 return False;
921 if (!cli_send_tconX(&cli1, share, "?????",
922 password, strlen(password)+1)) {
923 printf("%s refused 2nd tree connect (%s)\n", host,
924 cli_errstr(&cli1));
925 cli_shutdown(&cli1);
926 return False;
929 if (cli_write(&cli1, fnum1, 0, buf, 130, 4) == 4)
931 printf("write succeeded (%s)", cli_errstr(&cli1));
932 return False;
935 if (cli_close(&cli1, fnum1)) {
936 printf("close2 succeeded (%s)\n", cli_errstr(&cli1));
937 return False;
940 if (!cli_tdis(&cli1)) {
941 printf("tdis failed (%s)\n", cli_errstr(&cli1));
942 return False;
945 cli1.cnum = cnum;
947 if (!cli_close(&cli1, fnum1)) {
948 printf("close2 failed (%s)\n", cli_errstr(&cli1));
949 return False;
952 if (!close_connection(&cli1)) {
953 return False;
956 printf("Passed tcontest\n");
957 return True;
962 This test checks that
964 1) the server supports multiple locking contexts on the one SMB
965 connection, distinguished by PID.
967 2) the server correctly fails overlapping locks made by the same PID (this
968 goes against POSIX behaviour, which is why it is tricky to implement)
970 3) the server denies unlock requests by an incorrect client PID
972 static BOOL run_locktest2(int dummy)
974 static struct cli_state cli;
975 char *fname = "\\lockt2.lck";
976 int fnum1, fnum2, fnum3;
977 BOOL correct = True;
979 if (!open_connection(&cli)) {
980 return False;
983 cli_sockopt(&cli, sockops);
985 printf("starting locktest2\n");
987 cli_unlink(&cli, fname);
989 cli_setpid(&cli, 1);
991 fnum1 = cli_open(&cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
992 if (fnum1 == -1) {
993 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
994 return False;
997 fnum2 = cli_open(&cli, fname, O_RDWR, DENY_NONE);
998 if (fnum2 == -1) {
999 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli));
1000 return False;
1003 cli_setpid(&cli, 2);
1005 fnum3 = cli_open(&cli, fname, O_RDWR, DENY_NONE);
1006 if (fnum3 == -1) {
1007 printf("open3 of %s failed (%s)\n", fname, cli_errstr(&cli));
1008 return False;
1011 cli_setpid(&cli, 1);
1013 if (!cli_lock(&cli, fnum1, 0, 4, 0, WRITE_LOCK)) {
1014 printf("lock1 failed (%s)\n", cli_errstr(&cli));
1015 return False;
1018 if (cli_lock(&cli, fnum1, 0, 4, 0, WRITE_LOCK)) {
1019 printf("WRITE lock1 succeeded! This is a locking bug\n");
1020 correct = False;
1021 } else {
1022 if (!check_error(&cli, ERRDOS, ERRlock, 0)) return False;
1025 if (cli_lock(&cli, fnum2, 0, 4, 0, WRITE_LOCK)) {
1026 printf("WRITE lock2 succeeded! This is a locking bug\n");
1027 correct = False;
1028 } else {
1029 if (!check_error(&cli, ERRDOS, ERRlock, 0)) return False;
1032 if (cli_lock(&cli, fnum2, 0, 4, 0, READ_LOCK)) {
1033 printf("READ lock2 succeeded! This is a locking bug\n");
1034 correct = False;
1035 } else {
1036 if (!check_error(&cli, ERRDOS, ERRlock, 0)) return False;
1039 if (!cli_lock(&cli, fnum1, 100, 4, 0, WRITE_LOCK)) {
1040 printf("lock at 100 failed (%s)\n", cli_errstr(&cli));
1042 cli_setpid(&cli, 2);
1043 if (cli_unlock(&cli, fnum1, 100, 4)) {
1044 printf("unlock at 100 succeeded! This is a locking bug\n");
1045 correct = False;
1048 if (cli_unlock(&cli, fnum1, 0, 4)) {
1049 printf("unlock1 succeeded! This is a locking bug\n");
1050 correct = False;
1051 } else {
1052 if (!check_error(&cli, ERRDOS, ERRnotlocked, 0)) return False;
1055 if (cli_unlock(&cli, fnum1, 0, 8)) {
1056 printf("unlock2 succeeded! This is a locking bug\n");
1057 correct = False;
1058 } else {
1059 if (!check_error(&cli, ERRDOS, ERRnotlocked, 0)) return False;
1062 if (cli_lock(&cli, fnum3, 0, 4, 0, WRITE_LOCK)) {
1063 printf("lock3 succeeded! This is a locking bug\n");
1064 correct = False;
1065 } else {
1066 if (!check_error(&cli, ERRDOS, ERRlock, 0)) return False;
1069 cli_setpid(&cli, 1);
1071 if (!cli_close(&cli, fnum1)) {
1072 printf("close1 failed (%s)\n", cli_errstr(&cli));
1073 return False;
1076 if (!cli_close(&cli, fnum2)) {
1077 printf("close2 failed (%s)\n", cli_errstr(&cli));
1078 return False;
1081 if (!cli_close(&cli, fnum3)) {
1082 printf("close3 failed (%s)\n", cli_errstr(&cli));
1083 return False;
1086 if (!close_connection(&cli)) {
1087 correct = False;
1090 printf("locktest2 finished\n");
1092 return correct;
1097 This test checks that
1099 1) the server supports the full offset range in lock requests
1101 static BOOL run_locktest3(int dummy)
1103 static struct cli_state cli1, cli2;
1104 char *fname = "\\lockt3.lck";
1105 int fnum1, fnum2, i;
1106 uint32 offset;
1107 BOOL correct = True;
1109 #define NEXT_OFFSET offset += (~(uint32)0) / numops
1111 if (!open_connection(&cli1) || !open_connection(&cli2)) {
1112 return False;
1114 cli_sockopt(&cli1, sockops);
1115 cli_sockopt(&cli2, sockops);
1117 printf("starting locktest3\n");
1119 cli_unlink(&cli1, fname);
1121 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1122 if (fnum1 == -1) {
1123 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
1124 return False;
1126 fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
1127 if (fnum2 == -1) {
1128 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli2));
1129 return False;
1132 for (offset=i=0;i<numops;i++) {
1133 NEXT_OFFSET;
1134 if (!cli_lock(&cli1, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
1135 printf("lock1 %d failed (%s)\n",
1137 cli_errstr(&cli1));
1138 return False;
1141 if (!cli_lock(&cli2, fnum2, offset-2, 1, 0, WRITE_LOCK)) {
1142 printf("lock2 %d failed (%s)\n",
1144 cli_errstr(&cli1));
1145 return False;
1149 for (offset=i=0;i<numops;i++) {
1150 NEXT_OFFSET;
1152 if (cli_lock(&cli1, fnum1, offset-2, 1, 0, WRITE_LOCK)) {
1153 printf("error: lock1 %d succeeded!\n", i);
1154 return False;
1157 if (cli_lock(&cli2, fnum2, offset-1, 1, 0, WRITE_LOCK)) {
1158 printf("error: lock2 %d succeeded!\n", i);
1159 return False;
1162 if (cli_lock(&cli1, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
1163 printf("error: lock3 %d succeeded!\n", i);
1164 return False;
1167 if (cli_lock(&cli2, fnum2, offset-2, 1, 0, WRITE_LOCK)) {
1168 printf("error: lock4 %d succeeded!\n", i);
1169 return False;
1173 for (offset=i=0;i<numops;i++) {
1174 NEXT_OFFSET;
1176 if (!cli_unlock(&cli1, fnum1, offset-1, 1)) {
1177 printf("unlock1 %d failed (%s)\n",
1179 cli_errstr(&cli1));
1180 return False;
1183 if (!cli_unlock(&cli2, fnum2, offset-2, 1)) {
1184 printf("unlock2 %d failed (%s)\n",
1186 cli_errstr(&cli1));
1187 return False;
1191 if (!cli_close(&cli1, fnum1)) {
1192 printf("close1 failed (%s)\n", cli_errstr(&cli1));
1193 return False;
1196 if (!cli_close(&cli2, fnum2)) {
1197 printf("close2 failed (%s)\n", cli_errstr(&cli2));
1198 return False;
1201 if (!cli_unlink(&cli1, fname)) {
1202 printf("unlink failed (%s)\n", cli_errstr(&cli1));
1203 return False;
1206 if (!close_connection(&cli1)) {
1207 correct = False;
1210 if (!close_connection(&cli2)) {
1211 correct = False;
1214 printf("finished locktest3\n");
1216 return correct;
1219 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1220 printf("** "); correct = False; \
1224 looks at overlapping locks
1226 static BOOL run_locktest4(int dummy)
1228 static struct cli_state cli1, cli2;
1229 char *fname = "\\lockt4.lck";
1230 int fnum1, fnum2, f;
1231 BOOL ret;
1232 char buf[1000];
1233 BOOL correct = True;
1235 if (!open_connection(&cli1) || !open_connection(&cli2)) {
1236 return False;
1239 cli_sockopt(&cli1, sockops);
1240 cli_sockopt(&cli2, sockops);
1242 printf("starting locktest4\n");
1244 cli_unlink(&cli1, fname);
1246 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1247 fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
1249 memset(buf, 0, sizeof(buf));
1251 if (cli_write(&cli1, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
1252 printf("Failed to create file\n");
1253 correct = False;
1254 goto fail;
1257 ret = cli_lock(&cli1, fnum1, 0, 4, 0, WRITE_LOCK) &&
1258 cli_lock(&cli1, fnum1, 2, 4, 0, WRITE_LOCK);
1259 EXPECTED(ret, False);
1260 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1262 ret = cli_lock(&cli1, fnum1, 10, 4, 0, READ_LOCK) &&
1263 cli_lock(&cli1, fnum1, 12, 4, 0, READ_LOCK);
1264 EXPECTED(ret, True);
1265 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1267 ret = cli_lock(&cli1, fnum1, 20, 4, 0, WRITE_LOCK) &&
1268 cli_lock(&cli2, fnum2, 22, 4, 0, WRITE_LOCK);
1269 EXPECTED(ret, False);
1270 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1272 ret = cli_lock(&cli1, fnum1, 30, 4, 0, READ_LOCK) &&
1273 cli_lock(&cli2, fnum2, 32, 4, 0, READ_LOCK);
1274 EXPECTED(ret, True);
1275 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1277 ret = (cli_setpid(&cli1, 1), cli_lock(&cli1, fnum1, 40, 4, 0, WRITE_LOCK)) &&
1278 (cli_setpid(&cli1, 2), cli_lock(&cli1, fnum1, 42, 4, 0, WRITE_LOCK));
1279 EXPECTED(ret, False);
1280 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1282 ret = (cli_setpid(&cli1, 1), cli_lock(&cli1, fnum1, 50, 4, 0, READ_LOCK)) &&
1283 (cli_setpid(&cli1, 2), cli_lock(&cli1, fnum1, 52, 4, 0, READ_LOCK));
1284 EXPECTED(ret, True);
1285 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1287 ret = cli_lock(&cli1, fnum1, 60, 4, 0, READ_LOCK) &&
1288 cli_lock(&cli1, fnum1, 60, 4, 0, READ_LOCK);
1289 EXPECTED(ret, True);
1290 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1292 ret = cli_lock(&cli1, fnum1, 70, 4, 0, WRITE_LOCK) &&
1293 cli_lock(&cli1, fnum1, 70, 4, 0, WRITE_LOCK);
1294 EXPECTED(ret, False);
1295 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1297 ret = cli_lock(&cli1, fnum1, 80, 4, 0, READ_LOCK) &&
1298 cli_lock(&cli1, fnum1, 80, 4, 0, WRITE_LOCK);
1299 EXPECTED(ret, False);
1300 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
1302 ret = cli_lock(&cli1, fnum1, 90, 4, 0, WRITE_LOCK) &&
1303 cli_lock(&cli1, fnum1, 90, 4, 0, READ_LOCK);
1304 EXPECTED(ret, True);
1305 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1307 ret = (cli_setpid(&cli1, 1), cli_lock(&cli1, fnum1, 100, 4, 0, WRITE_LOCK)) &&
1308 (cli_setpid(&cli1, 2), cli_lock(&cli1, fnum1, 100, 4, 0, READ_LOCK));
1309 EXPECTED(ret, False);
1310 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1312 ret = cli_lock(&cli1, fnum1, 110, 4, 0, READ_LOCK) &&
1313 cli_lock(&cli1, fnum1, 112, 4, 0, READ_LOCK) &&
1314 cli_unlock(&cli1, fnum1, 110, 6);
1315 EXPECTED(ret, False);
1316 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
1319 ret = cli_lock(&cli1, fnum1, 120, 4, 0, WRITE_LOCK) &&
1320 (cli_read(&cli2, fnum2, buf, 120, 4) == 4);
1321 EXPECTED(ret, False);
1322 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
1324 ret = cli_lock(&cli1, fnum1, 130, 4, 0, READ_LOCK) &&
1325 (cli_write(&cli2, fnum2, 0, buf, 130, 4) == 4);
1326 EXPECTED(ret, False);
1327 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
1330 ret = cli_lock(&cli1, fnum1, 140, 4, 0, READ_LOCK) &&
1331 cli_lock(&cli1, fnum1, 140, 4, 0, READ_LOCK) &&
1332 cli_unlock(&cli1, fnum1, 140, 4) &&
1333 cli_unlock(&cli1, fnum1, 140, 4);
1334 EXPECTED(ret, True);
1335 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
1338 ret = cli_lock(&cli1, fnum1, 150, 4, 0, WRITE_LOCK) &&
1339 cli_lock(&cli1, fnum1, 150, 4, 0, READ_LOCK) &&
1340 cli_unlock(&cli1, fnum1, 150, 4) &&
1341 (cli_read(&cli2, fnum2, buf, 150, 4) == 4) &&
1342 !(cli_write(&cli2, fnum2, 0, buf, 150, 4) == 4) &&
1343 cli_unlock(&cli1, fnum1, 150, 4);
1344 EXPECTED(ret, True);
1345 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
1347 ret = cli_lock(&cli1, fnum1, 160, 4, 0, READ_LOCK) &&
1348 cli_unlock(&cli1, fnum1, 160, 4) &&
1349 (cli_write(&cli2, fnum2, 0, buf, 160, 4) == 4) &&
1350 (cli_read(&cli2, fnum2, buf, 160, 4) == 4);
1351 EXPECTED(ret, True);
1352 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
1354 ret = cli_lock(&cli1, fnum1, 170, 4, 0, WRITE_LOCK) &&
1355 cli_unlock(&cli1, fnum1, 170, 4) &&
1356 (cli_write(&cli2, fnum2, 0, buf, 170, 4) == 4) &&
1357 (cli_read(&cli2, fnum2, buf, 170, 4) == 4);
1358 EXPECTED(ret, True);
1359 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
1361 ret = cli_lock(&cli1, fnum1, 190, 4, 0, WRITE_LOCK) &&
1362 cli_lock(&cli1, fnum1, 190, 4, 0, READ_LOCK) &&
1363 cli_unlock(&cli1, fnum1, 190, 4) &&
1364 !(cli_write(&cli2, fnum2, 0, buf, 190, 4) == 4) &&
1365 (cli_read(&cli2, fnum2, buf, 190, 4) == 4);
1366 EXPECTED(ret, True);
1367 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
1369 cli_close(&cli1, fnum1);
1370 cli_close(&cli2, fnum2);
1371 fnum1 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
1372 f = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
1373 ret = cli_lock(&cli1, fnum1, 0, 8, 0, READ_LOCK) &&
1374 cli_lock(&cli1, f, 0, 1, 0, READ_LOCK) &&
1375 cli_close(&cli1, fnum1) &&
1376 ((fnum1 = cli_open(&cli1, fname, O_RDWR, DENY_NONE)) != -1) &&
1377 cli_lock(&cli1, fnum1, 7, 1, 0, WRITE_LOCK);
1378 cli_close(&cli1, f);
1379 EXPECTED(ret, True);
1380 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
1382 fail:
1383 cli_close(&cli1, fnum1);
1384 cli_close(&cli2, fnum2);
1385 cli_unlink(&cli1, fname);
1386 close_connection(&cli1);
1387 close_connection(&cli2);
1389 printf("finished locktest4\n");
1390 return correct;
1394 looks at lock upgrade/downgrade.
1396 static BOOL run_locktest5(int dummy)
1398 static struct cli_state cli1, cli2;
1399 char *fname = "\\lockt5.lck";
1400 int fnum1, fnum2, fnum3;
1401 BOOL ret;
1402 char buf[1000];
1403 BOOL correct = True;
1405 if (!open_connection(&cli1) || !open_connection(&cli2)) {
1406 return False;
1409 cli_sockopt(&cli1, sockops);
1410 cli_sockopt(&cli2, sockops);
1412 printf("starting locktest5\n");
1414 cli_unlink(&cli1, fname);
1416 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1417 fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
1418 fnum3 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
1420 memset(buf, 0, sizeof(buf));
1422 if (cli_write(&cli1, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
1423 printf("Failed to create file\n");
1424 correct = False;
1425 goto fail;
1428 /* Check for NT bug... */
1429 ret = cli_lock(&cli1, fnum1, 0, 8, 0, READ_LOCK) &&
1430 cli_lock(&cli1, fnum3, 0, 1, 0, READ_LOCK);
1431 cli_close(&cli1, fnum1);
1432 fnum1 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
1433 ret = cli_lock(&cli1, fnum1, 7, 1, 0, WRITE_LOCK);
1434 EXPECTED(ret, True);
1435 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
1436 cli_close(&cli1, fnum1);
1437 fnum1 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
1438 cli_unlock(&cli1, fnum3, 0, 1);
1440 ret = cli_lock(&cli1, fnum1, 0, 4, 0, WRITE_LOCK) &&
1441 cli_lock(&cli1, fnum1, 1, 1, 0, READ_LOCK);
1442 EXPECTED(ret, True);
1443 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
1445 ret = cli_lock(&cli2, fnum2, 0, 4, 0, READ_LOCK);
1446 EXPECTED(ret, False);
1448 printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
1450 /* Unlock the process 2 lock. */
1451 cli_unlock(&cli2, fnum2, 0, 4);
1453 ret = cli_lock(&cli1, fnum3, 0, 4, 0, READ_LOCK);
1454 EXPECTED(ret, False);
1456 printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
1458 /* Unlock the process 1 fnum3 lock. */
1459 cli_unlock(&cli1, fnum3, 0, 4);
1461 /* Stack 2 more locks here. */
1462 ret = cli_lock(&cli1, fnum1, 0, 4, 0, READ_LOCK) &&
1463 cli_lock(&cli1, fnum1, 0, 4, 0, READ_LOCK);
1465 EXPECTED(ret, True);
1466 printf("the same process %s stack read locks\n", ret?"can":"cannot");
1468 /* Unlock the first process lock, then check this was the WRITE lock that was
1469 removed. */
1471 ret = cli_unlock(&cli1, fnum1, 0, 4) &&
1472 cli_lock(&cli2, fnum2, 0, 4, 0, READ_LOCK);
1474 EXPECTED(ret, True);
1475 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
1477 /* Unlock the process 2 lock. */
1478 cli_unlock(&cli2, fnum2, 0, 4);
1480 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
1482 ret = cli_unlock(&cli1, fnum1, 1, 1) &&
1483 cli_unlock(&cli1, fnum1, 0, 4) &&
1484 cli_unlock(&cli1, fnum1, 0, 4);
1486 EXPECTED(ret, True);
1487 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
1489 /* Ensure the next unlock fails. */
1490 ret = cli_unlock(&cli1, fnum1, 0, 4);
1491 EXPECTED(ret, False);
1492 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
1494 /* Ensure connection 2 can get a write lock. */
1495 ret = cli_lock(&cli2, fnum2, 0, 4, 0, WRITE_LOCK);
1496 EXPECTED(ret, True);
1498 printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
1501 fail:
1502 cli_close(&cli1, fnum1);
1503 cli_close(&cli2, fnum2);
1504 cli_unlink(&cli1, fname);
1505 if (!close_connection(&cli1)) {
1506 correct = False;
1508 if (!close_connection(&cli2)) {
1509 correct = False;
1512 printf("finished locktest5\n");
1514 return correct;
1519 this produces a matrix of deny mode behaviour
1521 static BOOL run_denytest1(int dummy)
1523 static struct cli_state cli1, cli2;
1524 int fnum1, fnum2;
1525 int f, d1, d2, o1, o2, x=0;
1526 char *fnames[] = {"\\denytest1.exe", "\\denytest1.dat", NULL};
1527 struct {
1528 int v;
1529 char *name;
1530 } deny_modes[] = {
1531 {DENY_DOS, "DENY_DOS"},
1532 {DENY_ALL, "DENY_ALL"},
1533 {DENY_WRITE, "DENY_WRITE"},
1534 {DENY_READ, "DENY_READ"},
1535 {DENY_NONE, "DENY_NONE"},
1536 {DENY_FCB, "DENY_FCB"},
1537 {-1, NULL}};
1538 struct {
1539 int v;
1540 char *name;
1541 } open_modes[] = {
1542 {O_RDWR, "O_RDWR"},
1543 {O_RDONLY, "O_RDONLY"},
1544 {O_WRONLY, "O_WRONLY"},
1545 {-1, NULL}};
1546 BOOL correct = True;
1548 if (!open_connection(&cli1) || !open_connection(&cli2)) {
1549 return False;
1551 cli_sockopt(&cli1, sockops);
1552 cli_sockopt(&cli2, sockops);
1554 printf("starting denytest1\n");
1556 for (f=0;fnames[f];f++) {
1557 cli_unlink(&cli1, fnames[f]);
1559 fnum1 = cli_open(&cli1, fnames[f], O_RDWR|O_CREAT, DENY_NONE);
1560 cli_write(&cli1, fnum1, 0, fnames[f], 0, strlen(fnames[f]));
1561 cli_close(&cli1, fnum1);
1563 for (d1=0;deny_modes[d1].name;d1++)
1564 for (o1=0;open_modes[o1].name;o1++)
1565 for (d2=0;deny_modes[d2].name;d2++)
1566 for (o2=0;open_modes[o2].name;o2++) {
1567 fnum1 = cli_open(&cli1, fnames[f],
1568 open_modes[o1].v,
1569 deny_modes[d1].v);
1570 fnum2 = cli_open(&cli2, fnames[f],
1571 open_modes[o2].v,
1572 deny_modes[d2].v);
1574 printf("%s %8s %10s %8s %10s ",
1575 fnames[f],
1576 open_modes[o1].name,
1577 deny_modes[d1].name,
1578 open_modes[o2].name,
1579 deny_modes[d2].name);
1581 if (fnum1 == -1) {
1582 printf("X");
1583 } else if (fnum2 == -1) {
1584 printf("-");
1585 } else {
1586 if (cli_read(&cli2, fnum2, (void *)&x, 0, 1) == 1) {
1587 printf("R");
1589 if (cli_write(&cli2, fnum2, 0, (void *)&x, 0, 1) == 1) {
1590 printf("W");
1594 printf("\n");
1595 cli_close(&cli1, fnum1);
1596 cli_close(&cli2, fnum2);
1599 cli_unlink(&cli1, fnames[f]);
1602 if (!close_connection(&cli1)) {
1603 correct = False;
1605 if (!close_connection(&cli2)) {
1606 correct = False;
1609 printf("finshed denytest1\n");
1610 return correct;
1615 this produces a matrix of deny mode behaviour for two opens on the
1616 same connection
1618 static BOOL run_denytest2(int dummy)
1620 static struct cli_state cli1;
1621 int fnum1, fnum2;
1622 int f, d1, d2, o1, o2, x=0;
1623 char *fnames[] = {"\\denytest2.exe", "\\denytest2.dat", NULL};
1624 struct {
1625 int v;
1626 char *name;
1627 } deny_modes[] = {
1628 {DENY_DOS, "DENY_DOS"},
1629 {DENY_ALL, "DENY_ALL"},
1630 {DENY_WRITE, "DENY_WRITE"},
1631 {DENY_READ, "DENY_READ"},
1632 {DENY_NONE, "DENY_NONE"},
1633 {DENY_FCB, "DENY_FCB"},
1634 {-1, NULL}};
1635 struct {
1636 int v;
1637 char *name;
1638 } open_modes[] = {
1639 {O_RDWR, "O_RDWR"},
1640 {O_RDONLY, "O_RDONLY"},
1641 {O_WRONLY, "O_WRONLY"},
1642 {-1, NULL}};
1643 BOOL correct = True;
1645 if (!open_connection(&cli1)) {
1646 return False;
1648 cli_sockopt(&cli1, sockops);
1650 printf("starting denytest2\n");
1652 for (f=0;fnames[f];f++) {
1653 cli_unlink(&cli1, fnames[f]);
1655 fnum1 = cli_open(&cli1, fnames[f], O_RDWR|O_CREAT, DENY_NONE);
1656 cli_write(&cli1, fnum1, 0, fnames[f], 0, strlen(fnames[f]));
1657 cli_close(&cli1, fnum1);
1659 for (d1=0;deny_modes[d1].name;d1++)
1660 for (o1=0;open_modes[o1].name;o1++)
1661 for (d2=0;deny_modes[d2].name;d2++)
1662 for (o2=0;open_modes[o2].name;o2++) {
1663 fnum1 = cli_open(&cli1, fnames[f],
1664 open_modes[o1].v,
1665 deny_modes[d1].v);
1666 fnum2 = cli_open(&cli1, fnames[f],
1667 open_modes[o2].v,
1668 deny_modes[d2].v);
1670 printf("%s %8s %10s %8s %10s ",
1671 fnames[f],
1672 open_modes[o1].name,
1673 deny_modes[d1].name,
1674 open_modes[o2].name,
1675 deny_modes[d2].name);
1677 if (fnum1 == -1) {
1678 printf("X");
1679 } else if (fnum2 == -1) {
1680 printf("-");
1681 } else {
1682 if (cli_read(&cli1, fnum2, (void *)&x, 0, 1) == 1) {
1683 printf("R");
1685 if (cli_write(&cli1, fnum2, 0, (void *)&x, 0, 1) == 1) {
1686 printf("W");
1690 printf("\n");
1691 cli_close(&cli1, fnum1);
1692 cli_close(&cli1, fnum2);
1695 cli_unlink(&cli1, fnames[f]);
1698 if (!close_connection(&cli1)) {
1699 correct = False;
1702 printf("finshed denytest2\n");
1703 return correct;
1707 test whether fnums and tids open on one VC are available on another (a major
1708 security hole)
1710 static BOOL run_fdpasstest(int dummy)
1712 static struct cli_state cli1, cli2, cli3;
1713 char *fname = "\\fdpass.tst";
1714 int fnum1;
1715 pstring buf;
1717 if (!open_connection(&cli1) || !open_connection(&cli2)) {
1718 return False;
1720 cli_sockopt(&cli1, sockops);
1721 cli_sockopt(&cli2, sockops);
1723 printf("starting fdpasstest\n");
1725 cli_unlink(&cli1, fname);
1727 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1728 if (fnum1 == -1) {
1729 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
1730 return False;
1733 if (cli_write(&cli1, fnum1, 0, "hello world\n", 0, 13) != 13) {
1734 printf("write failed (%s)\n", cli_errstr(&cli1));
1735 return False;
1738 cli3 = cli2;
1739 cli3.vuid = cli1.vuid;
1740 cli3.cnum = cli1.cnum;
1741 cli3.pid = cli1.pid;
1743 if (cli_read(&cli3, fnum1, buf, 0, 13) == 13) {
1744 printf("read succeeded! nasty security hole [%s]\n",
1745 buf);
1746 return False;
1749 cli_close(&cli1, fnum1);
1750 cli_unlink(&cli1, fname);
1752 close_connection(&cli1);
1753 close_connection(&cli2);
1755 printf("finished fdpasstest\n");
1756 return True;
1759 /*test multiple users over a single tcp connection*/
1760 /*test multiple users over a single tcp connection ~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1761 /*test multiple users over a single tcp connection*/
1764 typedef struct subtaboid {
1766 struct subtaboid *next;
1768 BOOL status;
1769 fstring name;
1770 fstring op_error;
1771 fstring sys_error;
1773 } SUBTABOID;
1775 typedef struct taboid {
1777 int owner, share, as_user;
1779 void *arg;
1781 SUBTABOID *subtaboids[2];
1783 } TABOID;
1785 static void init_TABOID(TABOID *t, int owner, int share, int as_user)
1787 memset( t, '\0', sizeof(*t));
1788 t->owner = owner;
1789 t->share = share;
1790 t->as_user = as_user;
1793 static BOOL run_vusertest_op_null(TABOID *t)
1795 return True;
1798 static BOOL run_vusertest_report_full(
1799 const char *operation,
1800 const char *sub_operation,
1801 BOOL failure,
1802 BOOL report,
1803 fstring *buf,
1804 TABOID *t)
1807 (*buf)[0] = '\0';
1809 snprintf(*buf,
1810 sizeof(*buf),
1811 "%8s[%s]:%10s file %10s user %10s(%5d). share %10s tid %5d owner %10s(%5d). fnum %5d was %5d (%s).",
1812 operation,
1813 failure?"FAILURE":"SUCCESS",
1814 sub_operation,
1815 vusers[t->owner].fname,
1816 vusers[t->as_user].username,
1817 /*vusers[t->as_user].vuid,*/
1818 vusers[t->as_user].cli.vuid,
1819 shares[t->share],
1820 /*vusers[t->owner].per_tid[t->share].tid,*/
1821 vusers[t->as_user].cli.cnum,
1822 vusers[t->owner].username,
1823 /*vusers[t->owner].vuid,*/
1824 vusers[t->owner].cli.vuid,
1825 vusers[t->as_user].per_tid[t->share].fnum[t->owner],
1826 vusers[t->as_user].per_tid[t->share].backup_fnum[t->owner],
1827 failure?cli_errstr(&vusers[t->as_user].cli):""
1830 if(report)
1831 printf("%s\n", *buf);
1833 return True;
1836 static BOOL run_vusertest_report(
1837 const char *operation,
1838 const char *sub_operation,
1839 BOOL failure,
1840 TABOID *t)
1843 fstring buf;
1845 return run_vusertest_report_full(operation, sub_operation, failure, True, &buf, t);
1848 static BOOL run_vusertest_report_failure(
1849 const char *operation,
1850 const char *sub_operation,
1851 TABOID *t)
1854 fstring buf;
1856 return run_vusertest_report_full(operation, sub_operation, True, True, &buf, t);
1859 static BOOL run_vusertest_report_success(
1860 const char *operation,
1861 const char *sub_operation,
1862 TABOID *t)
1865 fstring buf;
1867 return run_vusertest_report_full(operation, sub_operation, False, True, &buf, t);
1870 static BOOL run_vusertest_op_init(TABOID *t)
1873 int i, j;
1875 vusers[t->owner].fname[0] = '\0';
1877 vusers[t->owner].vuid = 0;
1878 vusers[t->owner].vuid_valid = False;
1879 vusers[t->owner].files_valid = False;
1881 for(i = 0; i < sizeof(vusers[t->owner].per_tid)/sizeof(vusers[t->owner].per_tid[0]); i++) {
1883 vusers[t->owner].per_tid[i].tid = 0;
1884 vusers[t->owner].per_tid[i].tid_valid = False;
1886 for(j = 0; j < sizeof(vusers[t->owner].per_tid[i].fnum)/sizeof(vusers[t->owner].per_tid[i].fnum[0]); j++) {
1888 vusers[t->owner].per_tid[i].fnum[j] = vusers[t->owner].per_tid[i].backup_fnum[j] = -1;
1892 return True;
1895 static BOOL run_vusertest_op_create(TABOID *t)
1898 BOOL should_work = (vusers[t->owner].per_tid[t->share].tid_valid && vusers[t->as_user].vuid_valid);
1900 snprintf(vusers[t->owner].fname, sizeof(vusers[t->owner].fname), "muserconn_%d", t->owner);
1902 vusers[t->as_user].cli.cnum = vusers[t->owner].per_tid[t->share].tid;
1904 if(!cli_unlink(&vusers[t->as_user].cli, vusers[t->owner].fname)) {
1906 run_vusertest_report_failure("CREATE", "unlink", t);
1908 return should_work?False:True;
1911 vusers[t->as_user].per_tid[t->share].fnum[t->owner] =
1912 cli_open(&vusers[t->as_user].cli, vusers[t->owner].fname, O_RDWR|O_CREAT, DENY_NONE);
1914 if (vusers[t->as_user].per_tid[t->share].fnum[t->owner] == -1) {
1916 run_vusertest_report_failure("CREATE", "create", t);
1918 return should_work?False:True;
1921 run_vusertest_report_success("CREATE", "created", t);
1923 vusers[t->as_user].files_valid = True; /*not true for all!*/
1925 return should_work?True:False;
1928 static BOOL run_vusertest_op_write(TABOID *t)
1931 BOOL should_work = (
1932 vusers[t->owner].per_tid[t->share].tid_valid &&
1933 vusers[t->as_user].vuid_valid &&
1934 vusers[t->as_user].files_valid
1937 fstring msg;
1938 int msglen;
1940 vusers[t->as_user].cli.cnum = vusers[t->owner].per_tid[t->share].tid;
1942 run_vusertest_report_full("WRITE", "write 2", False, False, &msg, t);
1944 msglen = strlen(msg)+1;
1946 if (cli_write(&vusers[t->as_user].cli,
1947 vusers[t->as_user].per_tid[t->share].fnum[t->owner], 0, (char *)&msglen, 0, sizeof(msglen)) != sizeof(msglen)) {
1949 run_vusertest_report_failure("WRITE", "write 1", t);
1951 return should_work?False:True;
1954 if (cli_write(&vusers[t->as_user].cli,
1955 vusers[t->as_user].per_tid[t->share].fnum[t->owner], 0, msg, sizeof(msglen), msglen) != msglen) {
1957 run_vusertest_report_failure("WRITE", "write 2", t);
1959 return should_work?False:True;
1962 run_vusertest_report_success("WRITE", "write", t);
1964 return should_work?True:False;
1967 static BOOL run_vusertest_op_create_and_write(TABOID *t)
1970 BOOL ret = True;
1972 if(!run_vusertest_op_create(t)) {
1974 ret = False;
1977 if(!run_vusertest_op_write(t)) {
1979 ret = False;
1982 return ret;
1985 static BOOL run_vusertest_op_openr(TABOID *t)
1988 BOOL should_work = (vusers[t->owner].per_tid[t->share].tid_valid && vusers[t->as_user].vuid_valid);
1990 vusers[t->as_user].cli.cnum = vusers[t->owner].per_tid[t->share].tid;
1992 vusers[t->as_user].per_tid[t->share].fnum[t->owner] =
1993 cli_open(&vusers[t->as_user].cli, vusers[t->owner].fname, O_RDONLY, DENY_NONE);
1995 if (vusers[t->as_user].per_tid[t->share].fnum[t->owner] == -1) {
1997 run_vusertest_report_failure("OPENR", "open", t);
1999 return should_work?False:True;
2002 run_vusertest_report_success("OPENR", "open", t);
2004 vusers[t->as_user].files_valid = True; /*not true for all!*/
2006 return should_work?True:False;
2009 static BOOL run_vusertest_op_read(TABOID *t)
2012 fstring msg;
2013 int msglen = 0;
2015 BOOL should_work = (
2016 vusers[t->owner].per_tid[t->share].tid_valid &&
2017 vusers[t->as_user].vuid_valid &&
2018 vusers[t->as_user].files_valid &&
2019 vusers[t->as_user].per_tid[t->share].fnum[t->owner] != -1
2022 vusers[t->as_user].cli.cnum = vusers[t->owner].per_tid[t->share].tid;
2024 if (cli_read(&vusers[t->as_user].cli,
2025 vusers[t->as_user].per_tid[t->share].fnum[t->owner], (char *)&msglen, 0, sizeof(msglen)) != sizeof(msglen)) {
2027 run_vusertest_report_failure("READ", "read 1", t);
2029 return should_work?False:True;
2032 if (cli_read(&vusers[t->as_user].cli,
2033 vusers[t->as_user].per_tid[t->share].fnum[t->owner], msg, sizeof(msglen), msglen) != msglen) {
2035 run_vusertest_report_failure("READ", "read 2", t);
2037 return should_work?False:True;
2040 run_vusertest_report_success("READ", "read", t);
2042 return should_work?True:False;
2045 static BOOL run_vusertest_op_openr_and_read(TABOID *t)
2048 BOOL ret = True;
2050 if(!run_vusertest_op_openr(t)) {
2052 ret = False;
2055 if(!run_vusertest_op_read(t)) {
2057 ret = False;
2060 return ret;
2063 static BOOL run_vusertest_op_backup_open_fids(TABOID *t)
2066 memcpy(vusers[t->as_user].per_tid[t->share].backup_fnum,
2067 vusers[t->as_user].per_tid[t->share].fnum,
2068 sizeof(vusers[t->as_user].per_tid[t->share].fnum));
2070 return True;
2073 static BOOL run_vusertest_op_close(TABOID *t)
2076 BOOL should_work = (
2078 vusers[t->owner].per_tid[t->share].tid_valid &&
2079 vusers[t->as_user].vuid_valid &&
2080 vusers[t->as_user].files_valid
2084 vusers[t->as_user].per_tid[t->share].fnum[t->owner] == -1 &&
2085 vusers[t->as_user].per_tid[t->share].backup_fnum[t->owner] == -1
2089 BOOL ret = should_work?True:False;
2091 vusers[t->as_user].cli.cnum = vusers[t->owner].per_tid[t->share].tid;
2093 if(vusers[t->as_user].per_tid[t->share].fnum[t->owner] != -1) {
2095 if(!cli_close(&vusers[t->as_user].cli, vusers[t->as_user].per_tid[t->share].fnum[t->owner])) {
2097 run_vusertest_report_failure("CLOSE", "close", t);
2099 ret = should_work?False:True;
2100 } else {
2102 run_vusertest_report_success("CLOSE", "close", t);
2105 vusers[t->as_user].per_tid[t->share].fnum[t->owner] = -1;
2108 if(vusers[t->as_user].per_tid[t->share].backup_fnum[t->owner] != -1 &&
2109 vusers[t->as_user].per_tid[t->share].backup_fnum[t->owner] != 0) {
2111 if(!cli_close(&vusers[t->as_user].cli, vusers[t->as_user].per_tid[t->share].backup_fnum[t->owner])) {
2113 run_vusertest_report_failure("CLOSE", "close backup", t);
2115 ret = should_work?False:True;
2117 } else {
2119 run_vusertest_report_success("CLOSE", "close backup", t);
2122 vusers[t->as_user].per_tid[t->share].backup_fnum[t->owner] = -1;
2125 return ret;
2128 static BOOL run_vusertest_op_tcon(TABOID *t)
2131 BOOL should_work = (vusers[t->as_user].vuid_valid);
2133 vusers[t->owner].per_tid[t->share].tid_valid = False;
2135 if (!cli_send_tconX(&vusers[t->as_user].cli,
2136 shares[t->share],
2137 "?????",
2138 vusers[t->as_user].password,
2139 strlen(vusers[t->as_user].password)+1)) {
2141 run_vusertest_report_failure("TCON", "tcon", t);
2143 return should_work?False:True;
2146 vusers[t->owner].per_tid[t->share].tid_valid = True;
2147 vusers[t->owner].per_tid[t->share].tid = vusers[t->as_user].cli.cnum;
2149 run_vusertest_report_success("TCON", "tcon", t);
2151 return should_work?True:False;
2154 static BOOL run_vusertest_op_tdis(TABOID *t)
2157 BOOL should_work = (vusers[t->owner].per_tid[t->share].tid_valid && vusers[t->as_user].vuid_valid);
2159 #if 0
2160 if(!vusers[t->owner].per_tid[t->share].tid_valid) {
2162 return True;
2164 #endif
2166 vusers[t->as_user].cli.cnum = vusers[t->owner].per_tid[t->share].tid;
2168 if(!cli_tdis(&vusers[t->as_user].cli)) {
2170 run_vusertest_report_failure("TDIS", "tdis", t);
2172 return should_work?False:True;
2175 run_vusertest_report_success("TDIS", "tdis", t);
2177 vusers[t->owner].per_tid[t->share].tid_valid = False;
2179 return should_work?True:False;
2182 static BOOL run_vusertest_op_ulogon(TABOID *t)
2185 vusers[t->owner].cli = *seed;
2187 vusers[t->owner].vuid_valid = False;
2189 if (!cli_session_setup(&vusers[t->owner].cli,
2190 vusers[t->owner].username,
2191 vusers[t->owner].password,
2192 strlen(vusers[t->owner].password),
2193 vusers[t->owner].password,
2194 strlen(vusers[t->owner].password),
2195 workgroup)) {
2198 run_vusertest_report_failure("ULOGON", "logon", t);
2200 return False;
2203 run_vusertest_report_success("ULOGON", "logon", t);
2205 vusers[t->owner].vuid_valid = True;
2206 vusers[t->owner].vuid = vusers[t->owner].cli.vuid;
2208 return True;
2211 static BOOL run_vusertest_op_ulogoff(TABOID *t)
2214 BOOL should_work = (vusers[t->owner].vuid_valid);
2216 #if 0
2217 if(!vusers[t->owner].vuid_valid) {
2219 return True;
2221 #endif
2223 if(!cli_ulogoff(&vusers[t->owner].cli)) {
2225 run_vusertest_report_failure("ULOGOFF", "logoff", t);
2227 return should_work?False:True;
2230 run_vusertest_report_success("ULOGOFF", "logoff", t);
2232 vusers[t->owner].vuid_valid = False;
2233 vusers[t->owner].files_valid = False;
2235 return should_work?True:False;
2238 /***********************************************************/
2239 /***********************************************************/
2241 static BOOL run_vusertest_owner_op(BOOL (*op)(TABOID *t))
2244 BOOL ret = True;
2246 int owner = 0;
2248 for(; owner < nusers; owner++) {
2250 TABOID t;
2251 init_TABOID(&t, owner, 0, owner);
2253 if(!op(&t)) {
2255 ret = False;
2256 printf("^^^^^^^^^^^^^^^^\n");
2260 return ret;
2263 static BOOL run_vusertest_owner_share_op(BOOL (*op)(TABOID *t))
2266 BOOL ret = True;
2268 int owner = 0;
2270 for(; owner < nusers; owner++) {
2272 int share = 0;
2274 for(; share < nshares; share++) {
2276 TABOID t;
2277 init_TABOID( &t, owner, share, owner);
2279 if(!op(&t)) {
2281 ret = False;
2282 printf("^^^^^^^^^^^^^^^^\n");
2287 return ret;
2290 static BOOL run_vusertest_owner_share_preop_user_op(
2291 BOOL (*preop)(TABOID *t),
2292 BOOL (*op)(TABOID *t),
2293 BOOL (*postop)(TABOID *t)
2297 BOOL ret = True;
2299 int owner = 0;
2301 for(; owner < nusers; owner++) {
2303 int share = 0;
2305 for(; share < nshares; share++) {
2307 TABOID t;
2308 init_TABOID( &t, owner, share, owner);
2310 if(!preop(&t)) {
2312 ret = False;
2313 printf("^^^^^^^^^^^^^^^^\n");
2316 for(t.as_user = 0; t.as_user < nusers; t.as_user++) {
2318 if(!op(&t)) {
2321 ret = False;
2322 printf("^^^^^^^^^^^^^^^^\n");
2326 t.as_user = owner;
2328 if(!postop(&t)) {
2330 ret = False;
2331 printf("^^^^^^^^^^^^^^^^\n");
2336 return ret;
2339 static BOOL run_vusertest_owner_share_user_preop_op(
2340 BOOL (*preop)(TABOID *t),
2341 BOOL (*op)(TABOID *t),
2342 BOOL (*postop)(TABOID *t)
2346 BOOL ret = True;
2348 int owner = 0;
2350 for(; owner < nusers; owner++) {
2352 int share = 0;
2354 for(; share < nshares; share++) {
2356 int as_user = 0;
2358 for(; as_user < nusers; as_user++) {
2360 TABOID t;
2361 init_TABOID( &t, owner, share, owner);
2363 if(!preop(&t)) {
2365 ret = False;
2367 printf("^^^^^^^^^^^^^^^^\n");
2370 t.as_user = as_user;
2372 if(!op(&t)) {
2375 ret = False;
2377 printf("^^^^^^^^^^^^^^^^\n");
2380 t.as_user = owner;
2382 if(!postop(&t)) {
2385 ret = False;
2387 printf("^^^^^^^^^^^^^^^^\n");
2393 return ret;
2396 /*user applies op*/
2398 #define VU_INIT (run_vusertest_owner_op(run_vusertest_op_init))
2400 #define VU_ULOGON (run_vusertest_owner_op(run_vusertest_op_ulogon))
2401 #define VU_ULOGOFF (run_vusertest_owner_op(run_vusertest_op_ulogoff))
2403 /*each user applies op to each of their shares*/
2405 #define VU_TCON (run_vusertest_owner_share_op(run_vusertest_op_tcon))
2406 #define VU_TDIS (run_vusertest_owner_share_op(run_vusertest_op_tdis))
2408 #define VU_CREATE_AND_WRITE (run_vusertest_owner_share_op(run_vusertest_op_create_and_write))
2409 #define VU_OPEN_AND_READ (run_vusertest_owner_share_op(run_vusertest_op_openr_and_read))
2410 #define VU_READ (run_vusertest_owner_share_op(run_vusertest_op_read))
2411 #define VU_FCLOSE (run_vusertest_owner_share_op(run_vusertest_op_close))
2412 #define VU_BACKUP_FIDS (run_vusertest_owner_share_op(run_vusertest_op_backup_open_fids))
2414 /*for u1 for u2 apply op as u2 on u1's tid*/
2416 #define VU_CROSS_READ (run_vusertest_owner_share_preop_user_op(run_vusertest_op_null,\
2417 run_vusertest_op_read,\
2418 run_vusertest_op_null))
2419 #define VU_CROSS_OPEN_AND_READ (run_vusertest_owner_share_preop_user_op(run_vusertest_op_null,\
2420 run_vusertest_op_openr_and_read,\
2421 run_vusertest_op_null))
2422 #define VU_CROSS_FCLOSE (run_vusertest_owner_share_preop_user_op(run_vusertest_op_null,\
2423 run_vusertest_op_close,\
2424 run_vusertest_op_null))
2426 #define VU_TCON_TDIS_OPEN_AND_READ (run_vusertest_owner_share_user_preop_op(run_vusertest_op_tcon,\
2427 run_vusertest_op_tdis,\
2428 run_vusertest_op_openr_and_read))
2433 Check relationship between:
2435 files open
2437 session logoff (Samba closes all files for vuid)
2439 tree disconnection (Samba set conn->used to False then calls close_cnum(conn, vuid), this flushes dir cache, closes files on the conn, frees the conn structure)
2441 1. can a user access a tid connected by another
2443 for u1 {
2444 for u2 {
2445 u2 opens file on u1's tid
2449 2. can one user disconnect a tid connected by another
2451 for u1 {
2452 for u2 {
2453 connect u1's tid as u1
2454 disconnect u1's tid as u2;
2455 open and read files as u1
2459 2a. does a disconnect by another invalidate the tid for the original connector
2461 3. does a disconnect invalidate a tid with no files open on it
2463 close files
2464 for u1 {
2465 disconnect u1's tid
2466 open and read files on u1's tid
2469 4. does a disconnect invalidate a tid with files open on it
2471 open files
2472 for u1 {
2473 disconnect u1's tid
2474 open and read files on u1's tid as u1
2477 5. does a disconnect invalidate files open on a tid.
2479 open files
2480 for u1 {
2481 disconnect u1's tid
2482 read files on u1's tid as u1
2485 6. can a user session exist with no tid and no open files
2487 close files
2488 for u1 {
2490 disconnect u1's tid
2493 for u1 {
2495 reconnect u1's tid
2499 7. does a logoff invalidate a tid with no files open on it
2501 close files
2502 for u1 {
2503 logoff u1
2504 open and read files on u1's tid
2507 close files
2508 for u1 {
2509 logon u1
2510 open and read files on u1's tid
2513 8. does a logoff invalidate a tid with files open on it
2515 open files
2516 for u1 {
2517 logoff u1
2518 open and read files on u1's tid
2521 for u1 {
2522 logon u1
2523 open and read files on u1's tid
2526 9. does a logoff invalidate a fid.
2528 open files
2529 for u1 {
2530 logoff u1
2531 read files on u1's tid
2534 for u1 {
2535 logon u1
2536 read files on u1's tid
2540 10. does a logoff invalidate a vuid.
2542 see 8
2544 11. can a connection survive close files, close tids, logoff users
2546 close files
2547 for u1 {
2548 disconnect u1's tids
2549 logoff u1
2552 for u1 {
2553 logon u1
2554 reconnect u1's tids
2555 open and read
2562 static BOOL run_vusertest(int dummy)
2564 BOOL ret = True;
2566 int testcnt = 0;
2568 seed = &vusers[0].cli;
2570 ZERO_STRUCTP(seed);
2572 printf("\nopen nbt connection\n");
2574 if (!open_nbt_connection(seed)) {
2576 return False;
2579 cli_sockopt(seed, sockops);
2581 printf("\nnegotiate protocol\n");
2583 /*the CIFS spec says this should be done only once on a VC and W2K doesn't like it more than once. Samba doesn't mind*/
2585 if (!cli_negprot(seed)) {
2586 printf("%s rejected the negprot (%s)\n",host, cli_errstr(seed));
2587 cli_shutdown(seed);
2588 return False;
2591 printf("\nnegotiate protocol again.\n");
2593 if (!cli_negprot(seed)) {
2595 printf("%s rejected a second negprot (%s)\n",host, cli_errstr(seed));
2597 printf("\nshutdown client\n");
2599 cli_shutdown(seed);
2601 ZERO_STRUCTP(seed);
2603 printf("\nopen new nbt session\n");
2605 if (!open_nbt_connection(seed)) {
2607 return False;
2610 cli_sockopt(seed, sockops);
2612 printf("\nre negotiate protocol\n");
2614 if (!cli_negprot(seed)) {
2615 printf("%s rejected the negprot (%s)\n",host, cli_errstr(seed));
2616 cli_shutdown(seed);
2617 return False;
2621 printf("starting vusertest with %d users and %d shares.\n", nusers, nshares);
2623 /***********************************************************/
2624 /***********************************************************/
2626 printf("\ninitialise\n\n");
2628 if(!VU_INIT) {
2630 printf("initialisation failed.\n");
2631 return False;
2634 printf("\nsetup sessions\n\n");
2636 if(!VU_ULOGON) {
2638 printf("setup sessions failed.\n");
2639 return False;
2642 printf("\nconnect to shares\n\n");
2644 if(!VU_TCON) {
2646 printf("connect to shares failed.\n");
2647 return False;
2650 /***********************************************************/
2651 /***********************************************************/
2655 char *test = "create and write files";
2656 BOOL tret = True;
2658 printf("\nTEST:%d %s\n\n", testcnt, test);
2660 testcnt++;
2662 if(!VU_CREATE_AND_WRITE) {
2664 printf("%s failed.\n", test);
2665 return False;
2668 if(!VU_FCLOSE) {
2670 tret = False;
2673 if(!tret) {
2675 printf("TEST FAILED.\n");
2676 ret = False;
2680 /***********************************************************/
2681 /***********************************************************/
2684 char *test = "can a user access a tid connected by another?";
2686 BOOL tret = True;
2688 printf("\nTEST:%d %s\n\n", testcnt, test);
2690 testcnt++;
2692 if(!VU_CROSS_OPEN_AND_READ) {
2694 tret = False;
2697 if(!VU_CROSS_FCLOSE) {
2699 tret = False;
2702 if(!tret) {
2704 printf("TEST FAILED.\n");
2705 ret = False;
2709 /***********************************************************/
2710 /***********************************************************/
2713 char *test = "can one user disconnect a tid connected by another.\n2a does disconnect by another invalidate tid for all?";
2715 BOOL tret = True;
2717 printf("\nTEST:%d %s\n\n", testcnt, test);
2719 testcnt++;
2721 if(!VU_TCON_TDIS_OPEN_AND_READ) {
2723 tret = False;
2726 if(!VU_CROSS_FCLOSE) {
2728 tret = False;
2731 if(!tret) {
2733 printf("TEST FAILED.\n");
2734 ret = False;
2738 /***********************************************************/
2739 /***********************************************************/
2743 char *test = "does a disconnect invalidate a tid with no files open on it?";
2745 BOOL tret = True;
2747 printf("\nTEST:%d %s\n\n", testcnt, test);
2749 testcnt++;
2751 if(!VU_FCLOSE) {
2753 tret = False;
2756 if(!VU_TDIS) {
2758 tret = False;
2761 if(!VU_OPEN_AND_READ) {
2763 tret = False;
2766 if(!VU_TCON) {
2768 tret = False;
2771 if(!tret) {
2773 printf("TEST FAILED.\n");
2774 ret = False;
2778 /***********************************************************/
2779 /***********************************************************/
2783 char *test = "does a disconnect invalidate a tid with files open on it?";
2785 BOOL tret = True;
2787 printf("\nTEST:%d %s\n\n", testcnt, test);
2789 testcnt++;
2791 if(!VU_FCLOSE) {
2793 tret = False;
2796 if(!VU_OPEN_AND_READ) {
2798 tret = False;
2801 if(!VU_TDIS) {
2803 tret = False;
2806 if(!VU_OPEN_AND_READ) {
2808 tret = False;
2811 if(!VU_TCON) {
2813 tret = False;
2816 if(!tret) {
2818 printf("TEST FAILED.\n");
2819 ret = False;
2823 /***********************************************************/
2824 /***********************************************************/
2828 char *test = "does a disconnect invalidate files open on a tid?";
2830 BOOL tret = True;
2832 printf("\nTEST:%d %s\n\n", testcnt, test);
2834 testcnt++;
2836 if(!VU_FCLOSE) {
2838 tret = False;
2841 if(!VU_OPEN_AND_READ) {
2843 tret = False;
2846 if(!VU_TDIS) {
2848 tret = False;
2851 if(!VU_READ) {
2853 tret = False;
2856 if(!VU_FCLOSE) {
2858 tret = False;
2861 if(!VU_TCON) {
2863 tret = False;
2866 if(!tret) {
2868 printf("TEST FAILED.\n");
2869 ret = False;
2873 /***********************************************************/
2874 /***********************************************************/
2878 char *test = "can a user session exist with no tid and no open files?";
2880 BOOL tret = True;
2882 printf("\nTEST:%d %s\n\n", testcnt, test);
2884 testcnt++;
2886 if(!VU_TDIS) {
2888 tret = False;
2891 if(!VU_TCON) {
2893 tret = False;
2896 if(!VU_OPEN_AND_READ) {
2898 tret = False;
2901 if(!tret) {
2903 printf("TEST FAILED.\n");
2904 ret = False;
2908 /***********************************************************/
2909 /***********************************************************/
2913 char *test = "does a logoff invalidate a tid with no files open on it?";
2915 BOOL tret = True;
2917 printf("\nTEST:%d %s\n\n", testcnt, test);
2919 testcnt++;
2921 if(!VU_FCLOSE) {
2923 tret = False;
2926 if(!VU_ULOGOFF) {
2928 tret = False;
2931 if(!VU_OPEN_AND_READ) {
2933 tret = False;
2936 if(!VU_FCLOSE) {
2938 tret = False;
2941 if(!VU_ULOGON) {
2943 tret = False;
2946 if(!VU_OPEN_AND_READ) {
2948 tret = False;
2951 if(!VU_FCLOSE) {
2953 tret = False;
2956 if(!VU_TDIS) {
2958 tret = False;
2961 if(!VU_TCON) {
2963 tret = False;
2966 if(!tret) {
2968 printf("TEST FAILED.\n");
2969 ret = False;
2973 /***********************************************************/
2974 /***********************************************************/
2977 char *test = "does a logoff invalidate a tid with files open on it?";
2979 BOOL tret = True;
2981 printf("\nTEST:%d %s\n\n", testcnt, test);
2983 testcnt++;
2985 if(!VU_OPEN_AND_READ) {
2987 tret = False;
2990 if(!VU_ULOGOFF) {
2992 tret = False;
2995 if(!VU_OPEN_AND_READ) {
2997 tret = False;
3000 if(!VU_ULOGON) {
3002 tret = False;
3005 if(!VU_OPEN_AND_READ) {
3007 tret = False;
3010 if(!VU_FCLOSE) {
3012 tret = False;
3015 if(!VU_TDIS) {
3017 tret = False;
3020 if(!VU_TCON) {
3022 tret = False;
3025 if(!tret) {
3027 printf("TEST FAILED.\n");
3028 ret = False;
3032 /***********************************************************/
3033 /***********************************************************/
3036 char *test = "does a logoff invalidate a fid?";
3037 BOOL tret = True;
3039 printf("\nTEST:%d %s\n\n", testcnt, test);
3041 testcnt++;
3043 if(!VU_OPEN_AND_READ) {
3045 tret = False;
3048 if(!VU_ULOGOFF) {
3050 tret = False;
3053 if(!VU_READ) {
3055 tret = False;
3058 if(!VU_ULOGON) {
3060 tret = False;
3063 if(!VU_READ) {
3065 tret = False;
3068 if(!VU_FCLOSE) {
3070 tret = False;
3073 if(!VU_TDIS) {
3075 tret = False;
3078 if(!VU_TCON) {
3080 tret = False;
3083 if(!tret) {
3085 printf("TEST FAILED.\n");
3086 ret = False;
3090 /***********************************************************/
3091 /***********************************************************/
3093 printf("\nTEST:%d does a logoff invalidate a vuid? see 8.\n\n", testcnt);
3095 testcnt++;
3097 /***********************************************************/
3098 /***********************************************************/
3101 char *test = "can a connection survive close files, disconnect tids, logoff users?";
3102 BOOL tret = True;
3104 printf("\nTEST:%d %s\n\n", testcnt, test);
3106 testcnt++;
3108 if(!VU_FCLOSE) {
3110 tret = False;
3113 if(!VU_TDIS) {
3115 tret = False;
3118 if(!VU_ULOGOFF) {
3120 tret = False;
3123 if(!VU_ULOGON) {
3125 tret = False;
3128 if(!VU_TCON) {
3130 tret = False;
3133 if(!VU_OPEN_AND_READ) {
3135 tret = False;
3138 if(!tret) {
3140 printf("TEST FAILED.\n");
3141 ret = False;
3145 /***********************************************************/
3146 /***********************************************************/
3149 char *test = "clean up.";
3150 BOOL tret = True;
3152 printf("\nTEST:%s\n\n", test);
3154 if(!VU_CROSS_FCLOSE) {
3156 tret = False;
3159 if(!VU_TDIS) {
3161 tret = False;
3164 if(!VU_ULOGOFF) {
3166 tret = False;
3169 if(!tret) {
3171 printf("TEST FAILED.\n");
3172 ret = False;
3176 cli_shutdown(seed);
3178 printf("finished vusertest.\n");
3179 return ret;
3183 This test checks that
3185 1) the server does not allow an unlink on a file that is open
3187 static BOOL run_unlinktest(int dummy)
3189 static struct cli_state cli;
3190 char *fname = "\\unlink.tst";
3191 int fnum;
3192 BOOL correct = True;
3194 if (!open_connection(&cli)) {
3195 return False;
3198 cli_sockopt(&cli, sockops);
3200 printf("starting unlink test\n");
3202 cli_unlink(&cli, fname);
3204 cli_setpid(&cli, 1);
3206 fnum = cli_open(&cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
3207 if (fnum == -1) {
3208 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
3209 return False;
3212 if (cli_unlink(&cli, fname)) {
3213 printf("error: server allowed unlink on an open file\n");
3214 correct = False;
3217 cli_close(&cli, fnum);
3218 cli_unlink(&cli, fname);
3220 if (!close_connection(&cli)) {
3221 correct = False;
3224 printf("unlink test finished\n");
3226 return correct;
3231 test how many open files this server supports on the one socket
3233 static BOOL run_maxfidtest(int dummy)
3235 static struct cli_state cli;
3236 char *template = "\\maxfid.%d.%d";
3237 fstring fname;
3238 int fnum;
3239 int retries=4;
3240 BOOL correct = True;
3242 cli = current_cli;
3244 if (retries <= 0) {
3245 printf("failed to connect\n");
3246 return False;
3249 cli_sockopt(&cli, sockops);
3251 fnum = 0;
3252 while (1) {
3253 slprintf(fname,sizeof(fname)-1,template, fnum,(int)getpid());
3254 if (cli_open(&cli, fname,
3255 O_RDWR|O_CREAT|O_TRUNC, DENY_NONE) ==
3256 -1) {
3257 printf("open of %s failed (%s)\n",
3258 fname, cli_errstr(&cli));
3259 printf("maximum fnum is %d\n", fnum);
3260 break;
3262 fnum++;
3263 if (fnum % 100 == 0) printf("%d\r", fnum);
3265 printf("%d\n", fnum);
3267 printf("cleaning up\n");
3268 while (fnum > 0) {
3269 fnum--;
3270 slprintf(fname,sizeof(fname)-1,template, fnum,(int)getpid());
3271 cli_close(&cli, fnum);
3272 if (!cli_unlink(&cli, fname)) {
3273 printf("unlink of %s failed (%s)\n",
3274 fname, cli_errstr(&cli));
3275 correct = False;
3279 printf("maxfid test finished\n");
3280 if (!close_connection(&cli)) {
3281 correct = False;
3283 return correct;
3286 /* generate a random buffer */
3287 static void rand_buf(char *buf, int len)
3289 while (len--) {
3290 *buf = (char)sys_random();
3291 buf++;
3295 /* send smb negprot commands, not reading the response */
3296 static BOOL run_negprot_nowait(int dummy)
3298 int i;
3299 static struct cli_state cli;
3300 BOOL correct = True;
3302 printf("starting negprot nowait test\n");
3304 if (!open_nbt_connection(&cli)) {
3305 return False;
3308 for (i=0;i<50000;i++) {
3309 cli_negprot_send(&cli);
3312 if (!close_connection(&cli)) {
3313 correct = False;
3316 printf("finished negprot nowait test\n");
3318 return correct;
3322 /* send random IPC commands */
3323 static BOOL run_randomipc(int dummy)
3325 char *rparam = NULL;
3326 char *rdata = NULL;
3327 int rdrcnt,rprcnt;
3328 pstring param;
3329 int api, param_len, i;
3330 static struct cli_state cli;
3331 BOOL correct = True;
3333 printf("starting random ipc test\n");
3335 if (!open_connection(&cli)) {
3336 return False;
3339 for (i=0;i<50000;i++) {
3340 api = sys_random() % 500;
3341 param_len = (sys_random() % 64);
3343 rand_buf(param, param_len);
3345 SSVAL(param,0,api);
3347 cli_api(&cli,
3348 param, param_len, 8,
3349 NULL, 0, BUFFER_SIZE,
3350 &rparam, &rprcnt,
3351 &rdata, &rdrcnt);
3354 if (!close_connection(&cli)) {
3355 correct = False;
3358 printf("finished random ipc test\n");
3360 return correct;
3365 static void browse_callback(const char *sname, uint32 stype,
3366 const char *comment, void *state)
3368 printf("\t%20.20s %08x %s\n", sname, stype, comment);
3374 This test checks the browse list code
3377 static BOOL run_browsetest(int dummy)
3379 static struct cli_state cli;
3380 BOOL correct = True;
3382 printf("starting browse test\n");
3384 if (!open_connection(&cli)) {
3385 return False;
3388 printf("domain list:\n");
3389 cli_NetServerEnum(&cli, cli.server_domain,
3390 SV_TYPE_DOMAIN_ENUM,
3391 browse_callback, NULL);
3393 printf("machine list:\n");
3394 cli_NetServerEnum(&cli, cli.server_domain,
3395 SV_TYPE_ALL,
3396 browse_callback, NULL);
3398 if (!close_connection(&cli)) {
3399 correct = False;
3402 printf("browse test finished\n");
3404 return correct;
3410 This checks how the getatr calls works
3412 static BOOL run_attrtest(int dummy)
3414 static struct cli_state cli;
3415 int fnum;
3416 time_t t, t2;
3417 char *fname = "\\attrib.tst";
3418 BOOL correct = True;
3420 printf("starting attrib test\n");
3422 if (!open_connection(&cli)) {
3423 return False;
3426 cli_unlink(&cli, fname);
3427 fnum = cli_open(&cli, fname,
3428 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
3429 cli_close(&cli, fnum);
3430 if (!cli_getatr(&cli, fname, NULL, NULL, &t)) {
3431 printf("getatr failed (%s)\n", cli_errstr(&cli));
3432 correct = False;
3435 if (abs(t - time(NULL)) > 2) {
3436 printf("ERROR: SMBgetatr bug. time is %s",
3437 ctime(&t));
3438 t = time(NULL);
3439 correct = True;
3442 t2 = t-60*60*24; /* 1 day ago */
3444 if (!cli_setatr(&cli, fname, 0, t2)) {
3445 printf("setatr failed (%s)\n", cli_errstr(&cli));
3446 correct = True;
3449 if (!cli_getatr(&cli, fname, NULL, NULL, &t)) {
3450 printf("getatr failed (%s)\n", cli_errstr(&cli));
3451 correct = True;
3454 if (t != t2) {
3455 printf("ERROR: getatr/setatr bug. times are\n%s",
3456 ctime(&t));
3457 printf("%s", ctime(&t2));
3458 correct = True;
3461 cli_unlink(&cli, fname);
3463 if (!close_connection(&cli)) {
3464 correct = False;
3467 printf("attrib test finished\n");
3469 return correct;
3474 This checks a couple of trans2 calls
3476 static BOOL run_trans2test(int dummy)
3478 static struct cli_state cli;
3479 int fnum;
3480 size_t size;
3481 time_t c_time, a_time, m_time, w_time, m_time2;
3482 char *fname = "\\trans2.tst";
3483 char *dname = "\\trans2";
3484 char *fname2 = "\\trans2\\trans2.tst";
3485 BOOL correct = True;
3487 printf("starting trans2 test\n");
3489 if (!open_connection(&cli)) {
3490 return False;
3493 cli_unlink(&cli, fname);
3494 fnum = cli_open(&cli, fname,
3495 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
3496 if (!cli_qfileinfo(&cli, fnum, NULL, &size, &c_time, &a_time, &m_time,
3497 NULL, NULL)) {
3498 printf("ERROR: qfileinfo failed (%s)\n", cli_errstr(&cli));
3499 correct = False;
3501 cli_close(&cli, fnum);
3503 sleep(2);
3505 cli_unlink(&cli, fname);
3506 fnum = cli_open(&cli, fname,
3507 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
3508 if (fnum == -1) {
3509 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
3510 return False;
3512 cli_close(&cli, fnum);
3514 if (!cli_qpathinfo(&cli, fname, &c_time, &a_time, &m_time, &size, NULL)) {
3515 printf("ERROR: qpathinfo failed (%s)\n", cli_errstr(&cli));
3516 correct = False;
3517 } else {
3518 if (c_time != m_time) {
3519 printf("create time=%s", ctime(&c_time));
3520 printf("modify time=%s", ctime(&m_time));
3521 printf("This system appears to have sticky create times\n");
3522 correct = False;
3524 if (a_time % (60*60) == 0) {
3525 printf("access time=%s", ctime(&a_time));
3526 printf("This system appears to set a midnight access time\n");
3527 correct = False;
3530 if (abs(m_time - time(NULL)) > 60*60*24*7) {
3531 printf("ERROR: totally incorrect times - maybe word reversed?\n");
3532 correct = False;
3537 cli_unlink(&cli, fname);
3538 fnum = cli_open(&cli, fname,
3539 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
3540 cli_close(&cli, fnum);
3541 if (!cli_qpathinfo2(&cli, fname, &c_time, &a_time, &m_time,
3542 &w_time, &size, NULL, NULL)) {
3543 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
3544 correct = False;
3545 } else {
3546 if (w_time < 60*60*24*2) {
3547 printf("write time=%s", ctime(&w_time));
3548 printf("This system appears to set a initial 0 write time\n");
3549 correct = False;
3553 cli_unlink(&cli, fname);
3556 /* check if the server updates the directory modification time
3557 when creating a new file */
3558 if (!cli_mkdir(&cli, dname)) {
3559 printf("ERROR: mkdir failed (%s)\n", cli_errstr(&cli));
3560 correct = False;
3562 sleep(3);
3563 if (!cli_qpathinfo2(&cli, "\\trans2\\", &c_time, &a_time, &m_time,
3564 &w_time, &size, NULL, NULL)) {
3565 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
3566 correct = False;
3569 fnum = cli_open(&cli, fname2,
3570 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
3571 cli_write(&cli, fnum, 0, (char *)&fnum, 0, sizeof(fnum));
3572 cli_close(&cli, fnum);
3573 if (!cli_qpathinfo2(&cli, "\\trans2\\", &c_time, &a_time, &m_time2,
3574 &w_time, &size, NULL, NULL)) {
3575 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
3576 correct = False;
3577 } else {
3578 if (m_time2 == m_time) {
3579 printf("This system does not update directory modification times\n");
3580 correct = False;
3583 cli_unlink(&cli, fname2);
3584 cli_rmdir(&cli, dname);
3586 if (!close_connection(&cli)) {
3587 correct = False;
3590 printf("trans2 test finished\n");
3592 return correct;
3596 This checks new W2K calls.
3599 static BOOL new_trans(struct cli_state *pcli, int fnum, int level)
3601 char buf[4096];
3602 BOOL correct = True;
3604 memset(buf, 0xff, sizeof(buf));
3606 if (!cli_qfileinfo_test(pcli, fnum, level, buf)) {
3607 printf("ERROR: qfileinfo (%d) failed (%s)\n", level, cli_errstr(pcli));
3608 correct = False;
3609 } else {
3610 printf("qfileinfo: level %d\n", level);
3611 dump_data(0, buf, 256);
3612 printf("\n");
3614 return correct;
3617 /****************************************************************************
3618 Set or clear the delete on close flag.
3619 ****************************************************************************/
3621 int cli_setfileinfo_test(struct cli_state *cli, int fnum, int level, char *data, int data_len)
3623 int param_len = 6;
3624 uint16 setup = TRANSACT2_SETFILEINFO;
3625 pstring param;
3626 char *rparam=NULL, *rdata=NULL;
3628 memset(param, 0, param_len);
3629 SSVAL(param,0,fnum);
3630 SSVAL(param,2,level);
3632 if (!cli_send_trans(cli, SMBtrans2,
3633 NULL, /* name */
3634 -1, 0, /* fid, flags */
3635 &setup, 1, 0, /* setup, length, max */
3636 param, param_len, 2, /* param, length, max */
3637 data, data_len, cli->max_xmit /* data, length, max */
3638 )) {
3639 return False;
3642 if (!cli_receive_trans(cli, SMBtrans2,
3643 &rparam, &param_len,
3644 &rdata, &data_len)) {
3645 return False;
3648 SAFE_FREE(rdata);
3649 SAFE_FREE(rparam);
3651 return True;
3654 static BOOL run_w2ktest(int dummy)
3656 static struct cli_state cli;
3657 int fnum;
3658 char *fname = "\\w2ktest\\w2k.tst";
3659 char *fname1 = "\\w2ktest\\w2k.dir";
3660 int level;
3661 char data;
3662 BOOL correct = True;
3664 printf("starting w2k test\n");
3666 if (!open_connection(&cli)) {
3667 return False;
3670 fnum = cli_open(&cli, fname,
3671 O_RDWR | O_CREAT , DENY_NONE);
3673 for (level = 1004; level < 1040; level++) {
3674 new_trans(&cli, fnum, level);
3677 cli_close(&cli, fnum);
3678 cli_unlink(&cli, fname);
3680 /* Check the strange 1013 setinfo call. */
3681 cli_mkdir(&cli, fname1);
3682 fnum = cli_nt_create_full( &cli, fname1, 0x60080, 0, 7,
3683 1, 0);
3685 data = 1;
3686 if (!cli_setfileinfo_test( &cli, fnum, 1013, &data, 1)) {
3687 printf("setfileinfo test 1 failed with %s\n", cli_errstr(&cli));
3689 data = 0;
3690 if (!cli_setfileinfo_test( &cli, fnum, 1013, &data, 1)) {
3691 printf("setfileinfo test 2 failed with %s\n", cli_errstr(&cli));
3694 cli_close(&cli, fnum);
3695 cli_rmdir(&cli, fname1);
3697 fnum = cli_open(&cli, fname, O_RDWR | O_CREAT , DENY_NONE);
3699 cli_write(&cli, fnum, 0, (char *)&data, 0, sizeof(data));
3700 cli_close(&cli, fnum);
3701 cli_ulogoff(&cli);
3703 fnum = cli_open(&cli, fname, O_RDWR , DENY_NONE);
3704 if (cli_read(&cli, fnum, &data, 0, 1) != 1) {
3705 printf("x test 2 failed with %s\n", cli_errstr(&cli));
3707 cli_close(&cli, fnum);
3708 cli_unlink(&cli, fname);
3710 if (!close_connection(&cli)) {
3711 correct = False;
3714 printf("w2k test finished\n");
3716 return correct;
3721 this is a harness for some oplock tests
3723 static BOOL run_oplock1(int dummy)
3725 static struct cli_state cli1;
3726 char *fname = "\\lockt1.lck";
3727 int fnum1;
3728 BOOL correct = True;
3730 printf("starting oplock test 1\n");
3732 if (!open_connection(&cli1)) {
3733 return False;
3736 cli_unlink(&cli1, fname);
3738 cli_sockopt(&cli1, sockops);
3740 cli1.use_oplocks = True;
3742 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
3743 if (fnum1 == -1) {
3744 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
3745 return False;
3748 cli1.use_oplocks = False;
3750 cli_unlink(&cli1, fname);
3751 cli_unlink(&cli1, fname);
3753 if (!cli_close(&cli1, fnum1)) {
3754 printf("close2 failed (%s)\n", cli_errstr(&cli1));
3755 return False;
3758 if (!cli_unlink(&cli1, fname)) {
3759 printf("unlink failed (%s)\n", cli_errstr(&cli1));
3760 return False;
3763 if (!close_connection(&cli1)) {
3764 correct = False;
3767 printf("finished oplock test 1\n");
3769 return correct;
3772 static BOOL run_oplock2(int dummy)
3774 static struct cli_state cli1, cli2;
3775 char *fname = "\\lockt2.lck";
3776 int fnum1, fnum2;
3777 int saved_use_oplocks = use_oplocks;
3778 char buf[4];
3779 BOOL correct = True;
3780 volatile BOOL *shared_correct;
3782 shared_correct = (volatile BOOL *)shm_setup(sizeof(BOOL));
3783 *shared_correct = True;
3785 use_level_II_oplocks = True;
3786 use_oplocks = True;
3788 printf("starting oplock test 2\n");
3790 if (!open_connection(&cli1)) {
3791 use_level_II_oplocks = False;
3792 use_oplocks = saved_use_oplocks;
3793 return False;
3796 cli1.use_oplocks = True;
3797 cli1.use_level_II_oplocks = True;
3799 if (!open_connection(&cli2)) {
3800 use_level_II_oplocks = False;
3801 use_oplocks = saved_use_oplocks;
3802 return False;
3805 cli2.use_oplocks = True;
3806 cli2.use_level_II_oplocks = True;
3808 cli_unlink(&cli1, fname);
3810 cli_sockopt(&cli1, sockops);
3811 cli_sockopt(&cli2, sockops);
3813 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
3814 if (fnum1 == -1) {
3815 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
3816 return False;
3819 /* Don't need the globals any more. */
3820 use_level_II_oplocks = False;
3821 use_oplocks = saved_use_oplocks;
3823 if (fork() == 0) {
3824 /* Child code */
3825 fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
3826 if (fnum2 == -1) {
3827 printf("second open of %s failed (%s)\n", fname, cli_errstr(&cli1));
3828 *shared_correct = False;
3829 exit(0);
3832 sleep(2);
3834 if (!cli_close(&cli2, fnum2)) {
3835 printf("close2 failed (%s)\n", cli_errstr(&cli1));
3836 *shared_correct = False;
3839 exit(0);
3842 sleep(2);
3844 /* Ensure cli1 processes the break. */
3846 if (cli_read(&cli1, fnum1, buf, 0, 4) != 4) {
3847 printf("read on fnum1 failed (%s)\n", cli_errstr(&cli1));
3848 correct = False;
3851 /* Should now be at level II. */
3852 /* Test if sending a write locks causes a break to none. */
3854 if (!cli_lock(&cli1, fnum1, 0, 4, 0, READ_LOCK)) {
3855 printf("lock failed (%s)\n", cli_errstr(&cli1));
3856 correct = False;
3859 cli_unlock(&cli1, fnum1, 0, 4);
3861 sleep(2);
3863 if (!cli_lock(&cli1, fnum1, 0, 4, 0, WRITE_LOCK)) {
3864 printf("lock failed (%s)\n", cli_errstr(&cli1));
3865 correct = False;
3868 cli_unlock(&cli1, fnum1, 0, 4);
3870 sleep(2);
3872 cli_read(&cli1, fnum1, buf, 0, 4);
3874 #if 0
3875 if (cli_write(&cli1, fnum1, 0, buf, 0, 4) != 4) {
3876 printf("write on fnum1 failed (%s)\n", cli_errstr(&cli1));
3877 correct = False;
3879 #endif
3881 if (!cli_close(&cli1, fnum1)) {
3882 printf("close1 failed (%s)\n", cli_errstr(&cli1));
3883 correct = False;
3886 sleep(4);
3888 if (!cli_unlink(&cli1, fname)) {
3889 printf("unlink failed (%s)\n", cli_errstr(&cli1));
3890 correct = False;
3893 if (!close_connection(&cli1)) {
3894 correct = False;
3897 if (!*shared_correct) {
3898 correct = False;
3901 printf("finished oplock test 2\n");
3903 return correct;
3908 Test delete on close semantics.
3910 static BOOL run_deletetest(int dummy)
3912 static struct cli_state cli1;
3913 static struct cli_state cli2;
3914 char *fname = "\\delete.file";
3915 int fnum1, fnum2;
3916 BOOL correct = True;
3918 printf("starting delete test\n");
3920 if (!open_connection(&cli1)) {
3921 return False;
3924 cli_sockopt(&cli1, sockops);
3926 /* Test 1 - this should *NOT* delete the file on close. */
3928 cli_setatr(&cli1, fname, 0, 0);
3929 cli_unlink(&cli1, fname);
3931 fnum1 = cli_nt_create_full(&cli1, fname, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
3932 FILE_SHARE_DELETE, FILE_OVERWRITE_IF, DELETE_ON_CLOSE_FLAG);
3934 if (fnum1 == -1) {
3935 printf("[1] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
3936 return False;
3939 if (!cli_close(&cli1, fnum1)) {
3940 printf("[1] close failed (%s)\n", cli_errstr(&cli1));
3941 return False;
3944 fnum1 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
3945 if (fnum1 == -1) {
3946 printf("[1] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
3947 return False;
3950 if (!cli_close(&cli1, fnum1)) {
3951 printf("[1] close failed (%s)\n", cli_errstr(&cli1));
3952 return False;
3955 printf("first delete on close test succeeded.\n");
3957 /* Test 2 - this should delete the file on close. */
3959 cli_setatr(&cli1, fname, 0, 0);
3960 cli_unlink(&cli1, fname);
3962 fnum1 = cli_nt_create_full(&cli1, fname, GENERIC_ALL_ACCESS,
3963 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0);
3965 if (fnum1 == -1) {
3966 printf("[2] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
3967 return False;
3970 if (!cli_nt_delete_on_close(&cli1, fnum1, True)) {
3971 printf("[2] setting delete_on_close failed (%s)\n", cli_errstr(&cli1));
3972 return False;
3975 if (!cli_close(&cli1, fnum1)) {
3976 printf("[2] close failed (%s)\n", cli_errstr(&cli1));
3977 return False;
3980 fnum1 = cli_open(&cli1, fname, O_RDONLY, DENY_NONE);
3981 if (fnum1 != -1) {
3982 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
3983 if (!cli_close(&cli1, fnum1)) {
3984 printf("[2] close failed (%s)\n", cli_errstr(&cli1));
3985 correct = False;
3987 cli_unlink(&cli1, fname);
3988 } else
3989 printf("second delete on close test succeeded.\n");
3992 /* Test 3 - ... */
3993 cli_setatr(&cli1, fname, 0, 0);
3994 cli_unlink(&cli1, fname);
3996 fnum1 = cli_nt_create_full(&cli1, fname, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
3997 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0);
3999 if (fnum1 == -1) {
4000 printf("[3] open - 1 of %s failed (%s)\n", fname, cli_errstr(&cli1));
4001 return False;
4004 /* This should fail with a sharing violation - open for delete is only compatible
4005 with SHARE_DELETE. */
4007 fnum2 = cli_nt_create_full(&cli1, fname, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4008 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0);
4010 if (fnum2 != -1) {
4011 printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
4012 return False;
4015 /* This should succeed. */
4017 fnum2 = cli_nt_create_full(&cli1, fname, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4018 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0);
4020 if (fnum2 == -1) {
4021 printf("[3] open - 2 of %s failed (%s)\n", fname, cli_errstr(&cli1));
4022 return False;
4025 if (!cli_nt_delete_on_close(&cli1, fnum1, True)) {
4026 printf("[3] setting delete_on_close failed (%s)\n", cli_errstr(&cli1));
4027 return False;
4030 if (!cli_close(&cli1, fnum1)) {
4031 printf("[3] close 1 failed (%s)\n", cli_errstr(&cli1));
4032 return False;
4035 if (!cli_close(&cli1, fnum2)) {
4036 printf("[3] close 2 failed (%s)\n", cli_errstr(&cli1));
4037 return False;
4040 /* This should fail - file should no longer be there. */
4042 fnum1 = cli_open(&cli1, fname, O_RDONLY, DENY_NONE);
4043 if (fnum1 != -1) {
4044 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
4045 if (!cli_close(&cli1, fnum1)) {
4046 printf("[3] close failed (%s)\n", cli_errstr(&cli1));
4048 cli_unlink(&cli1, fname);
4049 correct = False;
4050 } else
4051 printf("third delete on close test succeeded.\n");
4053 /* Test 4 ... */
4054 cli_setatr(&cli1, fname, 0, 0);
4055 cli_unlink(&cli1, fname);
4057 fnum1 = cli_nt_create_full(&cli1, fname, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4058 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0);
4060 if (fnum1 == -1) {
4061 printf("[4] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
4062 return False;
4065 /* This should succeed. */
4066 fnum2 = cli_nt_create_full(&cli1, fname, GENERIC_READ_ACCESS,
4067 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0);
4068 if (fnum2 == -1) {
4069 printf("[4] open - 2 of %s failed (%s)\n", fname, cli_errstr(&cli1));
4070 return False;
4073 if (!cli_close(&cli1, fnum2)) {
4074 printf("[4] close - 1 failed (%s)\n", cli_errstr(&cli1));
4075 return False;
4078 if (!cli_nt_delete_on_close(&cli1, fnum1, True)) {
4079 printf("[4] setting delete_on_close failed (%s)\n", cli_errstr(&cli1));
4080 return False;
4083 /* This should fail - no more opens once delete on close set. */
4084 fnum2 = cli_nt_create_full(&cli1, fname, GENERIC_READ_ACCESS,
4085 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0);
4086 if (fnum2 != -1) {
4087 printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
4088 return False;
4089 } else
4090 printf("fourth delete on close test succeeded.\n");
4092 if (!cli_close(&cli1, fnum1)) {
4093 printf("[4] close - 2 failed (%s)\n", cli_errstr(&cli1));
4094 return False;
4097 /* Test 5 ... */
4098 cli_setatr(&cli1, fname, 0, 0);
4099 cli_unlink(&cli1, fname);
4101 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT, DENY_NONE);
4102 if (fnum1 == -1) {
4103 printf("[5] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
4104 return False;
4107 /* This should fail - only allowed on NT opens with DELETE access. */
4109 if (cli_nt_delete_on_close(&cli1, fnum1, True)) {
4110 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
4111 return False;
4114 if (!cli_close(&cli1, fnum1)) {
4115 printf("[5] close - 2 failed (%s)\n", cli_errstr(&cli1));
4116 return False;
4119 printf("fifth delete on close test succeeded.\n");
4121 /* Test 6 ... */
4122 cli_setatr(&cli1, fname, 0, 0);
4123 cli_unlink(&cli1, fname);
4125 fnum1 = cli_nt_create_full(&cli1, fname, FILE_READ_DATA|FILE_WRITE_DATA,
4126 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4127 FILE_OVERWRITE_IF, 0);
4129 if (fnum1 == -1) {
4130 printf("[6] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
4131 return False;
4134 /* This should fail - only allowed on NT opens with DELETE access. */
4136 if (cli_nt_delete_on_close(&cli1, fnum1, True)) {
4137 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
4138 return False;
4141 if (!cli_close(&cli1, fnum1)) {
4142 printf("[6] close - 2 failed (%s)\n", cli_errstr(&cli1));
4143 return False;
4146 printf("sixth delete on close test succeeded.\n");
4148 /* Test 7 ... */
4149 cli_setatr(&cli1, fname, 0, 0);
4150 cli_unlink(&cli1, fname);
4152 fnum1 = cli_nt_create_full(&cli1, fname, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4153 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF, 0);
4155 if (fnum1 == -1) {
4156 printf("[7] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
4157 return False;
4160 if (!cli_nt_delete_on_close(&cli1, fnum1, True)) {
4161 printf("[7] setting delete_on_close on file failed !\n");
4162 return False;
4165 if (!cli_nt_delete_on_close(&cli1, fnum1, False)) {
4166 printf("[7] unsetting delete_on_close on file failed !\n");
4167 return False;
4170 if (!cli_close(&cli1, fnum1)) {
4171 printf("[7] close - 2 failed (%s)\n", cli_errstr(&cli1));
4172 return False;
4175 /* This next open should succeed - we reset the flag. */
4177 fnum1 = cli_open(&cli1, fname, O_RDONLY, DENY_NONE);
4178 if (fnum1 == -1) {
4179 printf("[5] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
4180 return False;
4183 if (!cli_close(&cli1, fnum1)) {
4184 printf("[7] close - 2 failed (%s)\n", cli_errstr(&cli1));
4185 return False;
4188 printf("seventh delete on close test succeeded.\n");
4190 /* Test 7 ... */
4191 cli_setatr(&cli1, fname, 0, 0);
4192 cli_unlink(&cli1, fname);
4194 if (!open_connection(&cli2)) {
4195 printf("[8] failed to open second connection.\n");
4196 return False;
4199 cli_sockopt(&cli1, sockops);
4201 fnum1 = cli_nt_create_full(&cli1, fname, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4202 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0);
4204 if (fnum1 == -1) {
4205 printf("[8] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
4206 return False;
4209 fnum2 = cli_nt_create_full(&cli2, fname, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4210 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0);
4212 if (fnum2 == -1) {
4213 printf("[8] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
4214 return False;
4217 if (!cli_nt_delete_on_close(&cli1, fnum1, True)) {
4218 printf("[8] setting delete_on_close on file failed !\n");
4219 return False;
4222 if (!cli_close(&cli1, fnum1)) {
4223 printf("[8] close - 1 failed (%s)\n", cli_errstr(&cli1));
4224 return False;
4227 if (!cli_close(&cli2, fnum2)) {
4228 printf("[8] close - 2 failed (%s)\n", cli_errstr(&cli2));
4229 return False;
4232 /* This should fail.. */
4233 fnum1 = cli_open(&cli1, fname, O_RDONLY, DENY_NONE);
4234 if (fnum1 != -1) {
4235 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
4236 if (!cli_close(&cli1, fnum1)) {
4237 printf("[8] close failed (%s)\n", cli_errstr(&cli1));
4239 cli_unlink(&cli1, fname);
4240 correct = False;
4241 } else
4242 printf("eighth delete on close test succeeded.\n");
4244 printf("finished delete test\n");
4246 cli_setatr(&cli1, fname, 0, 0);
4247 cli_unlink(&cli1, fname);
4249 if (!close_connection(&cli1)) {
4250 correct = False;
4252 if (!close_connection(&cli2)) {
4253 correct = False;
4255 return correct;
4259 Test open mode returns on read-only files.
4261 static BOOL run_opentest(int dummy)
4263 static struct cli_state cli1;
4264 char *fname = "\\readonly.file";
4265 int fnum1, fnum2;
4266 uint8 eclass;
4267 uint32 errnum;
4268 char buf[20];
4269 size_t fsize;
4270 BOOL correct = True;
4272 printf("starting open test\n");
4274 if (!open_connection(&cli1)) {
4275 return False;
4278 cli_setatr(&cli1, fname, 0, 0);
4279 cli_unlink(&cli1, fname);
4281 cli_sockopt(&cli1, sockops);
4283 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
4284 if (fnum1 == -1) {
4285 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
4286 return False;
4289 if (!cli_close(&cli1, fnum1)) {
4290 printf("close2 failed (%s)\n", cli_errstr(&cli1));
4291 return False;
4294 if (!cli_setatr(&cli1, fname, aRONLY, 0)) {
4295 printf("cli_setatr failed (%s)\n", cli_errstr(&cli1));
4296 return False;
4299 fnum1 = cli_open(&cli1, fname, O_RDONLY, DENY_WRITE);
4300 if (fnum1 == -1) {
4301 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
4302 return False;
4305 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
4306 fnum2 = cli_open(&cli1, fname, O_RDWR, DENY_ALL);
4308 cli_dos_error( &cli1, &eclass, &errnum);
4310 if (eclass != ERRDOS || errnum != ERRnoaccess) {
4311 printf("wrong error code (%x,%x) = %s\n", (unsigned int)eclass,
4312 (unsigned int)errnum, cli_errstr(&cli1) );
4313 correct = False;
4314 } else {
4315 printf("correct error code ERRDOS/ERRnoaccess returned\n");
4319 printf("finished open test 1\n");
4321 cli_close(&cli1, fnum1);
4323 /* Now try not readonly and ensure ERRbadshare is returned. */
4325 cli_setatr(&cli1, fname, 0, 0);
4327 fnum1 = cli_open(&cli1, fname, O_RDONLY, DENY_WRITE);
4328 if (fnum1 == -1) {
4329 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
4330 return False;
4333 /* This will fail - but the error should be ERRshare. */
4334 fnum2 = cli_open(&cli1, fname, O_RDWR, DENY_ALL);
4336 cli_dos_error( &cli1, &eclass, &errnum);
4338 if (eclass != ERRDOS || errnum != ERRbadshare) {
4339 printf("wrong error code (%x,%x) = %s\n", (unsigned int)eclass,
4340 (unsigned int)errnum, cli_errstr(&cli1) );
4341 correct = False;
4342 } else {
4343 printf("correct error code ERRDOS/ERRbadshare returned\n");
4346 if (!cli_close(&cli1, fnum1)) {
4347 printf("close2 failed (%s)\n", cli_errstr(&cli1));
4348 return False;
4351 cli_unlink(&cli1, fname);
4353 printf("finished open test 2\n");
4355 /* Test truncate open disposition on file opened for read. */
4357 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
4358 if (fnum1 == -1) {
4359 printf("(3) open (1) of %s failed (%s)\n", fname, cli_errstr(&cli1));
4360 return False;
4363 /* write 20 bytes. */
4365 memset(buf, '\0', 20);
4367 if (cli_write(&cli1, fnum1, 0, buf, 0, 20) != 20) {
4368 printf("write failed (%s)\n", cli_errstr(&cli1));
4369 correct = False;
4372 if (!cli_close(&cli1, fnum1)) {
4373 printf("(3) close1 failed (%s)\n", cli_errstr(&cli1));
4374 return False;
4377 /* Ensure size == 20. */
4378 if (!cli_getatr(&cli1, fname, NULL, &fsize, NULL)) {
4379 printf("(3) getatr failed (%s)\n", cli_errstr(&cli1));
4380 return False;
4383 if (fsize != 20) {
4384 printf("(3) file size != 20\n");
4385 return False;
4388 /* Now test if we can truncate a file opened for readonly. */
4390 fnum1 = cli_open(&cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE);
4391 if (fnum1 == -1) {
4392 printf("(3) open (2) of %s failed (%s)\n", fname, cli_errstr(&cli1));
4393 return False;
4396 if (!cli_close(&cli1, fnum1)) {
4397 printf("close2 failed (%s)\n", cli_errstr(&cli1));
4398 return False;
4401 /* Ensure size == 0. */
4402 if (!cli_getatr(&cli1, fname, NULL, &fsize, NULL)) {
4403 printf("(3) getatr failed (%s)\n", cli_errstr(&cli1));
4404 return False;
4407 if (fsize != 0) {
4408 printf("(3) file size != 0\n");
4409 return False;
4411 printf("finished open test 3\n");
4413 cli_unlink(&cli1, fname);
4416 printf("testing ctemp\n");
4418 char *tmp_path;
4419 fnum1 = cli_ctemp(&cli1, "\\", &tmp_path);
4420 if (fnum1 == -1) {
4421 printf("ctemp failed (%s)\n", cli_errstr(&cli1));
4422 return False;
4424 printf("ctemp gave path %s\n", tmp_path);
4425 cli_close(&cli1, fnum1);
4426 cli_unlink(&cli1, tmp_path);
4429 if (!close_connection(&cli1)) {
4430 correct = False;
4433 return correct;
4436 static void list_fn(file_info *finfo, const char *name, void *state)
4442 test directory listing speed
4444 static BOOL run_dirtest(int dummy)
4446 int i;
4447 static struct cli_state cli;
4448 int fnum;
4449 double t1;
4450 BOOL correct = True;
4452 printf("starting directory test\n");
4454 if (!open_connection(&cli)) {
4455 return False;
4458 cli_sockopt(&cli, sockops);
4460 srandom(0);
4461 for (i=0;i<numops;i++) {
4462 fstring fname;
4463 slprintf(fname, sizeof(fname), "%x", (int)random());
4464 fnum = cli_open(&cli, fname, O_RDWR|O_CREAT, DENY_NONE);
4465 if (fnum == -1) {
4466 fprintf(stderr,"Failed to open %s\n", fname);
4467 return False;
4469 cli_close(&cli, fnum);
4472 t1 = end_timer();
4474 printf("Matched %d\n", cli_list(&cli, "a*.*", 0, list_fn, NULL));
4475 printf("Matched %d\n", cli_list(&cli, "b*.*", 0, list_fn, NULL));
4476 printf("Matched %d\n", cli_list(&cli, "xyzabc", 0, list_fn, NULL));
4478 printf("dirtest core %g seconds\n", end_timer() - t1);
4480 srandom(0);
4481 for (i=0;i<numops;i++) {
4482 fstring fname;
4483 slprintf(fname, sizeof(fname), "%x", (int)random());
4484 cli_unlink(&cli, fname);
4487 if (!close_connection(&cli)) {
4488 correct = False;
4491 printf("finished dirtest\n");
4493 return correct;
4496 static double create_procs(BOOL (*fn)(int), BOOL *result)
4498 int i, status;
4499 volatile pid_t *child_status;
4500 volatile BOOL *child_status_out;
4501 int synccount;
4502 int tries = 8;
4504 synccount = 0;
4506 child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*nprocs);
4507 if (!child_status) {
4508 printf("Failed to setup shared memory\n");
4509 return -1;
4512 child_status_out = (volatile BOOL *)shm_setup(sizeof(BOOL)*nprocs);
4513 if (!child_status_out) {
4514 printf("Failed to setup result status shared memory\n");
4515 return -1;
4518 memset(child_status, 0, sizeof(pid_t)*nprocs);
4519 memset(child_status_out, True, sizeof(BOOL)*nprocs);
4521 start_timer();
4523 for (i=0;i<nprocs;i++) {
4524 procnum = i;
4525 if (fork() == 0) {
4526 pid_t mypid = getpid();
4527 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
4529 slprintf(myname,sizeof(myname),"CLIENT%d", i);
4531 while (1) {
4532 memset(&current_cli, 0, sizeof(current_cli));
4533 if (open_connection(&current_cli)) break;
4534 if (tries-- == 0) {
4535 printf("pid %d failed to start\n", (int)getpid());
4536 _exit(1);
4538 msleep(10);
4541 child_status[i] = getpid();
4543 while (child_status[i] && end_timer() < 5) msleep(2);
4545 child_status_out[i] = fn(i);
4546 _exit(0);
4550 do {
4551 synccount = 0;
4552 for (i=0;i<nprocs;i++) {
4553 if (child_status[i]) synccount++;
4555 if (synccount == nprocs) break;
4556 msleep(10);
4557 } while (end_timer() < 30);
4559 if (synccount != nprocs) {
4560 printf("FAILED TO START %d CLIENTS (started %d)\n", nprocs, synccount);
4561 *result = False;
4562 return end_timer();
4565 /* start the client load */
4566 start_timer();
4568 for (i=0;i<nprocs;i++) {
4569 child_status[i] = 0;
4572 printf("%d clients started\n", nprocs);
4574 for (i=0;i<nprocs;i++) {
4575 waitpid(0, &status, 0);
4576 printf("*");
4579 printf("\n");
4581 for (i=0;i<nprocs;i++) {
4582 if (!child_status_out[i]) {
4583 *result = False;
4586 return end_timer();
4590 #define FLAG_MULTIPROC (1<<0)
4591 #define FLAG_MULTIUSER (1<<1)
4592 #define FLAG_MULTISHARE (1<<2)
4593 #define FLAG_PROBE (1<<3)
4595 static struct {
4596 char *name;
4597 BOOL (*fn)(int);
4598 unsigned flags;
4599 } torture_ops[] = {
4600 {"FDPASS", run_fdpasstest, 0},
4601 {"LOCK1", run_locktest1, 0},
4602 {"LOCK2", run_locktest2, 0},
4603 {"LOCK3", run_locktest3, 0},
4604 {"LOCK4", run_locktest4, 0},
4605 {"LOCK5", run_locktest5, 0},
4606 {"UNLINK", run_unlinktest, 0},
4607 {"BROWSE", run_browsetest, 0},
4608 {"ATTR", run_attrtest, 0},
4609 {"TRANS2", run_trans2test, 0},
4610 {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
4611 {"TORTURE",run_torture, FLAG_MULTIPROC},
4612 {"RANDOMIPC", run_randomipc, 0},
4613 {"NEGNOWAIT", run_negprot_nowait, 0},
4614 {"NBW95", run_nbw95, 0},
4615 {"NBWNT", run_nbwnt, 0},
4616 {"OPLOCK1", run_oplock1, 0},
4617 {"OPLOCK2", run_oplock2, 0},
4618 {"DIR", run_dirtest, 0},
4619 {"DENY1", run_denytest1, 0},
4620 {"DENY2", run_denytest2, 0},
4621 {"TCON", run_tcon_test, 0},
4622 {"RW1", run_readwritetest, 0},
4623 {"RW2", run_readwritemulti, FLAG_MULTIPROC},
4624 {"RW3", run_readwritelarge, 0},
4625 {"OPEN", run_opentest, 0},
4626 {"DELETE", run_deletetest, 0},
4627 {"W2K", run_w2ktest, 0},
4628 {"VU", run_vusertest, FLAG_MULTIUSER | FLAG_MULTISHARE},
4629 {NULL, NULL, 0}};
4633 /****************************************************************************
4634 run a specified test or "ALL"
4635 ****************************************************************************/
4637 static BOOL get_test_flags(char *name, BOOL *flags) {
4639 int i;
4641 BOOL all = strequal(name,"ALL") == 0;
4643 for (i=0;torture_ops[i].name;i++) {
4645 if (all || strequal(name, torture_ops[i].name)) {
4647 *flags |= torture_ops[i].flags;
4649 if(!all) {
4651 break;
4656 return True;
4659 static BOOL run_test(char *name)
4661 BOOL ret = True;
4662 BOOL result = True;
4663 int i;
4664 double t;
4665 if (strequal(name,"ALL")) {
4666 for (i=0;torture_ops[i].name;i++) {
4667 run_test(torture_ops[i].name);
4671 for (i=0;torture_ops[i].name;i++) {
4672 snprintf(randomfname, sizeof(randomfname), "\\XX%x",
4673 (unsigned)random());
4675 if (strequal(name, torture_ops[i].name)) {
4676 printf("Running %s\n", name);
4677 if (torture_ops[i].flags & FLAG_MULTIPROC) {
4678 t = create_procs(torture_ops[i].fn, &result);
4679 if (!result) {
4680 ret = False;
4681 printf("TEST %s FAILED!\n", name);
4684 } else {
4685 start_timer();
4686 if (!torture_ops[i].fn(0)) {
4687 ret = False;
4688 printf("TEST %s FAILED!\n", name);
4690 t = end_timer();
4692 printf("%s took %g secs\n\n", name, t);
4695 return ret;
4699 static void usage(void)
4701 int i;
4703 printf("Usage: smbtorture //server/share[,share...] <options> TEST1 TEST2 ...\n");
4705 printf("\t-d debuglevel\n");
4706 printf("\t-U user%%pass\n");
4707 printf("\t-u user%%pass[,user%%pass...]\n");
4708 printf("\t-N numprocs\n");
4709 printf("\t-n my_netbios_name\n");
4710 printf("\t-W workgroup\n");
4711 printf("\t-o num_operations\n");
4712 printf("\t-O socket_options\n");
4713 printf("\t-m maximum protocol\n");
4714 printf("\t-L use oplocks\n");
4715 printf("\n\n");
4717 printf("tests are:");
4718 for (i=0;torture_ops[i].name;i++) {
4719 printf(" %s", torture_ops[i].name);
4721 printf("\n");
4723 printf("default test is ALL\n");
4725 exit(1);
4728 static BOOL split_password_from_username(char *username, char *password) {
4730 char * pp = strchr(username,'%');
4731 if (pp) {
4732 *pp = 0;
4733 pstrcpy(password, pp+1);
4734 return True;
4737 return False;
4740 static BOOL extract_users(char *user_list) {
4742 const char *separators = ",";
4744 char *p = strtok(user_list, separators);
4746 while(p && nusers < MAX_USERS) {
4748 vusers[nusers].username[0] = '\0';
4749 vusers[nusers].password[0] = '\0';
4750 vusers[nusers].gotpass = False;
4752 pstrcpy(vusers[nusers].username, p);
4754 vusers[nusers].gotpass = split_password_from_username(vusers[nusers].username, vusers[nusers].password);
4756 nusers++;
4758 p = strtok(NULL, separators);
4761 return True;
4764 static BOOL extract_shares(char *share_list) {
4766 const char *separators = ",";
4768 char *p = strtok(share_list, separators);
4770 while(p && nshares < MAX_TIDS) {
4772 pstrcpy(shares[nshares], p);
4774 nshares++;
4776 p = strtok(NULL, separators);
4779 return True;
4782 /****************************************************************************
4783 main program
4784 ****************************************************************************/
4786 int main(int argc,char *argv[])
4788 int opt, i;
4789 char *p;
4790 int test_flags = 0;
4791 BOOL *gotpass = &vusers[0].gotpass;
4792 extern char *optarg;
4793 extern int optind;
4794 extern FILE *dbf;
4795 static pstring servicesf = CONFIGFILE;
4796 BOOL correct = True;
4797 fstring user_list;
4798 fstring share_list;
4800 dbf = stdout;
4802 #ifdef HAVE_SETBUFFER
4803 setbuffer(stdout, NULL, 0);
4804 #endif
4805 charset_initialise();
4807 codepage_initialise(lp_client_code_page());
4809 codepage_initialise(lp_client_code_page());
4811 lp_load(servicesf,True,False,False);
4812 load_interfaces();
4814 if (argc < 2) {
4815 usage();
4818 for(p = argv[1]; *p; p++)
4819 if(*p == '\\')
4820 *p = '/';
4822 if (strncmp(argv[1], "//", 2)) {
4823 usage();
4826 fstrcpy(host, &argv[1][2]);
4827 p = strchr(&host[2],'/');
4828 if (!p) {
4829 usage();
4832 *p = 0;
4833 fstrcpy(share_list, p+1);
4835 get_myname(myname);
4837 if (*username == 0 && getenv("LOGNAME")) {
4839 pstrcpy(username,getenv("LOGNAME"));
4842 argc--;
4843 argv++;
4845 fstrcpy(workgroup, lp_workgroup());
4847 while ((opt = getopt(argc, argv, "hW:U:u:n:N:O:o:m:Ld:")) != EOF) {
4848 switch (opt) {
4849 case 'W':
4850 fstrcpy(workgroup,optarg);
4851 break;
4852 case 'm':
4853 max_protocol = interpret_protocol(optarg, max_protocol);
4854 break;
4855 case 'N':
4856 nprocs = atoi(optarg);
4857 break;
4858 case 'o':
4859 numops = atoi(optarg);
4860 break;
4861 case 'd':
4862 DEBUGLEVEL = atoi(optarg);
4863 break;
4864 case 'O':
4865 sockops = optarg;
4866 break;
4867 case 'L':
4868 use_oplocks = True;
4869 break;
4870 case 'n':
4871 fstrcpy(myname, optarg);
4872 break;
4873 case 'U':
4874 pstrcpy(username,optarg);
4875 *gotpass = split_password_from_username(username, password);
4876 break;
4877 case 'u':
4878 pstrcpy(user_list, optarg);
4879 if(!extract_users(user_list)) {
4880 usage();
4882 break;
4883 default:
4884 printf("Unknown option %c (%d)\n", (char)opt, opt);
4885 usage();
4889 if (argc == 1) {
4890 get_test_flags("ALL", &test_flags);
4891 } else {
4892 for (i=1;i<argc;i++) {
4894 get_test_flags(argv[i], &test_flags);
4898 while (!*gotpass) {
4899 fstring s;
4900 snprintf(s, sizeof(s), "Password for user %s:", username);
4901 p = getpass(s);
4902 if (p) {
4903 pstrcpy(password, p);
4904 *gotpass = True;
4908 extract_shares(share_list);
4910 if(test_flags & FLAG_MULTIUSER) {
4912 if(nusers == 1) {
4914 /*generate another user from the one that is already specified*/
4916 vusers[nusers] = vusers[nusers-1];
4918 nusers++;
4921 for(i = 1; i < nusers; i++) {
4923 fstring s;
4925 if(vusers[i].gotpass) {
4927 continue;
4930 snprintf(s, sizeof(s), "Password for user %s:", vusers[i].username);
4932 p = getpass(s);
4933 if (p) {
4935 pstrcpy(vusers[i].password, p);
4936 vusers[i].gotpass = True;
4941 user_list[0] = '\0';
4943 for(i = 0; i < nusers; i++) {
4945 if(!vusers[i].gotpass) {
4947 continue;
4950 if(i) {
4952 fstrcat(user_list, ", ");
4955 fstrcat(user_list, vusers[i].username);
4958 printf("host=%s shares=%s users=%s myname=%s\n", host, share_list, user_list, myname);
4960 if (argc == 1) {
4961 correct = run_test("ALL");
4962 } else {
4963 for (i=1;i<argc;i++) {
4964 if (!run_test(argv[i])) {
4965 correct = False;
4970 if (correct) {
4971 return(0);
4972 } else {
4973 return(1);