fixed error check which caused domain logons to fail
[Samba.git] / source / utils / torture.c
blobf85a73293dda9823999c618ba413121e468fcfb9
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;
138 extern struct in_addr ipzero;
140 ZERO_STRUCTP(c);
142 make_nmb_name(&calling, myname, 0x0);
143 make_nmb_name(&called , host, 0x20);
145 ip = ipzero;
147 if (!cli_initialise(c) || !cli_connect(c, host, &ip)) {
148 printf("Failed to connect with %s\n", host);
149 return False;
152 c->timeout = 120000; /* set a really long timeout (2 minutes) */
153 if (use_oplocks) c->use_oplocks = True;
154 if (use_level_II_oplocks) c->use_level_II_oplocks = True;
156 if (!cli_session_request(c, &calling, &called)) {
157 printf("%s rejected the session\n",host);
158 cli_shutdown(c);
159 return False;
162 return True;
165 static BOOL open_connection(struct cli_state *c)
167 ZERO_STRUCTP(c);
169 if (!open_nbt_connection(c)) {
170 return False;
173 if (!cli_negprot(c)) {
174 printf("%s rejected the negprot (%s)\n",host, cli_errstr(c));
175 cli_shutdown(c);
176 return False;
179 if (!cli_session_setup(c, username,
180 password, strlen(password),
181 password, strlen(password),
182 workgroup)) {
183 printf("%s rejected the sessionsetup (%s)\n", host, cli_errstr(c));
184 cli_shutdown(c);
185 return False;
188 if (!cli_send_tconX(c, share, "?????",
189 password, strlen(password)+1)) {
190 printf("%s refused tree connect (%s)\n", host, cli_errstr(c));
191 cli_shutdown(c);
192 return False;
195 return True;
198 static BOOL close_connection(struct cli_state *c)
200 BOOL ret = True;
201 if (!cli_tdis(c)) {
202 printf("tdis failed (%s)\n", cli_errstr(c));
203 ret = False;
206 cli_shutdown(c);
208 return ret;
212 /* check if the server produced the expected error code */
213 static BOOL check_error(struct cli_state *c,
214 uint8 eclass, uint32 ecode, uint32 nterr)
216 uint8 class;
217 uint32 num;
219 (void)cli_dos_error(c, &class, &num);
220 if ((eclass != class || ecode != num) &&
221 num != (nterr&0xFFFFFF)) {
222 printf("unexpected error code class=%d code=%d\n",
223 (int)class, (int)num);
224 printf(" expected %d/%d %d\n",
225 (int)eclass, (int)ecode, (int)nterr);
226 return False;
228 return True;
232 static BOOL wait_lock(struct cli_state *c, int fnum, uint32 offset, uint32 len)
234 while (!cli_lock(c, fnum, offset, len, -1, WRITE_LOCK)) {
235 if (!check_error(c, ERRDOS, ERRlock, 0)) return False;
237 return True;
241 static BOOL rw_torture(struct cli_state *c)
243 char *lockfname = "\\torture.lck";
244 fstring fname;
245 int fnum;
246 int fnum2;
247 pid_t pid2, pid = getpid();
248 int i, j;
249 char buf[1024];
250 BOOL correct = True;
252 fnum2 = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
253 DENY_NONE);
254 if (fnum2 == -1)
255 fnum2 = cli_open(c, lockfname, O_RDWR, DENY_NONE);
256 if (fnum2 == -1) {
257 printf("open of %s failed (%s)\n", lockfname, cli_errstr(c));
258 return False;
262 for (i=0;i<numops;i++) {
263 unsigned n = (unsigned)sys_random()%10;
264 if (i % 10 == 0) {
265 printf("%d\r", i); fflush(stdout);
267 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
269 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
270 return False;
273 fnum = cli_open(c, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL);
274 if (fnum == -1) {
275 printf("open failed (%s)\n", cli_errstr(c));
276 correct = False;
277 break;
280 if (cli_write(c, fnum, 0, (char *)&pid, 0, sizeof(pid)) != sizeof(pid)) {
281 printf("write failed (%s)\n", cli_errstr(c));
282 correct = False;
285 for (j=0;j<50;j++) {
286 if (cli_write(c, fnum, 0, (char *)buf,
287 sizeof(pid)+(j*sizeof(buf)),
288 sizeof(buf)) != sizeof(buf)) {
289 printf("write failed (%s)\n", cli_errstr(c));
290 correct = False;
294 pid2 = 0;
296 if (cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid)) != sizeof(pid)) {
297 printf("read failed (%s)\n", cli_errstr(c));
298 correct = False;
301 if (pid2 != pid) {
302 printf("data corruption!\n");
303 correct = False;
306 if (!cli_close(c, fnum)) {
307 printf("close failed (%s)\n", cli_errstr(c));
308 correct = False;
311 if (!cli_unlink(c, fname)) {
312 printf("unlink failed (%s)\n", cli_errstr(c));
313 correct = False;
316 if (!cli_unlock(c, fnum2, n*sizeof(int), sizeof(int))) {
317 printf("unlock failed (%s)\n", cli_errstr(c));
318 correct = False;
322 cli_close(c, fnum2);
323 cli_unlink(c, lockfname);
325 printf("%d\n", i);
327 return correct;
330 static BOOL run_torture(int dummy)
332 struct cli_state cli;
333 BOOL ret;
335 cli = current_cli;
337 cli_sockopt(&cli, sockops);
339 ret = rw_torture(&cli);
341 if (!close_connection(&cli)) {
342 ret = False;
345 return ret;
348 static BOOL rw_torture3(struct cli_state *c, char *lockfname)
350 int fnum = -1;
351 int i = 0;
352 char buf[131072];
353 char buf_rd[131072];
354 unsigned count;
355 unsigned countprev = 0;
356 unsigned sent = 0;
357 BOOL correct = True;
359 srandom(1);
360 for (i = 0; i < sizeof(buf); i += sizeof(uint32))
362 SIVAL(buf, i, sys_random());
365 if (procnum == 0)
367 fnum = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
368 DENY_NONE);
369 if (fnum == -1) {
370 printf("first open read/write of %s failed (%s)\n",
371 lockfname, cli_errstr(c));
372 return False;
375 else
377 for (i = 0; i < 500 && fnum == -1; i++)
379 fnum = cli_open(c, lockfname, O_RDONLY,
380 DENY_NONE);
381 msleep(10);
383 if (fnum == -1) {
384 printf("second open read-only of %s failed (%s)\n",
385 lockfname, cli_errstr(c));
386 return False;
390 i = 0;
391 for (count = 0; count < sizeof(buf); count += sent)
393 if (count >= countprev) {
394 printf("%d %8d\r", i, count);
395 fflush(stdout);
396 i++;
397 countprev += (sizeof(buf) / 20);
400 if (procnum == 0)
402 sent = ((unsigned)sys_random()%(20))+ 1;
403 if (sent > sizeof(buf) - count)
405 sent = sizeof(buf) - count;
408 if (cli_write(c, fnum, 0, buf+count, count, sent) != sent) {
409 printf("write failed (%s)\n", cli_errstr(c));
410 correct = False;
413 else
415 sent = cli_read(c, fnum, buf_rd+count, count,
416 sizeof(buf)-count);
417 if (sent < 0)
419 printf("read failed offset:%d size:%d (%s)\n",
420 count, sizeof(buf)-count,
421 cli_errstr(c));
422 correct = False;
423 sent = 0;
425 if (sent > 0)
427 if (memcmp(buf_rd+count, buf+count, sent) != 0)
429 printf("read/write compare failed\n");
430 printf("offset: %d req %d recvd %d\n",
431 count, sizeof(buf)-count, sent);
432 correct = False;
433 break;
440 if (!cli_close(c, fnum)) {
441 printf("close failed (%s)\n", cli_errstr(c));
442 correct = False;
445 return correct;
448 static BOOL rw_torture2(struct cli_state *c1, struct cli_state *c2)
450 char *lockfname = "\\torture.lck";
451 int fnum1;
452 int fnum2;
453 int i;
454 char buf[131072];
455 char buf_rd[131072];
456 BOOL correct = True;
457 ssize_t bytes_read;
459 if (!cli_unlink(c1, lockfname)) {
460 printf("unlink failed (%s) (normal, this file should not exist)\n", cli_errstr(c1));
463 fnum1 = cli_open(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
464 DENY_NONE);
465 if (fnum1 == -1) {
466 printf("first open read/write of %s failed (%s)\n",
467 lockfname, cli_errstr(c1));
468 return False;
470 fnum2 = cli_open(c2, lockfname, O_RDONLY,
471 DENY_NONE);
472 if (fnum2 == -1) {
473 printf("second open read-only of %s failed (%s)\n",
474 lockfname, cli_errstr(c2));
475 cli_close(c1, fnum1);
476 return False;
479 for (i=0;i<numops;i++)
481 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
482 if (i % 10 == 0) {
483 printf("%d\r", i); fflush(stdout);
486 generate_random_buffer(buf, buf_size, False);
488 if (cli_write(c1, fnum1, 0, buf, 0, buf_size) != buf_size) {
489 printf("write failed (%s)\n", cli_errstr(c1));
490 correct = False;
493 if ((bytes_read = cli_read(c2, fnum2, buf_rd, 0, buf_size)) != buf_size) {
494 printf("read failed (%s)\n", cli_errstr(c2));
495 printf("read %d, expected %d\n", bytes_read, buf_size);
496 correct = False;
499 if (memcmp(buf_rd, buf, buf_size) != 0)
501 printf("read/write compare failed\n");
502 correct = False;
506 if (!cli_close(c2, fnum2)) {
507 printf("close failed (%s)\n", cli_errstr(c2));
508 correct = False;
510 if (!cli_close(c1, fnum1)) {
511 printf("close failed (%s)\n", cli_errstr(c1));
512 correct = False;
515 if (!cli_unlink(c1, lockfname)) {
516 printf("unlink failed (%s)\n", cli_errstr(c1));
517 correct = False;
520 return correct;
523 static BOOL run_readwritetest(int dummy)
525 static struct cli_state cli1, cli2;
526 BOOL test1, test2;
528 if (!open_connection(&cli1) || !open_connection(&cli2)) {
529 return False;
531 cli_sockopt(&cli1, sockops);
532 cli_sockopt(&cli2, sockops);
534 printf("starting readwritetest\n");
536 test1 = rw_torture2(&cli1, &cli2);
537 printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
539 test2 = rw_torture2(&cli1, &cli1);
540 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
542 if (!close_connection(&cli1)) {
543 test1 = False;
546 if (!close_connection(&cli2)) {
547 test2 = False;
550 return (test1 && test2);
553 static BOOL run_readwritemulti(int dummy)
555 static struct cli_state cli;
556 BOOL test;
558 cli = current_cli;
560 cli_sockopt(&cli, sockops);
562 printf("run_readwritemulti: fname %s\n", randomfname);
563 test = rw_torture3(&cli, randomfname);
565 if (!close_connection(&cli)) {
566 test = False;
569 return test;
572 static BOOL run_readwritelarge(int dummy)
574 static struct cli_state cli1;
575 int fnum1;
576 char *lockfname = "\\large.dat";
577 size_t fsize;
578 char buf[0x10000];
579 BOOL correct = True;
581 if (!open_connection(&cli1)) {
582 return False;
584 cli_sockopt(&cli1, sockops);
585 memset(buf,'\0',sizeof(buf));
587 cli1.max_xmit = 0x11000;
589 printf("starting readwritelarge\n");
591 cli_unlink(&cli1, lockfname);
593 fnum1 = cli_open(&cli1, lockfname, O_RDWR | O_CREAT | O_EXCL, DENY_NONE);
594 if (fnum1 == -1) {
595 printf("open read/write of %s failed (%s)\n", lockfname, cli_errstr(&cli1));
596 return False;
599 cli_write(&cli1, fnum1, 0, buf, 0, sizeof(buf));
601 if (!cli_close(&cli1, fnum1)) {
602 printf("close failed (%s)\n", cli_errstr(&cli1));
603 correct = False;
606 if (!cli_qpathinfo(&cli1, lockfname, NULL, NULL, NULL, &fsize, NULL)) {
607 printf("qpathinfo failed (%s)\n", cli_errstr(&cli1));
608 correct = False;
611 if (fsize == sizeof(buf))
612 printf("readwritelarge test 1 succeeded (size = %x)\n", fsize);
613 else {
614 printf("readwritelarge test 1 failed (size = %x)\n", fsize);
615 correct = False;
618 if (!cli_unlink(&cli1, lockfname)) {
619 printf("unlink failed (%s)\n", cli_errstr(&cli1));
620 correct = False;
623 fnum1 = cli_open(&cli1, lockfname, O_RDWR | O_CREAT | O_EXCL, DENY_NONE);
624 if (fnum1 == -1) {
625 printf("open read/write of %s failed (%s)\n", lockfname, cli_errstr(&cli1));
626 return False;
629 cli_smbwrite(&cli1, fnum1, buf, 0, sizeof(buf));
631 if (!cli_close(&cli1, fnum1)) {
632 printf("close failed (%s)\n", cli_errstr(&cli1));
633 correct = False;
636 if (!close_connection(&cli1)) {
637 correct = False;
639 return correct;
642 int line_count = 0;
644 /* run a test that simulates an approximate netbench client load */
645 static BOOL run_netbench(int client)
647 struct cli_state cli;
648 int i;
649 fstring fname;
650 pstring line;
651 char cname[20];
652 FILE *f;
653 char *params[20];
654 BOOL correct = True;
656 cli = current_cli;
658 cli_sockopt(&cli, sockops);
660 nb_setup(&cli);
662 slprintf(cname,sizeof(fname), "CLIENT%d", client);
664 f = fopen("client.txt", "r");
666 if (!f) {
667 perror("client.txt");
668 return False;
671 while (fgets(line, sizeof(line)-1, f)) {
672 line_count++;
674 line[strlen(line)-1] = 0;
676 /* printf("[%d] %s\n", line_count, line); */
678 all_string_sub(line,"CLIENT1", cname, sizeof(line));
680 for (i=0;i<20;i++) params[i] = "";
682 /* parse the command parameters */
683 params[0] = strtok(line," ");
684 i = 0;
685 while (params[i]) params[++i] = strtok(NULL," ");
687 params[i] = "";
689 if (i < 2) continue;
691 if (strcmp(params[1],"REQUEST") == 0) {
692 if (!strcmp(params[0],"SMBopenX")) {
693 fstrcpy(fname, params[5]);
694 } else if (!strcmp(params[0],"SMBclose")) {
695 nb_close(atoi(params[3]));
696 } else if (!strcmp(params[0],"SMBmkdir")) {
697 nb_mkdir(params[3]);
698 } else if (!strcmp(params[0],"CREATE")) {
699 nb_create(params[3], atoi(params[5]));
700 } else if (!strcmp(params[0],"SMBrmdir")) {
701 nb_rmdir(params[3]);
702 } else if (!strcmp(params[0],"SMBunlink")) {
703 fstrcpy(fname, params[3]);
704 } else if (!strcmp(params[0],"SMBmv")) {
705 nb_rename(params[3], params[5]);
706 } else if (!strcmp(params[0],"SMBgetatr")) {
707 fstrcpy(fname, params[3]);
708 } else if (!strcmp(params[0],"SMBwrite")) {
709 nb_write(atoi(params[3]),
710 atoi(params[5]), atoi(params[7]));
711 } else if (!strcmp(params[0],"SMBwritebraw")) {
712 nb_write(atoi(params[3]),
713 atoi(params[7]), atoi(params[5]));
714 } else if (!strcmp(params[0],"SMBreadbraw")) {
715 nb_read(atoi(params[3]),
716 atoi(params[7]), atoi(params[5]));
717 } else if (!strcmp(params[0],"SMBread")) {
718 nb_read(atoi(params[3]),
719 atoi(params[5]), atoi(params[7]));
721 } else {
722 if (!strcmp(params[0],"SMBopenX")) {
723 if (!strncmp(params[2], "ERR", 3)) continue;
724 nb_open(fname, atoi(params[3]), atoi(params[5]));
725 } else if (!strcmp(params[0],"SMBgetatr")) {
726 if (!strncmp(params[2], "ERR", 3)) continue;
727 nb_stat(fname, atoi(params[3]));
728 } else if (!strcmp(params[0],"SMBunlink")) {
729 if (!strncmp(params[2], "ERR", 3)) continue;
730 nb_unlink(fname);
734 fclose(f);
736 slprintf(fname,sizeof(fname), "CLIENTS/CLIENT%d", client);
737 rmdir(fname);
738 rmdir("CLIENTS");
740 printf("+");
742 if (!close_connection(&cli)) {
743 correct = False;
746 return correct;
750 /* run a test that simulates an approximate netbench w9X client load */
751 static BOOL run_nbw95(int dummy)
753 double t;
754 BOOL correct = True;
755 t = create_procs(run_netbench, &correct);
756 /* to produce a netbench result we scale accoding to the
757 netbench measured throughput for the run that produced the
758 sniff that was used to produce client.txt. That run used 2
759 clients and ran for 660 seconds to produce a result of
760 4MBit/sec. */
761 printf("Throughput %g MB/sec (NB=%g MB/sec %g MBit/sec)\n",
762 132*nprocs/t, 0.5*0.5*nprocs*660/t, 2*nprocs*660/t);
763 return correct;
766 /* run a test that simulates an approximate netbench wNT client load */
767 static BOOL run_nbwnt(int dummy)
769 double t;
770 BOOL correct = True;
771 t = create_procs(run_netbench, &correct);
772 printf("Throughput %g MB/sec (NB=%g MB/sec %g MBit/sec)\n",
773 132*nprocs/t, 0.5*0.5*nprocs*660/t, 2*nprocs*660/t);
774 return correct;
780 This test checks for two things:
782 1) correct support for retaining locks over a close (ie. the server
783 must not use posix semantics)
784 2) support for lock timeouts
786 static BOOL run_locktest1(int dummy)
788 static struct cli_state cli1, cli2;
789 char *fname = "\\lockt1.lck";
790 int fnum1, fnum2, fnum3;
791 time_t t1, t2;
793 if (!open_connection(&cli1) || !open_connection(&cli2)) {
794 return False;
796 cli_sockopt(&cli1, sockops);
797 cli_sockopt(&cli2, sockops);
799 printf("starting locktest1\n");
801 cli_unlink(&cli1, fname);
803 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
804 if (fnum1 == -1) {
805 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
806 return False;
808 fnum2 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
809 if (fnum2 == -1) {
810 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli1));
811 return False;
813 fnum3 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
814 if (fnum3 == -1) {
815 printf("open3 of %s failed (%s)\n", fname, cli_errstr(&cli2));
816 return False;
819 if (!cli_lock(&cli1, fnum1, 0, 4, 0, WRITE_LOCK)) {
820 printf("lock1 failed (%s)\n", cli_errstr(&cli1));
821 return False;
825 if (cli_lock(&cli2, fnum3, 0, 4, 0, WRITE_LOCK)) {
826 printf("lock2 succeeded! This is a locking bug\n");
827 return False;
828 } else {
829 if (!check_error(&cli2, ERRDOS, ERRlock, 0)) return False;
833 printf("Testing lock timeouts\n");
834 t1 = time(NULL);
835 if (cli_lock(&cli2, fnum3, 0, 4, 10*1000, WRITE_LOCK)) {
836 printf("lock3 succeeded! This is a locking bug\n");
837 return False;
838 } else {
839 if (!check_error(&cli2, ERRDOS, ERRlock, 0)) return False;
841 t2 = time(NULL);
843 if (t2 - t1 < 5) {
844 printf("error: This server appears not to support timed lock requests\n");
847 if (!cli_close(&cli1, fnum2)) {
848 printf("close1 failed (%s)\n", cli_errstr(&cli1));
849 return False;
852 if (cli_lock(&cli2, fnum3, 0, 4, 0, WRITE_LOCK)) {
853 printf("lock4 succeeded! This is a locking bug\n");
854 return False;
855 } else {
856 if (!check_error(&cli2, ERRDOS, ERRlock, 0)) return False;
859 if (!cli_close(&cli1, fnum1)) {
860 printf("close2 failed (%s)\n", cli_errstr(&cli1));
861 return False;
864 if (!cli_close(&cli2, fnum3)) {
865 printf("close3 failed (%s)\n", cli_errstr(&cli2));
866 return False;
869 if (!cli_unlink(&cli1, fname)) {
870 printf("unlink failed (%s)\n", cli_errstr(&cli1));
871 return False;
875 if (!close_connection(&cli1)) {
876 return False;
879 if (!close_connection(&cli2)) {
880 return False;
883 printf("Passed locktest1\n");
884 return True;
888 checks for correct tconX support
890 static BOOL run_tcon_test(int dummy)
892 static struct cli_state cli1;
893 char *fname = "\\tcontest.tmp";
894 int fnum1;
895 uint16 cnum;
896 char buf[4];
898 if (!open_connection(&cli1)) {
899 return False;
901 cli_sockopt(&cli1, sockops);
903 printf("starting tcontest\n");
905 cli_unlink(&cli1, fname);
907 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
908 if (fnum1 == -1)
910 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
911 return False;
914 cnum = cli1.cnum;
916 if (cli_write(&cli1, fnum1, 0, buf, 130, 4) != 4)
918 printf("write failed (%s)", cli_errstr(&cli1));
919 return False;
922 if (!cli_send_tconX(&cli1, share, "?????",
923 password, strlen(password)+1)) {
924 printf("%s refused 2nd tree connect (%s)\n", host,
925 cli_errstr(&cli1));
926 cli_shutdown(&cli1);
927 return False;
930 if (cli_write(&cli1, fnum1, 0, buf, 130, 4) == 4)
932 printf("write succeeded (%s)", cli_errstr(&cli1));
933 return False;
936 if (cli_close(&cli1, fnum1)) {
937 printf("close2 succeeded (%s)\n", cli_errstr(&cli1));
938 return False;
941 if (!cli_tdis(&cli1)) {
942 printf("tdis failed (%s)\n", cli_errstr(&cli1));
943 return False;
946 cli1.cnum = cnum;
948 if (!cli_close(&cli1, fnum1)) {
949 printf("close2 failed (%s)\n", cli_errstr(&cli1));
950 return False;
953 if (!close_connection(&cli1)) {
954 return False;
957 printf("Passed tcontest\n");
958 return True;
963 This test checks that
965 1) the server supports multiple locking contexts on the one SMB
966 connection, distinguished by PID.
968 2) the server correctly fails overlapping locks made by the same PID (this
969 goes against POSIX behaviour, which is why it is tricky to implement)
971 3) the server denies unlock requests by an incorrect client PID
973 static BOOL run_locktest2(int dummy)
975 static struct cli_state cli;
976 char *fname = "\\lockt2.lck";
977 int fnum1, fnum2, fnum3;
978 BOOL correct = True;
980 if (!open_connection(&cli)) {
981 return False;
984 cli_sockopt(&cli, sockops);
986 printf("starting locktest2\n");
988 cli_unlink(&cli, fname);
990 cli_setpid(&cli, 1);
992 fnum1 = cli_open(&cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
993 if (fnum1 == -1) {
994 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
995 return False;
998 fnum2 = cli_open(&cli, fname, O_RDWR, DENY_NONE);
999 if (fnum2 == -1) {
1000 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli));
1001 return False;
1004 cli_setpid(&cli, 2);
1006 fnum3 = cli_open(&cli, fname, O_RDWR, DENY_NONE);
1007 if (fnum3 == -1) {
1008 printf("open3 of %s failed (%s)\n", fname, cli_errstr(&cli));
1009 return False;
1012 cli_setpid(&cli, 1);
1014 if (!cli_lock(&cli, fnum1, 0, 4, 0, WRITE_LOCK)) {
1015 printf("lock1 failed (%s)\n", cli_errstr(&cli));
1016 return False;
1019 if (cli_lock(&cli, fnum1, 0, 4, 0, WRITE_LOCK)) {
1020 printf("WRITE lock1 succeeded! This is a locking bug\n");
1021 correct = False;
1022 } else {
1023 if (!check_error(&cli, ERRDOS, ERRlock, 0)) return False;
1026 if (cli_lock(&cli, fnum2, 0, 4, 0, WRITE_LOCK)) {
1027 printf("WRITE lock2 succeeded! This is a locking bug\n");
1028 correct = False;
1029 } else {
1030 if (!check_error(&cli, ERRDOS, ERRlock, 0)) return False;
1033 if (cli_lock(&cli, fnum2, 0, 4, 0, READ_LOCK)) {
1034 printf("READ lock2 succeeded! This is a locking bug\n");
1035 correct = False;
1036 } else {
1037 if (!check_error(&cli, ERRDOS, ERRlock, 0)) return False;
1040 if (!cli_lock(&cli, fnum1, 100, 4, 0, WRITE_LOCK)) {
1041 printf("lock at 100 failed (%s)\n", cli_errstr(&cli));
1043 cli_setpid(&cli, 2);
1044 if (cli_unlock(&cli, fnum1, 100, 4)) {
1045 printf("unlock at 100 succeeded! This is a locking bug\n");
1046 correct = False;
1049 if (cli_unlock(&cli, fnum1, 0, 4)) {
1050 printf("unlock1 succeeded! This is a locking bug\n");
1051 correct = False;
1052 } else {
1053 if (!check_error(&cli, ERRDOS, ERRnotlocked, 0)) return False;
1056 if (cli_unlock(&cli, fnum1, 0, 8)) {
1057 printf("unlock2 succeeded! This is a locking bug\n");
1058 correct = False;
1059 } else {
1060 if (!check_error(&cli, ERRDOS, ERRnotlocked, 0)) return False;
1063 if (cli_lock(&cli, fnum3, 0, 4, 0, WRITE_LOCK)) {
1064 printf("lock3 succeeded! This is a locking bug\n");
1065 correct = False;
1066 } else {
1067 if (!check_error(&cli, ERRDOS, ERRlock, 0)) return False;
1070 cli_setpid(&cli, 1);
1072 if (!cli_close(&cli, fnum1)) {
1073 printf("close1 failed (%s)\n", cli_errstr(&cli));
1074 return False;
1077 if (!cli_close(&cli, fnum2)) {
1078 printf("close2 failed (%s)\n", cli_errstr(&cli));
1079 return False;
1082 if (!cli_close(&cli, fnum3)) {
1083 printf("close3 failed (%s)\n", cli_errstr(&cli));
1084 return False;
1087 if (!close_connection(&cli)) {
1088 correct = False;
1091 printf("locktest2 finished\n");
1093 return correct;
1098 This test checks that
1100 1) the server supports the full offset range in lock requests
1102 static BOOL run_locktest3(int dummy)
1104 static struct cli_state cli1, cli2;
1105 char *fname = "\\lockt3.lck";
1106 int fnum1, fnum2, i;
1107 uint32 offset;
1108 BOOL correct = True;
1110 #define NEXT_OFFSET offset += (~(uint32)0) / numops
1112 if (!open_connection(&cli1) || !open_connection(&cli2)) {
1113 return False;
1115 cli_sockopt(&cli1, sockops);
1116 cli_sockopt(&cli2, sockops);
1118 printf("starting locktest3\n");
1120 cli_unlink(&cli1, fname);
1122 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1123 if (fnum1 == -1) {
1124 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
1125 return False;
1127 fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
1128 if (fnum2 == -1) {
1129 printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli2));
1130 return False;
1133 for (offset=i=0;i<numops;i++) {
1134 NEXT_OFFSET;
1135 if (!cli_lock(&cli1, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
1136 printf("lock1 %d failed (%s)\n",
1138 cli_errstr(&cli1));
1139 return False;
1142 if (!cli_lock(&cli2, fnum2, offset-2, 1, 0, WRITE_LOCK)) {
1143 printf("lock2 %d failed (%s)\n",
1145 cli_errstr(&cli1));
1146 return False;
1150 for (offset=i=0;i<numops;i++) {
1151 NEXT_OFFSET;
1153 if (cli_lock(&cli1, fnum1, offset-2, 1, 0, WRITE_LOCK)) {
1154 printf("error: lock1 %d succeeded!\n", i);
1155 return False;
1158 if (cli_lock(&cli2, fnum2, offset-1, 1, 0, WRITE_LOCK)) {
1159 printf("error: lock2 %d succeeded!\n", i);
1160 return False;
1163 if (cli_lock(&cli1, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
1164 printf("error: lock3 %d succeeded!\n", i);
1165 return False;
1168 if (cli_lock(&cli2, fnum2, offset-2, 1, 0, WRITE_LOCK)) {
1169 printf("error: lock4 %d succeeded!\n", i);
1170 return False;
1174 for (offset=i=0;i<numops;i++) {
1175 NEXT_OFFSET;
1177 if (!cli_unlock(&cli1, fnum1, offset-1, 1)) {
1178 printf("unlock1 %d failed (%s)\n",
1180 cli_errstr(&cli1));
1181 return False;
1184 if (!cli_unlock(&cli2, fnum2, offset-2, 1)) {
1185 printf("unlock2 %d failed (%s)\n",
1187 cli_errstr(&cli1));
1188 return False;
1192 if (!cli_close(&cli1, fnum1)) {
1193 printf("close1 failed (%s)\n", cli_errstr(&cli1));
1194 return False;
1197 if (!cli_close(&cli2, fnum2)) {
1198 printf("close2 failed (%s)\n", cli_errstr(&cli2));
1199 return False;
1202 if (!cli_unlink(&cli1, fname)) {
1203 printf("unlink failed (%s)\n", cli_errstr(&cli1));
1204 return False;
1207 if (!close_connection(&cli1)) {
1208 correct = False;
1211 if (!close_connection(&cli2)) {
1212 correct = False;
1215 printf("finished locktest3\n");
1217 return correct;
1220 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1221 printf("** "); correct = False; \
1225 looks at overlapping locks
1227 static BOOL run_locktest4(int dummy)
1229 static struct cli_state cli1, cli2;
1230 char *fname = "\\lockt4.lck";
1231 int fnum1, fnum2, f;
1232 BOOL ret;
1233 char buf[1000];
1234 BOOL correct = True;
1236 if (!open_connection(&cli1) || !open_connection(&cli2)) {
1237 return False;
1240 cli_sockopt(&cli1, sockops);
1241 cli_sockopt(&cli2, sockops);
1243 printf("starting locktest4\n");
1245 cli_unlink(&cli1, fname);
1247 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1248 fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
1250 memset(buf, 0, sizeof(buf));
1252 if (cli_write(&cli1, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
1253 printf("Failed to create file\n");
1254 correct = False;
1255 goto fail;
1258 ret = cli_lock(&cli1, fnum1, 0, 4, 0, WRITE_LOCK) &&
1259 cli_lock(&cli1, fnum1, 2, 4, 0, WRITE_LOCK);
1260 EXPECTED(ret, False);
1261 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1263 ret = cli_lock(&cli1, fnum1, 10, 4, 0, READ_LOCK) &&
1264 cli_lock(&cli1, fnum1, 12, 4, 0, READ_LOCK);
1265 EXPECTED(ret, True);
1266 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1268 ret = cli_lock(&cli1, fnum1, 20, 4, 0, WRITE_LOCK) &&
1269 cli_lock(&cli2, fnum2, 22, 4, 0, WRITE_LOCK);
1270 EXPECTED(ret, False);
1271 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1273 ret = cli_lock(&cli1, fnum1, 30, 4, 0, READ_LOCK) &&
1274 cli_lock(&cli2, fnum2, 32, 4, 0, READ_LOCK);
1275 EXPECTED(ret, True);
1276 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1278 ret = (cli_setpid(&cli1, 1), cli_lock(&cli1, fnum1, 40, 4, 0, WRITE_LOCK)) &&
1279 (cli_setpid(&cli1, 2), cli_lock(&cli1, fnum1, 42, 4, 0, WRITE_LOCK));
1280 EXPECTED(ret, False);
1281 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1283 ret = (cli_setpid(&cli1, 1), cli_lock(&cli1, fnum1, 50, 4, 0, READ_LOCK)) &&
1284 (cli_setpid(&cli1, 2), cli_lock(&cli1, fnum1, 52, 4, 0, READ_LOCK));
1285 EXPECTED(ret, True);
1286 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1288 ret = cli_lock(&cli1, fnum1, 60, 4, 0, READ_LOCK) &&
1289 cli_lock(&cli1, fnum1, 60, 4, 0, READ_LOCK);
1290 EXPECTED(ret, True);
1291 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1293 ret = cli_lock(&cli1, fnum1, 70, 4, 0, WRITE_LOCK) &&
1294 cli_lock(&cli1, fnum1, 70, 4, 0, WRITE_LOCK);
1295 EXPECTED(ret, False);
1296 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1298 ret = cli_lock(&cli1, fnum1, 80, 4, 0, READ_LOCK) &&
1299 cli_lock(&cli1, fnum1, 80, 4, 0, WRITE_LOCK);
1300 EXPECTED(ret, False);
1301 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
1303 ret = cli_lock(&cli1, fnum1, 90, 4, 0, WRITE_LOCK) &&
1304 cli_lock(&cli1, fnum1, 90, 4, 0, READ_LOCK);
1305 EXPECTED(ret, True);
1306 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1308 ret = (cli_setpid(&cli1, 1), cli_lock(&cli1, fnum1, 100, 4, 0, WRITE_LOCK)) &&
1309 (cli_setpid(&cli1, 2), cli_lock(&cli1, fnum1, 100, 4, 0, READ_LOCK));
1310 EXPECTED(ret, False);
1311 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1313 ret = cli_lock(&cli1, fnum1, 110, 4, 0, READ_LOCK) &&
1314 cli_lock(&cli1, fnum1, 112, 4, 0, READ_LOCK) &&
1315 cli_unlock(&cli1, fnum1, 110, 6);
1316 EXPECTED(ret, False);
1317 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
1320 ret = cli_lock(&cli1, fnum1, 120, 4, 0, WRITE_LOCK) &&
1321 (cli_read(&cli2, fnum2, buf, 120, 4) == 4);
1322 EXPECTED(ret, False);
1323 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
1325 ret = cli_lock(&cli1, fnum1, 130, 4, 0, READ_LOCK) &&
1326 (cli_write(&cli2, fnum2, 0, buf, 130, 4) == 4);
1327 EXPECTED(ret, False);
1328 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
1331 ret = cli_lock(&cli1, fnum1, 140, 4, 0, READ_LOCK) &&
1332 cli_lock(&cli1, fnum1, 140, 4, 0, READ_LOCK) &&
1333 cli_unlock(&cli1, fnum1, 140, 4) &&
1334 cli_unlock(&cli1, fnum1, 140, 4);
1335 EXPECTED(ret, True);
1336 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
1339 ret = cli_lock(&cli1, fnum1, 150, 4, 0, WRITE_LOCK) &&
1340 cli_lock(&cli1, fnum1, 150, 4, 0, READ_LOCK) &&
1341 cli_unlock(&cli1, fnum1, 150, 4) &&
1342 (cli_read(&cli2, fnum2, buf, 150, 4) == 4) &&
1343 !(cli_write(&cli2, fnum2, 0, buf, 150, 4) == 4) &&
1344 cli_unlock(&cli1, fnum1, 150, 4);
1345 EXPECTED(ret, True);
1346 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
1348 ret = cli_lock(&cli1, fnum1, 160, 4, 0, READ_LOCK) &&
1349 cli_unlock(&cli1, fnum1, 160, 4) &&
1350 (cli_write(&cli2, fnum2, 0, buf, 160, 4) == 4) &&
1351 (cli_read(&cli2, fnum2, buf, 160, 4) == 4);
1352 EXPECTED(ret, True);
1353 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
1355 ret = cli_lock(&cli1, fnum1, 170, 4, 0, WRITE_LOCK) &&
1356 cli_unlock(&cli1, fnum1, 170, 4) &&
1357 (cli_write(&cli2, fnum2, 0, buf, 170, 4) == 4) &&
1358 (cli_read(&cli2, fnum2, buf, 170, 4) == 4);
1359 EXPECTED(ret, True);
1360 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
1362 ret = cli_lock(&cli1, fnum1, 190, 4, 0, WRITE_LOCK) &&
1363 cli_lock(&cli1, fnum1, 190, 4, 0, READ_LOCK) &&
1364 cli_unlock(&cli1, fnum1, 190, 4) &&
1365 !(cli_write(&cli2, fnum2, 0, buf, 190, 4) == 4) &&
1366 (cli_read(&cli2, fnum2, buf, 190, 4) == 4);
1367 EXPECTED(ret, True);
1368 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
1370 cli_close(&cli1, fnum1);
1371 cli_close(&cli2, fnum2);
1372 fnum1 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
1373 f = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
1374 ret = cli_lock(&cli1, fnum1, 0, 8, 0, READ_LOCK) &&
1375 cli_lock(&cli1, f, 0, 1, 0, READ_LOCK) &&
1376 cli_close(&cli1, fnum1) &&
1377 ((fnum1 = cli_open(&cli1, fname, O_RDWR, DENY_NONE)) != -1) &&
1378 cli_lock(&cli1, fnum1, 7, 1, 0, WRITE_LOCK);
1379 cli_close(&cli1, f);
1380 EXPECTED(ret, True);
1381 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
1383 fail:
1384 cli_close(&cli1, fnum1);
1385 cli_close(&cli2, fnum2);
1386 cli_unlink(&cli1, fname);
1387 close_connection(&cli1);
1388 close_connection(&cli2);
1390 printf("finished locktest4\n");
1391 return correct;
1395 looks at lock upgrade/downgrade.
1397 static BOOL run_locktest5(int dummy)
1399 static struct cli_state cli1, cli2;
1400 char *fname = "\\lockt5.lck";
1401 int fnum1, fnum2, fnum3;
1402 BOOL ret;
1403 char buf[1000];
1404 BOOL correct = True;
1406 if (!open_connection(&cli1) || !open_connection(&cli2)) {
1407 return False;
1410 cli_sockopt(&cli1, sockops);
1411 cli_sockopt(&cli2, sockops);
1413 printf("starting locktest5\n");
1415 cli_unlink(&cli1, fname);
1417 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1418 fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
1419 fnum3 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
1421 memset(buf, 0, sizeof(buf));
1423 if (cli_write(&cli1, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
1424 printf("Failed to create file\n");
1425 correct = False;
1426 goto fail;
1429 /* Check for NT bug... */
1430 ret = cli_lock(&cli1, fnum1, 0, 8, 0, READ_LOCK) &&
1431 cli_lock(&cli1, fnum3, 0, 1, 0, READ_LOCK);
1432 cli_close(&cli1, fnum1);
1433 fnum1 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
1434 ret = cli_lock(&cli1, fnum1, 7, 1, 0, WRITE_LOCK);
1435 EXPECTED(ret, True);
1436 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
1437 cli_close(&cli1, fnum1);
1438 fnum1 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
1439 cli_unlock(&cli1, fnum3, 0, 1);
1441 ret = cli_lock(&cli1, fnum1, 0, 4, 0, WRITE_LOCK) &&
1442 cli_lock(&cli1, fnum1, 1, 1, 0, READ_LOCK);
1443 EXPECTED(ret, True);
1444 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
1446 ret = cli_lock(&cli2, fnum2, 0, 4, 0, READ_LOCK);
1447 EXPECTED(ret, False);
1449 printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
1451 /* Unlock the process 2 lock. */
1452 cli_unlock(&cli2, fnum2, 0, 4);
1454 ret = cli_lock(&cli1, fnum3, 0, 4, 0, READ_LOCK);
1455 EXPECTED(ret, False);
1457 printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
1459 /* Unlock the process 1 fnum3 lock. */
1460 cli_unlock(&cli1, fnum3, 0, 4);
1462 /* Stack 2 more locks here. */
1463 ret = cli_lock(&cli1, fnum1, 0, 4, 0, READ_LOCK) &&
1464 cli_lock(&cli1, fnum1, 0, 4, 0, READ_LOCK);
1466 EXPECTED(ret, True);
1467 printf("the same process %s stack read locks\n", ret?"can":"cannot");
1469 /* Unlock the first process lock, then check this was the WRITE lock that was
1470 removed. */
1472 ret = cli_unlock(&cli1, fnum1, 0, 4) &&
1473 cli_lock(&cli2, fnum2, 0, 4, 0, READ_LOCK);
1475 EXPECTED(ret, True);
1476 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
1478 /* Unlock the process 2 lock. */
1479 cli_unlock(&cli2, fnum2, 0, 4);
1481 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
1483 ret = cli_unlock(&cli1, fnum1, 1, 1) &&
1484 cli_unlock(&cli1, fnum1, 0, 4) &&
1485 cli_unlock(&cli1, fnum1, 0, 4);
1487 EXPECTED(ret, True);
1488 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
1490 /* Ensure the next unlock fails. */
1491 ret = cli_unlock(&cli1, fnum1, 0, 4);
1492 EXPECTED(ret, False);
1493 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
1495 /* Ensure connection 2 can get a write lock. */
1496 ret = cli_lock(&cli2, fnum2, 0, 4, 0, WRITE_LOCK);
1497 EXPECTED(ret, True);
1499 printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
1502 fail:
1503 cli_close(&cli1, fnum1);
1504 cli_close(&cli2, fnum2);
1505 cli_unlink(&cli1, fname);
1506 if (!close_connection(&cli1)) {
1507 correct = False;
1509 if (!close_connection(&cli2)) {
1510 correct = False;
1513 printf("finished locktest5\n");
1515 return correct;
1520 this produces a matrix of deny mode behaviour
1522 static BOOL run_denytest1(int dummy)
1524 static struct cli_state cli1, cli2;
1525 int fnum1, fnum2;
1526 int f, d1, d2, o1, o2, x=0;
1527 char *fnames[] = {"\\denytest1.exe", "\\denytest1.dat", NULL};
1528 struct {
1529 int v;
1530 char *name;
1531 } deny_modes[] = {
1532 {DENY_DOS, "DENY_DOS"},
1533 {DENY_ALL, "DENY_ALL"},
1534 {DENY_WRITE, "DENY_WRITE"},
1535 {DENY_READ, "DENY_READ"},
1536 {DENY_NONE, "DENY_NONE"},
1537 {DENY_FCB, "DENY_FCB"},
1538 {-1, NULL}};
1539 struct {
1540 int v;
1541 char *name;
1542 } open_modes[] = {
1543 {O_RDWR, "O_RDWR"},
1544 {O_RDONLY, "O_RDONLY"},
1545 {O_WRONLY, "O_WRONLY"},
1546 {-1, NULL}};
1547 BOOL correct = True;
1549 if (!open_connection(&cli1) || !open_connection(&cli2)) {
1550 return False;
1552 cli_sockopt(&cli1, sockops);
1553 cli_sockopt(&cli2, sockops);
1555 printf("starting denytest1\n");
1557 for (f=0;fnames[f];f++) {
1558 cli_unlink(&cli1, fnames[f]);
1560 fnum1 = cli_open(&cli1, fnames[f], O_RDWR|O_CREAT, DENY_NONE);
1561 cli_write(&cli1, fnum1, 0, fnames[f], 0, strlen(fnames[f]));
1562 cli_close(&cli1, fnum1);
1564 for (d1=0;deny_modes[d1].name;d1++)
1565 for (o1=0;open_modes[o1].name;o1++)
1566 for (d2=0;deny_modes[d2].name;d2++)
1567 for (o2=0;open_modes[o2].name;o2++) {
1568 fnum1 = cli_open(&cli1, fnames[f],
1569 open_modes[o1].v,
1570 deny_modes[d1].v);
1571 fnum2 = cli_open(&cli2, fnames[f],
1572 open_modes[o2].v,
1573 deny_modes[d2].v);
1575 printf("%s %8s %10s %8s %10s ",
1576 fnames[f],
1577 open_modes[o1].name,
1578 deny_modes[d1].name,
1579 open_modes[o2].name,
1580 deny_modes[d2].name);
1582 if (fnum1 == -1) {
1583 printf("X");
1584 } else if (fnum2 == -1) {
1585 printf("-");
1586 } else {
1587 if (cli_read(&cli2, fnum2, (void *)&x, 0, 1) == 1) {
1588 printf("R");
1590 if (cli_write(&cli2, fnum2, 0, (void *)&x, 0, 1) == 1) {
1591 printf("W");
1595 printf("\n");
1596 cli_close(&cli1, fnum1);
1597 cli_close(&cli2, fnum2);
1600 cli_unlink(&cli1, fnames[f]);
1603 if (!close_connection(&cli1)) {
1604 correct = False;
1606 if (!close_connection(&cli2)) {
1607 correct = False;
1610 printf("finshed denytest1\n");
1611 return correct;
1616 this produces a matrix of deny mode behaviour for two opens on the
1617 same connection
1619 static BOOL run_denytest2(int dummy)
1621 static struct cli_state cli1;
1622 int fnum1, fnum2;
1623 int f, d1, d2, o1, o2, x=0;
1624 char *fnames[] = {"\\denytest2.exe", "\\denytest2.dat", NULL};
1625 struct {
1626 int v;
1627 char *name;
1628 } deny_modes[] = {
1629 {DENY_DOS, "DENY_DOS"},
1630 {DENY_ALL, "DENY_ALL"},
1631 {DENY_WRITE, "DENY_WRITE"},
1632 {DENY_READ, "DENY_READ"},
1633 {DENY_NONE, "DENY_NONE"},
1634 {DENY_FCB, "DENY_FCB"},
1635 {-1, NULL}};
1636 struct {
1637 int v;
1638 char *name;
1639 } open_modes[] = {
1640 {O_RDWR, "O_RDWR"},
1641 {O_RDONLY, "O_RDONLY"},
1642 {O_WRONLY, "O_WRONLY"},
1643 {-1, NULL}};
1644 BOOL correct = True;
1646 if (!open_connection(&cli1)) {
1647 return False;
1649 cli_sockopt(&cli1, sockops);
1651 printf("starting denytest2\n");
1653 for (f=0;fnames[f];f++) {
1654 cli_unlink(&cli1, fnames[f]);
1656 fnum1 = cli_open(&cli1, fnames[f], O_RDWR|O_CREAT, DENY_NONE);
1657 cli_write(&cli1, fnum1, 0, fnames[f], 0, strlen(fnames[f]));
1658 cli_close(&cli1, fnum1);
1660 for (d1=0;deny_modes[d1].name;d1++)
1661 for (o1=0;open_modes[o1].name;o1++)
1662 for (d2=0;deny_modes[d2].name;d2++)
1663 for (o2=0;open_modes[o2].name;o2++) {
1664 fnum1 = cli_open(&cli1, fnames[f],
1665 open_modes[o1].v,
1666 deny_modes[d1].v);
1667 fnum2 = cli_open(&cli1, fnames[f],
1668 open_modes[o2].v,
1669 deny_modes[d2].v);
1671 printf("%s %8s %10s %8s %10s ",
1672 fnames[f],
1673 open_modes[o1].name,
1674 deny_modes[d1].name,
1675 open_modes[o2].name,
1676 deny_modes[d2].name);
1678 if (fnum1 == -1) {
1679 printf("X");
1680 } else if (fnum2 == -1) {
1681 printf("-");
1682 } else {
1683 if (cli_read(&cli1, fnum2, (void *)&x, 0, 1) == 1) {
1684 printf("R");
1686 if (cli_write(&cli1, fnum2, 0, (void *)&x, 0, 1) == 1) {
1687 printf("W");
1691 printf("\n");
1692 cli_close(&cli1, fnum1);
1693 cli_close(&cli1, fnum2);
1696 cli_unlink(&cli1, fnames[f]);
1699 if (!close_connection(&cli1)) {
1700 correct = False;
1703 printf("finshed denytest2\n");
1704 return correct;
1708 test whether fnums and tids open on one VC are available on another (a major
1709 security hole)
1711 static BOOL run_fdpasstest(int dummy)
1713 static struct cli_state cli1, cli2, cli3;
1714 char *fname = "\\fdpass.tst";
1715 int fnum1;
1716 pstring buf;
1718 if (!open_connection(&cli1) || !open_connection(&cli2)) {
1719 return False;
1721 cli_sockopt(&cli1, sockops);
1722 cli_sockopt(&cli2, sockops);
1724 printf("starting fdpasstest\n");
1726 cli_unlink(&cli1, fname);
1728 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1729 if (fnum1 == -1) {
1730 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
1731 return False;
1734 if (cli_write(&cli1, fnum1, 0, "hello world\n", 0, 13) != 13) {
1735 printf("write failed (%s)\n", cli_errstr(&cli1));
1736 return False;
1739 cli3 = cli2;
1740 cli3.vuid = cli1.vuid;
1741 cli3.cnum = cli1.cnum;
1742 cli3.pid = cli1.pid;
1744 if (cli_read(&cli3, fnum1, buf, 0, 13) == 13) {
1745 printf("read succeeded! nasty security hole [%s]\n",
1746 buf);
1747 return False;
1750 cli_close(&cli1, fnum1);
1751 cli_unlink(&cli1, fname);
1753 close_connection(&cli1);
1754 close_connection(&cli2);
1756 printf("finished fdpasstest\n");
1757 return True;
1760 /*test multiple users over a single tcp connection*/
1761 /*test multiple users over a single tcp connection ~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1762 /*test multiple users over a single tcp connection*/
1765 typedef struct subtaboid {
1767 struct subtaboid *next;
1769 BOOL status;
1770 fstring name;
1771 fstring op_error;
1772 fstring sys_error;
1774 } SUBTABOID;
1776 typedef struct taboid {
1778 int owner, share, as_user;
1780 void *arg;
1782 SUBTABOID *subtaboids[2];
1784 } TABOID;
1786 static void init_TABOID(TABOID *t, int owner, int share, int as_user)
1788 memset( t, '\0', sizeof(*t));
1789 t->owner = owner;
1790 t->share = share;
1791 t->as_user = as_user;
1794 static BOOL run_vusertest_op_null(TABOID *t)
1796 return True;
1799 static BOOL run_vusertest_report_full(
1800 const char *operation,
1801 const char *sub_operation,
1802 BOOL failure,
1803 BOOL report,
1804 fstring *buf,
1805 TABOID *t)
1808 (*buf)[0] = '\0';
1810 snprintf(*buf,
1811 sizeof(*buf),
1812 "%8s[%s]:%10s file %10s user %10s(%5d). share %10s tid %5d owner %10s(%5d). fnum %5d was %5d (%s).",
1813 operation,
1814 failure?"FAILURE":"SUCCESS",
1815 sub_operation,
1816 vusers[t->owner].fname,
1817 vusers[t->as_user].username,
1818 /*vusers[t->as_user].vuid,*/
1819 vusers[t->as_user].cli.vuid,
1820 shares[t->share],
1821 /*vusers[t->owner].per_tid[t->share].tid,*/
1822 vusers[t->as_user].cli.cnum,
1823 vusers[t->owner].username,
1824 /*vusers[t->owner].vuid,*/
1825 vusers[t->owner].cli.vuid,
1826 vusers[t->as_user].per_tid[t->share].fnum[t->owner],
1827 vusers[t->as_user].per_tid[t->share].backup_fnum[t->owner],
1828 failure?cli_errstr(&vusers[t->as_user].cli):""
1831 if(report)
1832 printf("%s\n", *buf);
1834 return True;
1837 static BOOL run_vusertest_report(
1838 const char *operation,
1839 const char *sub_operation,
1840 BOOL failure,
1841 TABOID *t)
1844 fstring buf;
1846 return run_vusertest_report_full(operation, sub_operation, failure, True, &buf, t);
1849 static BOOL run_vusertest_report_failure(
1850 const char *operation,
1851 const char *sub_operation,
1852 TABOID *t)
1855 fstring buf;
1857 return run_vusertest_report_full(operation, sub_operation, True, True, &buf, t);
1860 static BOOL run_vusertest_report_success(
1861 const char *operation,
1862 const char *sub_operation,
1863 TABOID *t)
1866 fstring buf;
1868 return run_vusertest_report_full(operation, sub_operation, False, True, &buf, t);
1871 static BOOL run_vusertest_op_init(TABOID *t)
1874 int i, j;
1876 vusers[t->owner].fname[0] = '\0';
1878 vusers[t->owner].vuid = 0;
1879 vusers[t->owner].vuid_valid = False;
1880 vusers[t->owner].files_valid = False;
1882 for(i = 0; i < sizeof(vusers[t->owner].per_tid)/sizeof(vusers[t->owner].per_tid[0]); i++) {
1884 vusers[t->owner].per_tid[i].tid = 0;
1885 vusers[t->owner].per_tid[i].tid_valid = False;
1887 for(j = 0; j < sizeof(vusers[t->owner].per_tid[i].fnum)/sizeof(vusers[t->owner].per_tid[i].fnum[0]); j++) {
1889 vusers[t->owner].per_tid[i].fnum[j] = vusers[t->owner].per_tid[i].backup_fnum[j] = -1;
1893 return True;
1896 static BOOL run_vusertest_op_create(TABOID *t)
1899 BOOL should_work = (vusers[t->owner].per_tid[t->share].tid_valid && vusers[t->as_user].vuid_valid);
1901 snprintf(vusers[t->owner].fname, sizeof(vusers[t->owner].fname), "muserconn_%d", t->owner);
1903 vusers[t->as_user].cli.cnum = vusers[t->owner].per_tid[t->share].tid;
1905 if(!cli_unlink(&vusers[t->as_user].cli, vusers[t->owner].fname)) {
1907 run_vusertest_report_failure("CREATE", "unlink", t);
1909 return should_work?False:True;
1912 vusers[t->as_user].per_tid[t->share].fnum[t->owner] =
1913 cli_open(&vusers[t->as_user].cli, vusers[t->owner].fname, O_RDWR|O_CREAT, DENY_NONE);
1915 if (vusers[t->as_user].per_tid[t->share].fnum[t->owner] == -1) {
1917 run_vusertest_report_failure("CREATE", "create", t);
1919 return should_work?False:True;
1922 run_vusertest_report_success("CREATE", "created", t);
1924 vusers[t->as_user].files_valid = True; /*not true for all!*/
1926 return should_work?True:False;
1929 static BOOL run_vusertest_op_write(TABOID *t)
1932 BOOL should_work = (
1933 vusers[t->owner].per_tid[t->share].tid_valid &&
1934 vusers[t->as_user].vuid_valid &&
1935 vusers[t->as_user].files_valid
1938 fstring msg;
1939 int msglen;
1941 vusers[t->as_user].cli.cnum = vusers[t->owner].per_tid[t->share].tid;
1943 run_vusertest_report_full("WRITE", "write 2", False, False, &msg, t);
1945 msglen = strlen(msg)+1;
1947 if (cli_write(&vusers[t->as_user].cli,
1948 vusers[t->as_user].per_tid[t->share].fnum[t->owner], 0, (char *)&msglen, 0, sizeof(msglen)) != sizeof(msglen)) {
1950 run_vusertest_report_failure("WRITE", "write 1", t);
1952 return should_work?False:True;
1955 if (cli_write(&vusers[t->as_user].cli,
1956 vusers[t->as_user].per_tid[t->share].fnum[t->owner], 0, msg, sizeof(msglen), msglen) != msglen) {
1958 run_vusertest_report_failure("WRITE", "write 2", t);
1960 return should_work?False:True;
1963 run_vusertest_report_success("WRITE", "write", t);
1965 return should_work?True:False;
1968 static BOOL run_vusertest_op_create_and_write(TABOID *t)
1971 BOOL ret = True;
1973 if(!run_vusertest_op_create(t)) {
1975 ret = False;
1978 if(!run_vusertest_op_write(t)) {
1980 ret = False;
1983 return ret;
1986 static BOOL run_vusertest_op_openr(TABOID *t)
1989 BOOL should_work = (vusers[t->owner].per_tid[t->share].tid_valid && vusers[t->as_user].vuid_valid);
1991 vusers[t->as_user].cli.cnum = vusers[t->owner].per_tid[t->share].tid;
1993 vusers[t->as_user].per_tid[t->share].fnum[t->owner] =
1994 cli_open(&vusers[t->as_user].cli, vusers[t->owner].fname, O_RDONLY, DENY_NONE);
1996 if (vusers[t->as_user].per_tid[t->share].fnum[t->owner] == -1) {
1998 run_vusertest_report_failure("OPENR", "open", t);
2000 return should_work?False:True;
2003 run_vusertest_report_success("OPENR", "open", t);
2005 vusers[t->as_user].files_valid = True; /*not true for all!*/
2007 return should_work?True:False;
2010 static BOOL run_vusertest_op_read(TABOID *t)
2013 fstring msg;
2014 int msglen = 0;
2016 BOOL should_work = (
2017 vusers[t->owner].per_tid[t->share].tid_valid &&
2018 vusers[t->as_user].vuid_valid &&
2019 vusers[t->as_user].files_valid &&
2020 vusers[t->as_user].per_tid[t->share].fnum[t->owner] != -1
2023 vusers[t->as_user].cli.cnum = vusers[t->owner].per_tid[t->share].tid;
2025 if (cli_read(&vusers[t->as_user].cli,
2026 vusers[t->as_user].per_tid[t->share].fnum[t->owner], (char *)&msglen, 0, sizeof(msglen)) != sizeof(msglen)) {
2028 run_vusertest_report_failure("READ", "read 1", t);
2030 return should_work?False:True;
2033 if (cli_read(&vusers[t->as_user].cli,
2034 vusers[t->as_user].per_tid[t->share].fnum[t->owner], msg, sizeof(msglen), msglen) != msglen) {
2036 run_vusertest_report_failure("READ", "read 2", t);
2038 return should_work?False:True;
2041 run_vusertest_report_success("READ", "read", t);
2043 return should_work?True:False;
2046 static BOOL run_vusertest_op_openr_and_read(TABOID *t)
2049 BOOL ret = True;
2051 if(!run_vusertest_op_openr(t)) {
2053 ret = False;
2056 if(!run_vusertest_op_read(t)) {
2058 ret = False;
2061 return ret;
2064 static BOOL run_vusertest_op_backup_open_fids(TABOID *t)
2067 memcpy(vusers[t->as_user].per_tid[t->share].backup_fnum,
2068 vusers[t->as_user].per_tid[t->share].fnum,
2069 sizeof(vusers[t->as_user].per_tid[t->share].fnum));
2071 return True;
2074 static BOOL run_vusertest_op_close(TABOID *t)
2077 BOOL should_work = (
2079 vusers[t->owner].per_tid[t->share].tid_valid &&
2080 vusers[t->as_user].vuid_valid &&
2081 vusers[t->as_user].files_valid
2085 vusers[t->as_user].per_tid[t->share].fnum[t->owner] == -1 &&
2086 vusers[t->as_user].per_tid[t->share].backup_fnum[t->owner] == -1
2090 BOOL ret = should_work?True:False;
2092 vusers[t->as_user].cli.cnum = vusers[t->owner].per_tid[t->share].tid;
2094 if(vusers[t->as_user].per_tid[t->share].fnum[t->owner] != -1) {
2096 if(!cli_close(&vusers[t->as_user].cli, vusers[t->as_user].per_tid[t->share].fnum[t->owner])) {
2098 run_vusertest_report_failure("CLOSE", "close", t);
2100 ret = should_work?False:True;
2101 } else {
2103 run_vusertest_report_success("CLOSE", "close", t);
2106 vusers[t->as_user].per_tid[t->share].fnum[t->owner] = -1;
2109 if(vusers[t->as_user].per_tid[t->share].backup_fnum[t->owner] != -1 &&
2110 vusers[t->as_user].per_tid[t->share].backup_fnum[t->owner] != 0) {
2112 if(!cli_close(&vusers[t->as_user].cli, vusers[t->as_user].per_tid[t->share].backup_fnum[t->owner])) {
2114 run_vusertest_report_failure("CLOSE", "close backup", t);
2116 ret = should_work?False:True;
2118 } else {
2120 run_vusertest_report_success("CLOSE", "close backup", t);
2123 vusers[t->as_user].per_tid[t->share].backup_fnum[t->owner] = -1;
2126 return ret;
2129 static BOOL run_vusertest_op_tcon(TABOID *t)
2132 BOOL should_work = (vusers[t->as_user].vuid_valid);
2134 vusers[t->owner].per_tid[t->share].tid_valid = False;
2136 if (!cli_send_tconX(&vusers[t->as_user].cli,
2137 shares[t->share],
2138 "?????",
2139 vusers[t->as_user].password,
2140 strlen(vusers[t->as_user].password)+1)) {
2142 run_vusertest_report_failure("TCON", "tcon", t);
2144 return should_work?False:True;
2147 vusers[t->owner].per_tid[t->share].tid_valid = True;
2148 vusers[t->owner].per_tid[t->share].tid = vusers[t->as_user].cli.cnum;
2150 run_vusertest_report_success("TCON", "tcon", t);
2152 return should_work?True:False;
2155 static BOOL run_vusertest_op_tdis(TABOID *t)
2158 BOOL should_work = (vusers[t->owner].per_tid[t->share].tid_valid && vusers[t->as_user].vuid_valid);
2160 #if 0
2161 if(!vusers[t->owner].per_tid[t->share].tid_valid) {
2163 return True;
2165 #endif
2167 vusers[t->as_user].cli.cnum = vusers[t->owner].per_tid[t->share].tid;
2169 if(!cli_tdis(&vusers[t->as_user].cli)) {
2171 run_vusertest_report_failure("TDIS", "tdis", t);
2173 return should_work?False:True;
2176 run_vusertest_report_success("TDIS", "tdis", t);
2178 vusers[t->owner].per_tid[t->share].tid_valid = False;
2180 return should_work?True:False;
2183 static BOOL run_vusertest_op_ulogon(TABOID *t)
2186 vusers[t->owner].cli = *seed;
2188 vusers[t->owner].vuid_valid = False;
2190 if (!cli_session_setup(&vusers[t->owner].cli,
2191 vusers[t->owner].username,
2192 vusers[t->owner].password,
2193 strlen(vusers[t->owner].password),
2194 vusers[t->owner].password,
2195 strlen(vusers[t->owner].password),
2196 workgroup)) {
2199 run_vusertest_report_failure("ULOGON", "logon", t);
2201 return False;
2204 run_vusertest_report_success("ULOGON", "logon", t);
2206 vusers[t->owner].vuid_valid = True;
2207 vusers[t->owner].vuid = vusers[t->owner].cli.vuid;
2209 return True;
2212 static BOOL run_vusertest_op_ulogoff(TABOID *t)
2215 BOOL should_work = (vusers[t->owner].vuid_valid);
2217 #if 0
2218 if(!vusers[t->owner].vuid_valid) {
2220 return True;
2222 #endif
2224 if(!cli_ulogoff(&vusers[t->owner].cli)) {
2226 run_vusertest_report_failure("ULOGOFF", "logoff", t);
2228 return should_work?False:True;
2231 run_vusertest_report_success("ULOGOFF", "logoff", t);
2233 vusers[t->owner].vuid_valid = False;
2234 vusers[t->owner].files_valid = False;
2236 return should_work?True:False;
2239 /***********************************************************/
2240 /***********************************************************/
2242 static BOOL run_vusertest_owner_op(BOOL (*op)(TABOID *t))
2245 BOOL ret = True;
2247 int owner = 0;
2249 for(; owner < nusers; owner++) {
2251 TABOID t;
2252 init_TABOID(&t, owner, 0, owner);
2254 if(!op(&t)) {
2256 ret = False;
2257 printf("^^^^^^^^^^^^^^^^\n");
2261 return ret;
2264 static BOOL run_vusertest_owner_share_op(BOOL (*op)(TABOID *t))
2267 BOOL ret = True;
2269 int owner = 0;
2271 for(; owner < nusers; owner++) {
2273 int share = 0;
2275 for(; share < nshares; share++) {
2277 TABOID t;
2278 init_TABOID( &t, owner, share, owner);
2280 if(!op(&t)) {
2282 ret = False;
2283 printf("^^^^^^^^^^^^^^^^\n");
2288 return ret;
2291 static BOOL run_vusertest_owner_share_preop_user_op(
2292 BOOL (*preop)(TABOID *t),
2293 BOOL (*op)(TABOID *t),
2294 BOOL (*postop)(TABOID *t)
2298 BOOL ret = True;
2300 int owner = 0;
2302 for(; owner < nusers; owner++) {
2304 int share = 0;
2306 for(; share < nshares; share++) {
2308 TABOID t;
2309 init_TABOID( &t, owner, share, owner);
2311 if(!preop(&t)) {
2313 ret = False;
2314 printf("^^^^^^^^^^^^^^^^\n");
2317 for(t.as_user = 0; t.as_user < nusers; t.as_user++) {
2319 if(!op(&t)) {
2322 ret = False;
2323 printf("^^^^^^^^^^^^^^^^\n");
2327 t.as_user = owner;
2329 if(!postop(&t)) {
2331 ret = False;
2332 printf("^^^^^^^^^^^^^^^^\n");
2337 return ret;
2340 static BOOL run_vusertest_owner_share_user_preop_op(
2341 BOOL (*preop)(TABOID *t),
2342 BOOL (*op)(TABOID *t),
2343 BOOL (*postop)(TABOID *t)
2347 BOOL ret = True;
2349 int owner = 0;
2351 for(; owner < nusers; owner++) {
2353 int share = 0;
2355 for(; share < nshares; share++) {
2357 int as_user = 0;
2359 for(; as_user < nusers; as_user++) {
2361 TABOID t;
2362 init_TABOID( &t, owner, share, owner);
2364 if(!preop(&t)) {
2366 ret = False;
2368 printf("^^^^^^^^^^^^^^^^\n");
2371 t.as_user = as_user;
2373 if(!op(&t)) {
2376 ret = False;
2378 printf("^^^^^^^^^^^^^^^^\n");
2381 t.as_user = owner;
2383 if(!postop(&t)) {
2386 ret = False;
2388 printf("^^^^^^^^^^^^^^^^\n");
2394 return ret;
2397 /*user applies op*/
2399 #define VU_INIT (run_vusertest_owner_op(run_vusertest_op_init))
2401 #define VU_ULOGON (run_vusertest_owner_op(run_vusertest_op_ulogon))
2402 #define VU_ULOGOFF (run_vusertest_owner_op(run_vusertest_op_ulogoff))
2404 /*each user applies op to each of their shares*/
2406 #define VU_TCON (run_vusertest_owner_share_op(run_vusertest_op_tcon))
2407 #define VU_TDIS (run_vusertest_owner_share_op(run_vusertest_op_tdis))
2409 #define VU_CREATE_AND_WRITE (run_vusertest_owner_share_op(run_vusertest_op_create_and_write))
2410 #define VU_OPEN_AND_READ (run_vusertest_owner_share_op(run_vusertest_op_openr_and_read))
2411 #define VU_READ (run_vusertest_owner_share_op(run_vusertest_op_read))
2412 #define VU_FCLOSE (run_vusertest_owner_share_op(run_vusertest_op_close))
2413 #define VU_BACKUP_FIDS (run_vusertest_owner_share_op(run_vusertest_op_backup_open_fids))
2415 /*for u1 for u2 apply op as u2 on u1's tid*/
2417 #define VU_CROSS_READ (run_vusertest_owner_share_preop_user_op(run_vusertest_op_null,\
2418 run_vusertest_op_read,\
2419 run_vusertest_op_null))
2420 #define VU_CROSS_OPEN_AND_READ (run_vusertest_owner_share_preop_user_op(run_vusertest_op_null,\
2421 run_vusertest_op_openr_and_read,\
2422 run_vusertest_op_null))
2423 #define VU_CROSS_FCLOSE (run_vusertest_owner_share_preop_user_op(run_vusertest_op_null,\
2424 run_vusertest_op_close,\
2425 run_vusertest_op_null))
2427 #define VU_TCON_TDIS_OPEN_AND_READ (run_vusertest_owner_share_user_preop_op(run_vusertest_op_tcon,\
2428 run_vusertest_op_tdis,\
2429 run_vusertest_op_openr_and_read))
2434 Check relationship between:
2436 files open
2438 session logoff (Samba closes all files for vuid)
2440 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)
2442 1. can a user access a tid connected by another
2444 for u1 {
2445 for u2 {
2446 u2 opens file on u1's tid
2450 2. can one user disconnect a tid connected by another
2452 for u1 {
2453 for u2 {
2454 connect u1's tid as u1
2455 disconnect u1's tid as u2;
2456 open and read files as u1
2460 2a. does a disconnect by another invalidate the tid for the original connector
2462 3. does a disconnect invalidate a tid with no files open on it
2464 close files
2465 for u1 {
2466 disconnect u1's tid
2467 open and read files on u1's tid
2470 4. does a disconnect invalidate a tid with files open on it
2472 open files
2473 for u1 {
2474 disconnect u1's tid
2475 open and read files on u1's tid as u1
2478 5. does a disconnect invalidate files open on a tid.
2480 open files
2481 for u1 {
2482 disconnect u1's tid
2483 read files on u1's tid as u1
2486 6. can a user session exist with no tid and no open files
2488 close files
2489 for u1 {
2491 disconnect u1's tid
2494 for u1 {
2496 reconnect u1's tid
2500 7. does a logoff invalidate a tid with no files open on it
2502 close files
2503 for u1 {
2504 logoff u1
2505 open and read files on u1's tid
2508 close files
2509 for u1 {
2510 logon u1
2511 open and read files on u1's tid
2514 8. does a logoff invalidate a tid with files open on it
2516 open files
2517 for u1 {
2518 logoff u1
2519 open and read files on u1's tid
2522 for u1 {
2523 logon u1
2524 open and read files on u1's tid
2527 9. does a logoff invalidate a fid.
2529 open files
2530 for u1 {
2531 logoff u1
2532 read files on u1's tid
2535 for u1 {
2536 logon u1
2537 read files on u1's tid
2541 10. does a logoff invalidate a vuid.
2543 see 8
2545 11. can a connection survive close files, close tids, logoff users
2547 close files
2548 for u1 {
2549 disconnect u1's tids
2550 logoff u1
2553 for u1 {
2554 logon u1
2555 reconnect u1's tids
2556 open and read
2563 static BOOL run_vusertest(int dummy)
2565 BOOL ret = True;
2567 int testcnt = 0;
2569 seed = &vusers[0].cli;
2571 ZERO_STRUCTP(seed);
2573 printf("\nopen nbt connection\n");
2575 if (!open_nbt_connection(seed)) {
2577 return False;
2580 cli_sockopt(seed, sockops);
2582 printf("\nnegotiate protocol\n");
2584 /*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*/
2586 if (!cli_negprot(seed)) {
2587 printf("%s rejected the negprot (%s)\n",host, cli_errstr(seed));
2588 cli_shutdown(seed);
2589 return False;
2592 printf("\nnegotiate protocol again.\n");
2594 if (!cli_negprot(seed)) {
2596 printf("%s rejected a second negprot (%s)\n",host, cli_errstr(seed));
2598 printf("\nshutdown client\n");
2600 cli_shutdown(seed);
2602 ZERO_STRUCTP(seed);
2604 printf("\nopen new nbt session\n");
2606 if (!open_nbt_connection(seed)) {
2608 return False;
2611 cli_sockopt(seed, sockops);
2613 printf("\nre negotiate protocol\n");
2615 if (!cli_negprot(seed)) {
2616 printf("%s rejected the negprot (%s)\n",host, cli_errstr(seed));
2617 cli_shutdown(seed);
2618 return False;
2622 printf("starting vusertest with %d users and %d shares.\n", nusers, nshares);
2624 /***********************************************************/
2625 /***********************************************************/
2627 printf("\ninitialise\n\n");
2629 if(!VU_INIT) {
2631 printf("initialisation failed.\n");
2632 return False;
2635 printf("\nsetup sessions\n\n");
2637 if(!VU_ULOGON) {
2639 printf("setup sessions failed.\n");
2640 return False;
2643 printf("\nconnect to shares\n\n");
2645 if(!VU_TCON) {
2647 printf("connect to shares failed.\n");
2648 return False;
2651 /***********************************************************/
2652 /***********************************************************/
2656 char *test = "create and write files";
2657 BOOL tret = True;
2659 printf("\nTEST:%d %s\n\n", testcnt, test);
2661 testcnt++;
2663 if(!VU_CREATE_AND_WRITE) {
2665 printf("%s failed.\n", test);
2666 return False;
2669 if(!VU_FCLOSE) {
2671 tret = False;
2674 if(!tret) {
2676 printf("TEST FAILED.\n");
2677 ret = False;
2681 /***********************************************************/
2682 /***********************************************************/
2685 char *test = "can a user access a tid connected by another?";
2687 BOOL tret = True;
2689 printf("\nTEST:%d %s\n\n", testcnt, test);
2691 testcnt++;
2693 if(!VU_CROSS_OPEN_AND_READ) {
2695 tret = False;
2698 if(!VU_CROSS_FCLOSE) {
2700 tret = False;
2703 if(!tret) {
2705 printf("TEST FAILED.\n");
2706 ret = False;
2710 /***********************************************************/
2711 /***********************************************************/
2714 char *test = "can one user disconnect a tid connected by another.\n2a does disconnect by another invalidate tid for all?";
2716 BOOL tret = True;
2718 printf("\nTEST:%d %s\n\n", testcnt, test);
2720 testcnt++;
2722 if(!VU_TCON_TDIS_OPEN_AND_READ) {
2724 tret = False;
2727 if(!VU_CROSS_FCLOSE) {
2729 tret = False;
2732 if(!tret) {
2734 printf("TEST FAILED.\n");
2735 ret = False;
2739 /***********************************************************/
2740 /***********************************************************/
2744 char *test = "does a disconnect invalidate a tid with no files open on it?";
2746 BOOL tret = True;
2748 printf("\nTEST:%d %s\n\n", testcnt, test);
2750 testcnt++;
2752 if(!VU_FCLOSE) {
2754 tret = False;
2757 if(!VU_TDIS) {
2759 tret = False;
2762 if(!VU_OPEN_AND_READ) {
2764 tret = False;
2767 if(!VU_TCON) {
2769 tret = False;
2772 if(!tret) {
2774 printf("TEST FAILED.\n");
2775 ret = False;
2779 /***********************************************************/
2780 /***********************************************************/
2784 char *test = "does a disconnect invalidate a tid with files open on it?";
2786 BOOL tret = True;
2788 printf("\nTEST:%d %s\n\n", testcnt, test);
2790 testcnt++;
2792 if(!VU_FCLOSE) {
2794 tret = False;
2797 if(!VU_OPEN_AND_READ) {
2799 tret = False;
2802 if(!VU_TDIS) {
2804 tret = False;
2807 if(!VU_OPEN_AND_READ) {
2809 tret = False;
2812 if(!VU_TCON) {
2814 tret = False;
2817 if(!tret) {
2819 printf("TEST FAILED.\n");
2820 ret = False;
2824 /***********************************************************/
2825 /***********************************************************/
2829 char *test = "does a disconnect invalidate files open on a tid?";
2831 BOOL tret = True;
2833 printf("\nTEST:%d %s\n\n", testcnt, test);
2835 testcnt++;
2837 if(!VU_FCLOSE) {
2839 tret = False;
2842 if(!VU_OPEN_AND_READ) {
2844 tret = False;
2847 if(!VU_TDIS) {
2849 tret = False;
2852 if(!VU_READ) {
2854 tret = False;
2857 if(!VU_FCLOSE) {
2859 tret = False;
2862 if(!VU_TCON) {
2864 tret = False;
2867 if(!tret) {
2869 printf("TEST FAILED.\n");
2870 ret = False;
2874 /***********************************************************/
2875 /***********************************************************/
2879 char *test = "can a user session exist with no tid and no open files?";
2881 BOOL tret = True;
2883 printf("\nTEST:%d %s\n\n", testcnt, test);
2885 testcnt++;
2887 if(!VU_TDIS) {
2889 tret = False;
2892 if(!VU_TCON) {
2894 tret = False;
2897 if(!VU_OPEN_AND_READ) {
2899 tret = False;
2902 if(!tret) {
2904 printf("TEST FAILED.\n");
2905 ret = False;
2909 /***********************************************************/
2910 /***********************************************************/
2914 char *test = "does a logoff invalidate a tid with no files open on it?";
2916 BOOL tret = True;
2918 printf("\nTEST:%d %s\n\n", testcnt, test);
2920 testcnt++;
2922 if(!VU_FCLOSE) {
2924 tret = False;
2927 if(!VU_ULOGOFF) {
2929 tret = False;
2932 if(!VU_OPEN_AND_READ) {
2934 tret = False;
2937 if(!VU_FCLOSE) {
2939 tret = False;
2942 if(!VU_ULOGON) {
2944 tret = False;
2947 if(!VU_OPEN_AND_READ) {
2949 tret = False;
2952 if(!VU_FCLOSE) {
2954 tret = False;
2957 if(!VU_TDIS) {
2959 tret = False;
2962 if(!VU_TCON) {
2964 tret = False;
2967 if(!tret) {
2969 printf("TEST FAILED.\n");
2970 ret = False;
2974 /***********************************************************/
2975 /***********************************************************/
2978 char *test = "does a logoff invalidate a tid with files open on it?";
2980 BOOL tret = True;
2982 printf("\nTEST:%d %s\n\n", testcnt, test);
2984 testcnt++;
2986 if(!VU_OPEN_AND_READ) {
2988 tret = False;
2991 if(!VU_ULOGOFF) {
2993 tret = False;
2996 if(!VU_OPEN_AND_READ) {
2998 tret = False;
3001 if(!VU_ULOGON) {
3003 tret = False;
3006 if(!VU_OPEN_AND_READ) {
3008 tret = False;
3011 if(!VU_FCLOSE) {
3013 tret = False;
3016 if(!VU_TDIS) {
3018 tret = False;
3021 if(!VU_TCON) {
3023 tret = False;
3026 if(!tret) {
3028 printf("TEST FAILED.\n");
3029 ret = False;
3033 /***********************************************************/
3034 /***********************************************************/
3037 char *test = "does a logoff invalidate a fid?";
3038 BOOL tret = True;
3040 printf("\nTEST:%d %s\n\n", testcnt, test);
3042 testcnt++;
3044 if(!VU_OPEN_AND_READ) {
3046 tret = False;
3049 if(!VU_ULOGOFF) {
3051 tret = False;
3054 if(!VU_READ) {
3056 tret = False;
3059 if(!VU_ULOGON) {
3061 tret = False;
3064 if(!VU_READ) {
3066 tret = False;
3069 if(!VU_FCLOSE) {
3071 tret = False;
3074 if(!VU_TDIS) {
3076 tret = False;
3079 if(!VU_TCON) {
3081 tret = False;
3084 if(!tret) {
3086 printf("TEST FAILED.\n");
3087 ret = False;
3091 /***********************************************************/
3092 /***********************************************************/
3094 printf("\nTEST:%d does a logoff invalidate a vuid? see 8.\n\n", testcnt);
3096 testcnt++;
3098 /***********************************************************/
3099 /***********************************************************/
3102 char *test = "can a connection survive close files, disconnect tids, logoff users?";
3103 BOOL tret = True;
3105 printf("\nTEST:%d %s\n\n", testcnt, test);
3107 testcnt++;
3109 if(!VU_FCLOSE) {
3111 tret = False;
3114 if(!VU_TDIS) {
3116 tret = False;
3119 if(!VU_ULOGOFF) {
3121 tret = False;
3124 if(!VU_ULOGON) {
3126 tret = False;
3129 if(!VU_TCON) {
3131 tret = False;
3134 if(!VU_OPEN_AND_READ) {
3136 tret = False;
3139 if(!tret) {
3141 printf("TEST FAILED.\n");
3142 ret = False;
3146 /***********************************************************/
3147 /***********************************************************/
3150 char *test = "clean up.";
3151 BOOL tret = True;
3153 printf("\nTEST:%s\n\n", test);
3155 if(!VU_CROSS_FCLOSE) {
3157 tret = False;
3160 if(!VU_TDIS) {
3162 tret = False;
3165 if(!VU_ULOGOFF) {
3167 tret = False;
3170 if(!tret) {
3172 printf("TEST FAILED.\n");
3173 ret = False;
3177 cli_shutdown(seed);
3179 printf("finished vusertest.\n");
3180 return ret;
3184 This test checks that
3186 1) the server does not allow an unlink on a file that is open
3188 static BOOL run_unlinktest(int dummy)
3190 static struct cli_state cli;
3191 char *fname = "\\unlink.tst";
3192 int fnum;
3193 BOOL correct = True;
3195 if (!open_connection(&cli)) {
3196 return False;
3199 cli_sockopt(&cli, sockops);
3201 printf("starting unlink test\n");
3203 cli_unlink(&cli, fname);
3205 cli_setpid(&cli, 1);
3207 fnum = cli_open(&cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
3208 if (fnum == -1) {
3209 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
3210 return False;
3213 if (cli_unlink(&cli, fname)) {
3214 printf("error: server allowed unlink on an open file\n");
3215 correct = False;
3218 cli_close(&cli, fnum);
3219 cli_unlink(&cli, fname);
3221 if (!close_connection(&cli)) {
3222 correct = False;
3225 printf("unlink test finished\n");
3227 return correct;
3232 test how many open files this server supports on the one socket
3234 static BOOL run_maxfidtest(int dummy)
3236 static struct cli_state cli;
3237 char *template = "\\maxfid.%d.%d";
3238 fstring fname;
3239 int fnum;
3240 int retries=4;
3241 BOOL correct = True;
3243 cli = current_cli;
3245 if (retries <= 0) {
3246 printf("failed to connect\n");
3247 return False;
3250 cli_sockopt(&cli, sockops);
3252 fnum = 0;
3253 while (1) {
3254 slprintf(fname,sizeof(fname)-1,template, fnum,(int)getpid());
3255 if (cli_open(&cli, fname,
3256 O_RDWR|O_CREAT|O_TRUNC, DENY_NONE) ==
3257 -1) {
3258 printf("open of %s failed (%s)\n",
3259 fname, cli_errstr(&cli));
3260 printf("maximum fnum is %d\n", fnum);
3261 break;
3263 fnum++;
3264 if (fnum % 100 == 0) printf("%d\r", fnum);
3266 printf("%d\n", fnum);
3268 printf("cleaning up\n");
3269 while (fnum > 0) {
3270 fnum--;
3271 slprintf(fname,sizeof(fname)-1,template, fnum,(int)getpid());
3272 cli_close(&cli, fnum);
3273 if (!cli_unlink(&cli, fname)) {
3274 printf("unlink of %s failed (%s)\n",
3275 fname, cli_errstr(&cli));
3276 correct = False;
3280 printf("maxfid test finished\n");
3281 if (!close_connection(&cli)) {
3282 correct = False;
3284 return correct;
3287 /* generate a random buffer */
3288 static void rand_buf(char *buf, int len)
3290 while (len--) {
3291 *buf = (char)sys_random();
3292 buf++;
3296 /* send smb negprot commands, not reading the response */
3297 static BOOL run_negprot_nowait(int dummy)
3299 int i;
3300 static struct cli_state cli;
3301 BOOL correct = True;
3303 printf("starting negprot nowait test\n");
3305 if (!open_nbt_connection(&cli)) {
3306 return False;
3309 for (i=0;i<50000;i++) {
3310 cli_negprot_send(&cli);
3313 if (!close_connection(&cli)) {
3314 correct = False;
3317 printf("finished negprot nowait test\n");
3319 return correct;
3323 /* send random IPC commands */
3324 static BOOL run_randomipc(int dummy)
3326 char *rparam = NULL;
3327 char *rdata = NULL;
3328 int rdrcnt,rprcnt;
3329 pstring param;
3330 int api, param_len, i;
3331 static struct cli_state cli;
3332 BOOL correct = True;
3334 printf("starting random ipc test\n");
3336 if (!open_connection(&cli)) {
3337 return False;
3340 for (i=0;i<50000;i++) {
3341 api = sys_random() % 500;
3342 param_len = (sys_random() % 64);
3344 rand_buf(param, param_len);
3346 SSVAL(param,0,api);
3348 cli_api(&cli,
3349 param, param_len, 8,
3350 NULL, 0, BUFFER_SIZE,
3351 &rparam, &rprcnt,
3352 &rdata, &rdrcnt);
3355 if (!close_connection(&cli)) {
3356 correct = False;
3359 printf("finished random ipc test\n");
3361 return correct;
3366 static void browse_callback(const char *sname, uint32 stype,
3367 const char *comment, void *state)
3369 printf("\t%20.20s %08x %s\n", sname, stype, comment);
3375 This test checks the browse list code
3378 static BOOL run_browsetest(int dummy)
3380 static struct cli_state cli;
3381 BOOL correct = True;
3383 printf("starting browse test\n");
3385 if (!open_connection(&cli)) {
3386 return False;
3389 printf("domain list:\n");
3390 cli_NetServerEnum(&cli, cli.server_domain,
3391 SV_TYPE_DOMAIN_ENUM,
3392 browse_callback, NULL);
3394 printf("machine list:\n");
3395 cli_NetServerEnum(&cli, cli.server_domain,
3396 SV_TYPE_ALL,
3397 browse_callback, NULL);
3399 if (!close_connection(&cli)) {
3400 correct = False;
3403 printf("browse test finished\n");
3405 return correct;
3411 This checks how the getatr calls works
3413 static BOOL run_attrtest(int dummy)
3415 static struct cli_state cli;
3416 int fnum;
3417 time_t t, t2;
3418 char *fname = "\\attrib.tst";
3419 BOOL correct = True;
3421 printf("starting attrib test\n");
3423 if (!open_connection(&cli)) {
3424 return False;
3427 cli_unlink(&cli, fname);
3428 fnum = cli_open(&cli, fname,
3429 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
3430 cli_close(&cli, fnum);
3431 if (!cli_getatr(&cli, fname, NULL, NULL, &t)) {
3432 printf("getatr failed (%s)\n", cli_errstr(&cli));
3433 correct = False;
3436 if (abs(t - time(NULL)) > 2) {
3437 printf("ERROR: SMBgetatr bug. time is %s",
3438 ctime(&t));
3439 t = time(NULL);
3440 correct = True;
3443 t2 = t-60*60*24; /* 1 day ago */
3445 if (!cli_setatr(&cli, fname, 0, t2)) {
3446 printf("setatr failed (%s)\n", cli_errstr(&cli));
3447 correct = True;
3450 if (!cli_getatr(&cli, fname, NULL, NULL, &t)) {
3451 printf("getatr failed (%s)\n", cli_errstr(&cli));
3452 correct = True;
3455 if (t != t2) {
3456 printf("ERROR: getatr/setatr bug. times are\n%s",
3457 ctime(&t));
3458 printf("%s", ctime(&t2));
3459 correct = True;
3462 cli_unlink(&cli, fname);
3464 if (!close_connection(&cli)) {
3465 correct = False;
3468 printf("attrib test finished\n");
3470 return correct;
3475 This checks a couple of trans2 calls
3477 static BOOL run_trans2test(int dummy)
3479 static struct cli_state cli;
3480 int fnum;
3481 size_t size;
3482 time_t c_time, a_time, m_time, w_time, m_time2;
3483 char *fname = "\\trans2.tst";
3484 char *dname = "\\trans2";
3485 char *fname2 = "\\trans2\\trans2.tst";
3486 BOOL correct = True;
3488 printf("starting trans2 test\n");
3490 if (!open_connection(&cli)) {
3491 return False;
3494 cli_unlink(&cli, fname);
3495 fnum = cli_open(&cli, fname,
3496 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
3497 if (!cli_qfileinfo(&cli, fnum, NULL, &size, &c_time, &a_time, &m_time,
3498 NULL, NULL)) {
3499 printf("ERROR: qfileinfo failed (%s)\n", cli_errstr(&cli));
3500 correct = False;
3502 cli_close(&cli, fnum);
3504 sleep(2);
3506 cli_unlink(&cli, fname);
3507 fnum = cli_open(&cli, fname,
3508 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
3509 if (fnum == -1) {
3510 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
3511 return False;
3513 cli_close(&cli, fnum);
3515 if (!cli_qpathinfo(&cli, fname, &c_time, &a_time, &m_time, &size, NULL)) {
3516 printf("ERROR: qpathinfo failed (%s)\n", cli_errstr(&cli));
3517 correct = False;
3518 } else {
3519 if (c_time != m_time) {
3520 printf("create time=%s", ctime(&c_time));
3521 printf("modify time=%s", ctime(&m_time));
3522 printf("This system appears to have sticky create times\n");
3523 correct = False;
3525 if (a_time % (60*60) == 0) {
3526 printf("access time=%s", ctime(&a_time));
3527 printf("This system appears to set a midnight access time\n");
3528 correct = False;
3531 if (abs(m_time - time(NULL)) > 60*60*24*7) {
3532 printf("ERROR: totally incorrect times - maybe word reversed?\n");
3533 correct = False;
3538 cli_unlink(&cli, fname);
3539 fnum = cli_open(&cli, fname,
3540 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
3541 cli_close(&cli, fnum);
3542 if (!cli_qpathinfo2(&cli, fname, &c_time, &a_time, &m_time,
3543 &w_time, &size, NULL, NULL)) {
3544 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
3545 correct = False;
3546 } else {
3547 if (w_time < 60*60*24*2) {
3548 printf("write time=%s", ctime(&w_time));
3549 printf("This system appears to set a initial 0 write time\n");
3550 correct = False;
3554 cli_unlink(&cli, fname);
3557 /* check if the server updates the directory modification time
3558 when creating a new file */
3559 if (!cli_mkdir(&cli, dname)) {
3560 printf("ERROR: mkdir failed (%s)\n", cli_errstr(&cli));
3561 correct = False;
3563 sleep(3);
3564 if (!cli_qpathinfo2(&cli, "\\trans2\\", &c_time, &a_time, &m_time,
3565 &w_time, &size, NULL, NULL)) {
3566 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
3567 correct = False;
3570 fnum = cli_open(&cli, fname2,
3571 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
3572 cli_write(&cli, fnum, 0, (char *)&fnum, 0, sizeof(fnum));
3573 cli_close(&cli, fnum);
3574 if (!cli_qpathinfo2(&cli, "\\trans2\\", &c_time, &a_time, &m_time2,
3575 &w_time, &size, NULL, NULL)) {
3576 printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
3577 correct = False;
3578 } else {
3579 if (m_time2 == m_time) {
3580 printf("This system does not update directory modification times\n");
3581 correct = False;
3584 cli_unlink(&cli, fname2);
3585 cli_rmdir(&cli, dname);
3587 if (!close_connection(&cli)) {
3588 correct = False;
3591 printf("trans2 test finished\n");
3593 return correct;
3597 This checks new W2K calls.
3600 static BOOL new_trans(struct cli_state *pcli, int fnum, int level)
3602 char buf[4096];
3603 BOOL correct = True;
3605 memset(buf, 0xff, sizeof(buf));
3607 if (!cli_qfileinfo_test(pcli, fnum, level, buf)) {
3608 printf("ERROR: qfileinfo (%d) failed (%s)\n", level, cli_errstr(pcli));
3609 correct = False;
3610 } else {
3611 printf("qfileinfo: level %d\n", level);
3612 dump_data(0, buf, 256);
3613 printf("\n");
3615 return correct;
3618 /****************************************************************************
3619 Set or clear the delete on close flag.
3620 ****************************************************************************/
3622 int cli_setfileinfo_test(struct cli_state *cli, int fnum, int level, char *data, int data_len)
3624 int param_len = 6;
3625 uint16 setup = TRANSACT2_SETFILEINFO;
3626 pstring param;
3627 char *rparam=NULL, *rdata=NULL;
3629 memset(param, 0, param_len);
3630 SSVAL(param,0,fnum);
3631 SSVAL(param,2,level);
3633 if (!cli_send_trans(cli, SMBtrans2,
3634 NULL, /* name */
3635 -1, 0, /* fid, flags */
3636 &setup, 1, 0, /* setup, length, max */
3637 param, param_len, 2, /* param, length, max */
3638 data, data_len, cli->max_xmit /* data, length, max */
3639 )) {
3640 return False;
3643 if (!cli_receive_trans(cli, SMBtrans2,
3644 &rparam, &param_len,
3645 &rdata, &data_len)) {
3646 return False;
3649 if (rdata) free(rdata);
3650 if (rparam) free(rparam);
3652 return True;
3655 static BOOL run_w2ktest(int dummy)
3657 static struct cli_state cli;
3658 int fnum;
3659 char *fname = "\\w2ktest\\w2k.tst";
3660 char *fname1 = "\\w2ktest\\w2k.dir";
3661 int level;
3662 char data;
3663 BOOL correct = True;
3665 printf("starting w2k test\n");
3667 if (!open_connection(&cli)) {
3668 return False;
3671 fnum = cli_open(&cli, fname,
3672 O_RDWR | O_CREAT , DENY_NONE);
3674 for (level = 1004; level < 1040; level++) {
3675 new_trans(&cli, fnum, level);
3678 cli_close(&cli, fnum);
3679 cli_unlink(&cli, fname);
3681 /* Check the strange 1013 setinfo call. */
3682 cli_mkdir(&cli, fname1);
3683 fnum = cli_nt_create_full( &cli, fname1, 0x60080, 0, 7,
3684 1, 0);
3686 data = 1;
3687 if (!cli_setfileinfo_test( &cli, fnum, 1013, &data, 1)) {
3688 printf("setfileinfo test 1 failed with %s\n", cli_errstr(&cli));
3690 data = 0;
3691 if (!cli_setfileinfo_test( &cli, fnum, 1013, &data, 1)) {
3692 printf("setfileinfo test 2 failed with %s\n", cli_errstr(&cli));
3695 cli_close(&cli, fnum);
3696 cli_rmdir(&cli, fname1);
3698 fnum = cli_open(&cli, fname, O_RDWR | O_CREAT , DENY_NONE);
3700 cli_write(&cli, fnum, 0, (char *)&data, 0, sizeof(data));
3701 cli_close(&cli, fnum);
3702 cli_ulogoff(&cli);
3704 fnum = cli_open(&cli, fname, O_RDWR , DENY_NONE);
3705 if (cli_read(&cli, fnum, &data, 0, 1) != 1) {
3706 printf("x test 2 failed with %s\n", cli_errstr(&cli));
3708 cli_close(&cli, fnum);
3709 cli_unlink(&cli, fname);
3711 if (!close_connection(&cli)) {
3712 correct = False;
3715 printf("w2k test finished\n");
3717 return correct;
3722 this is a harness for some oplock tests
3724 static BOOL run_oplock1(int dummy)
3726 static struct cli_state cli1;
3727 char *fname = "\\lockt1.lck";
3728 int fnum1;
3729 BOOL correct = True;
3731 printf("starting oplock test 1\n");
3733 if (!open_connection(&cli1)) {
3734 return False;
3737 cli_unlink(&cli1, fname);
3739 cli_sockopt(&cli1, sockops);
3741 cli1.use_oplocks = True;
3743 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
3744 if (fnum1 == -1) {
3745 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
3746 return False;
3749 cli1.use_oplocks = False;
3751 cli_unlink(&cli1, fname);
3752 cli_unlink(&cli1, fname);
3754 if (!cli_close(&cli1, fnum1)) {
3755 printf("close2 failed (%s)\n", cli_errstr(&cli1));
3756 return False;
3759 if (!cli_unlink(&cli1, fname)) {
3760 printf("unlink failed (%s)\n", cli_errstr(&cli1));
3761 return False;
3764 if (!close_connection(&cli1)) {
3765 correct = False;
3768 printf("finished oplock test 1\n");
3770 return correct;
3773 static BOOL run_oplock2(int dummy)
3775 static struct cli_state cli1, cli2;
3776 char *fname = "\\lockt2.lck";
3777 int fnum1, fnum2;
3778 int saved_use_oplocks = use_oplocks;
3779 char buf[4];
3780 BOOL correct = True;
3781 volatile BOOL *shared_correct;
3783 shared_correct = (volatile BOOL *)shm_setup(sizeof(BOOL));
3784 *shared_correct = True;
3786 use_level_II_oplocks = True;
3787 use_oplocks = True;
3789 printf("starting oplock test 2\n");
3791 if (!open_connection(&cli1)) {
3792 use_level_II_oplocks = False;
3793 use_oplocks = saved_use_oplocks;
3794 return False;
3797 cli1.use_oplocks = True;
3798 cli1.use_level_II_oplocks = True;
3800 if (!open_connection(&cli2)) {
3801 use_level_II_oplocks = False;
3802 use_oplocks = saved_use_oplocks;
3803 return False;
3806 cli2.use_oplocks = True;
3807 cli2.use_level_II_oplocks = True;
3809 cli_unlink(&cli1, fname);
3811 cli_sockopt(&cli1, sockops);
3812 cli_sockopt(&cli2, sockops);
3814 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
3815 if (fnum1 == -1) {
3816 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
3817 return False;
3820 /* Don't need the globals any more. */
3821 use_level_II_oplocks = False;
3822 use_oplocks = saved_use_oplocks;
3824 if (fork() == 0) {
3825 /* Child code */
3826 fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
3827 if (fnum2 == -1) {
3828 printf("second open of %s failed (%s)\n", fname, cli_errstr(&cli1));
3829 *shared_correct = False;
3830 exit(0);
3833 sleep(2);
3835 if (!cli_close(&cli2, fnum2)) {
3836 printf("close2 failed (%s)\n", cli_errstr(&cli1));
3837 *shared_correct = False;
3840 exit(0);
3843 sleep(2);
3845 /* Ensure cli1 processes the break. */
3847 if (cli_read(&cli1, fnum1, buf, 0, 4) != 4) {
3848 printf("read on fnum1 failed (%s)\n", cli_errstr(&cli1));
3849 correct = False;
3852 /* Should now be at level II. */
3853 /* Test if sending a write locks causes a break to none. */
3855 if (!cli_lock(&cli1, fnum1, 0, 4, 0, READ_LOCK)) {
3856 printf("lock failed (%s)\n", cli_errstr(&cli1));
3857 correct = False;
3860 cli_unlock(&cli1, fnum1, 0, 4);
3862 sleep(2);
3864 if (!cli_lock(&cli1, fnum1, 0, 4, 0, WRITE_LOCK)) {
3865 printf("lock failed (%s)\n", cli_errstr(&cli1));
3866 correct = False;
3869 cli_unlock(&cli1, fnum1, 0, 4);
3871 sleep(2);
3873 cli_read(&cli1, fnum1, buf, 0, 4);
3875 #if 0
3876 if (cli_write(&cli1, fnum1, 0, buf, 0, 4) != 4) {
3877 printf("write on fnum1 failed (%s)\n", cli_errstr(&cli1));
3878 correct = False;
3880 #endif
3882 if (!cli_close(&cli1, fnum1)) {
3883 printf("close1 failed (%s)\n", cli_errstr(&cli1));
3884 correct = False;
3887 sleep(4);
3889 if (!cli_unlink(&cli1, fname)) {
3890 printf("unlink failed (%s)\n", cli_errstr(&cli1));
3891 correct = False;
3894 if (!close_connection(&cli1)) {
3895 correct = False;
3898 if (!*shared_correct) {
3899 correct = False;
3902 printf("finished oplock test 2\n");
3904 return correct;
3909 Test delete on close semantics.
3911 static BOOL run_deletetest(int dummy)
3913 static struct cli_state cli1;
3914 static struct cli_state cli2;
3915 char *fname = "\\delete.file";
3916 int fnum1, fnum2;
3917 BOOL correct = True;
3919 printf("starting delete test\n");
3921 if (!open_connection(&cli1)) {
3922 return False;
3925 cli_sockopt(&cli1, sockops);
3927 /* Test 1 - this should *NOT* delete the file on close. */
3929 cli_setatr(&cli1, fname, 0, 0);
3930 cli_unlink(&cli1, fname);
3932 fnum1 = cli_nt_create_full(&cli1, fname, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
3933 FILE_SHARE_DELETE, FILE_OVERWRITE_IF, DELETE_ON_CLOSE_FLAG);
3935 if (fnum1 == -1) {
3936 printf("[1] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
3937 return False;
3940 if (!cli_close(&cli1, fnum1)) {
3941 printf("[1] close failed (%s)\n", cli_errstr(&cli1));
3942 return False;
3945 fnum1 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
3946 if (fnum1 == -1) {
3947 printf("[1] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
3948 return False;
3951 if (!cli_close(&cli1, fnum1)) {
3952 printf("[1] close failed (%s)\n", cli_errstr(&cli1));
3953 return False;
3956 printf("first delete on close test succeeded.\n");
3958 /* Test 2 - this should delete the file on close. */
3960 cli_setatr(&cli1, fname, 0, 0);
3961 cli_unlink(&cli1, fname);
3963 fnum1 = cli_nt_create_full(&cli1, fname, GENERIC_ALL_ACCESS,
3964 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0);
3966 if (fnum1 == -1) {
3967 printf("[2] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
3968 return False;
3971 if (!cli_nt_delete_on_close(&cli1, fnum1, True)) {
3972 printf("[2] setting delete_on_close failed (%s)\n", cli_errstr(&cli1));
3973 return False;
3976 if (!cli_close(&cli1, fnum1)) {
3977 printf("[2] close failed (%s)\n", cli_errstr(&cli1));
3978 return False;
3981 fnum1 = cli_open(&cli1, fname, O_RDONLY, DENY_NONE);
3982 if (fnum1 != -1) {
3983 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
3984 if (!cli_close(&cli1, fnum1)) {
3985 printf("[2] close failed (%s)\n", cli_errstr(&cli1));
3986 correct = False;
3988 cli_unlink(&cli1, fname);
3989 } else
3990 printf("second delete on close test succeeded.\n");
3993 /* Test 3 - ... */
3994 cli_setatr(&cli1, fname, 0, 0);
3995 cli_unlink(&cli1, fname);
3997 fnum1 = cli_nt_create_full(&cli1, fname, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
3998 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0);
4000 if (fnum1 == -1) {
4001 printf("[3] open - 1 of %s failed (%s)\n", fname, cli_errstr(&cli1));
4002 return False;
4005 /* This should fail with a sharing violation - open for delete is only compatible
4006 with SHARE_DELETE. */
4008 fnum2 = cli_nt_create_full(&cli1, fname, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4009 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0);
4011 if (fnum2 != -1) {
4012 printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
4013 return False;
4016 /* This should succeed. */
4018 fnum2 = cli_nt_create_full(&cli1, fname, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4019 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0);
4021 if (fnum2 == -1) {
4022 printf("[3] open - 2 of %s failed (%s)\n", fname, cli_errstr(&cli1));
4023 return False;
4026 if (!cli_nt_delete_on_close(&cli1, fnum1, True)) {
4027 printf("[3] setting delete_on_close failed (%s)\n", cli_errstr(&cli1));
4028 return False;
4031 if (!cli_close(&cli1, fnum1)) {
4032 printf("[3] close 1 failed (%s)\n", cli_errstr(&cli1));
4033 return False;
4036 if (!cli_close(&cli1, fnum2)) {
4037 printf("[3] close 2 failed (%s)\n", cli_errstr(&cli1));
4038 return False;
4041 /* This should fail - file should no longer be there. */
4043 fnum1 = cli_open(&cli1, fname, O_RDONLY, DENY_NONE);
4044 if (fnum1 != -1) {
4045 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
4046 if (!cli_close(&cli1, fnum1)) {
4047 printf("[3] close failed (%s)\n", cli_errstr(&cli1));
4049 cli_unlink(&cli1, fname);
4050 correct = False;
4051 } else
4052 printf("third delete on close test succeeded.\n");
4054 /* Test 4 ... */
4055 cli_setatr(&cli1, fname, 0, 0);
4056 cli_unlink(&cli1, fname);
4058 fnum1 = cli_nt_create_full(&cli1, fname, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4059 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0);
4061 if (fnum1 == -1) {
4062 printf("[4] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
4063 return False;
4066 /* This should succeed. */
4067 fnum2 = cli_nt_create_full(&cli1, fname, GENERIC_READ_ACCESS,
4068 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0);
4069 if (fnum2 == -1) {
4070 printf("[4] open - 2 of %s failed (%s)\n", fname, cli_errstr(&cli1));
4071 return False;
4074 if (!cli_close(&cli1, fnum2)) {
4075 printf("[4] close - 1 failed (%s)\n", cli_errstr(&cli1));
4076 return False;
4079 if (!cli_nt_delete_on_close(&cli1, fnum1, True)) {
4080 printf("[4] setting delete_on_close failed (%s)\n", cli_errstr(&cli1));
4081 return False;
4084 /* This should fail - no more opens once delete on close set. */
4085 fnum2 = cli_nt_create_full(&cli1, fname, GENERIC_READ_ACCESS,
4086 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0);
4087 if (fnum2 != -1) {
4088 printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
4089 return False;
4090 } else
4091 printf("fourth delete on close test succeeded.\n");
4093 if (!cli_close(&cli1, fnum1)) {
4094 printf("[4] close - 2 failed (%s)\n", cli_errstr(&cli1));
4095 return False;
4098 /* Test 5 ... */
4099 cli_setatr(&cli1, fname, 0, 0);
4100 cli_unlink(&cli1, fname);
4102 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT, DENY_NONE);
4103 if (fnum1 == -1) {
4104 printf("[5] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
4105 return False;
4108 /* This should fail - only allowed on NT opens with DELETE access. */
4110 if (cli_nt_delete_on_close(&cli1, fnum1, True)) {
4111 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
4112 return False;
4115 if (!cli_close(&cli1, fnum1)) {
4116 printf("[5] close - 2 failed (%s)\n", cli_errstr(&cli1));
4117 return False;
4120 printf("fifth delete on close test succeeded.\n");
4122 /* Test 6 ... */
4123 cli_setatr(&cli1, fname, 0, 0);
4124 cli_unlink(&cli1, fname);
4126 fnum1 = cli_nt_create_full(&cli1, fname, FILE_READ_DATA|FILE_WRITE_DATA,
4127 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4128 FILE_OVERWRITE_IF, 0);
4130 if (fnum1 == -1) {
4131 printf("[6] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
4132 return False;
4135 /* This should fail - only allowed on NT opens with DELETE access. */
4137 if (cli_nt_delete_on_close(&cli1, fnum1, True)) {
4138 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
4139 return False;
4142 if (!cli_close(&cli1, fnum1)) {
4143 printf("[6] close - 2 failed (%s)\n", cli_errstr(&cli1));
4144 return False;
4147 printf("sixth delete on close test succeeded.\n");
4149 /* Test 7 ... */
4150 cli_setatr(&cli1, fname, 0, 0);
4151 cli_unlink(&cli1, fname);
4153 fnum1 = cli_nt_create_full(&cli1, fname, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4154 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF, 0);
4156 if (fnum1 == -1) {
4157 printf("[7] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
4158 return False;
4161 if (!cli_nt_delete_on_close(&cli1, fnum1, True)) {
4162 printf("[7] setting delete_on_close on file failed !\n");
4163 return False;
4166 if (!cli_nt_delete_on_close(&cli1, fnum1, False)) {
4167 printf("[7] unsetting delete_on_close on file failed !\n");
4168 return False;
4171 if (!cli_close(&cli1, fnum1)) {
4172 printf("[7] close - 2 failed (%s)\n", cli_errstr(&cli1));
4173 return False;
4176 /* This next open should succeed - we reset the flag. */
4178 fnum1 = cli_open(&cli1, fname, O_RDONLY, DENY_NONE);
4179 if (fnum1 == -1) {
4180 printf("[5] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
4181 return False;
4184 if (!cli_close(&cli1, fnum1)) {
4185 printf("[7] close - 2 failed (%s)\n", cli_errstr(&cli1));
4186 return False;
4189 printf("seventh delete on close test succeeded.\n");
4191 /* Test 7 ... */
4192 cli_setatr(&cli1, fname, 0, 0);
4193 cli_unlink(&cli1, fname);
4195 if (!open_connection(&cli2)) {
4196 printf("[8] failed to open second connection.\n");
4197 return False;
4200 cli_sockopt(&cli1, sockops);
4202 fnum1 = cli_nt_create_full(&cli1, fname, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4203 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0);
4205 if (fnum1 == -1) {
4206 printf("[8] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
4207 return False;
4210 fnum2 = cli_nt_create_full(&cli2, fname, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4211 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0);
4213 if (fnum2 == -1) {
4214 printf("[8] open of %s failed (%s)\n", fname, cli_errstr(&cli1));
4215 return False;
4218 if (!cli_nt_delete_on_close(&cli1, fnum1, True)) {
4219 printf("[8] setting delete_on_close on file failed !\n");
4220 return False;
4223 if (!cli_close(&cli1, fnum1)) {
4224 printf("[8] close - 1 failed (%s)\n", cli_errstr(&cli1));
4225 return False;
4228 if (!cli_close(&cli2, fnum2)) {
4229 printf("[8] close - 2 failed (%s)\n", cli_errstr(&cli2));
4230 return False;
4233 /* This should fail.. */
4234 fnum1 = cli_open(&cli1, fname, O_RDONLY, DENY_NONE);
4235 if (fnum1 != -1) {
4236 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
4237 if (!cli_close(&cli1, fnum1)) {
4238 printf("[8] close failed (%s)\n", cli_errstr(&cli1));
4240 cli_unlink(&cli1, fname);
4241 correct = False;
4242 } else
4243 printf("eighth delete on close test succeeded.\n");
4245 printf("finished delete test\n");
4247 cli_setatr(&cli1, fname, 0, 0);
4248 cli_unlink(&cli1, fname);
4250 if (!close_connection(&cli1)) {
4251 correct = False;
4253 if (!close_connection(&cli2)) {
4254 correct = False;
4256 return correct;
4260 Test open mode returns on read-only files.
4262 static BOOL run_opentest(int dummy)
4264 static struct cli_state cli1;
4265 char *fname = "\\readonly.file";
4266 int fnum1, fnum2;
4267 uint8 eclass;
4268 uint32 errnum;
4269 char buf[20];
4270 size_t fsize;
4271 BOOL correct = True;
4273 printf("starting open test\n");
4275 if (!open_connection(&cli1)) {
4276 return False;
4279 cli_setatr(&cli1, fname, 0, 0);
4280 cli_unlink(&cli1, fname);
4282 cli_sockopt(&cli1, sockops);
4284 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
4285 if (fnum1 == -1) {
4286 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
4287 return False;
4290 if (!cli_close(&cli1, fnum1)) {
4291 printf("close2 failed (%s)\n", cli_errstr(&cli1));
4292 return False;
4295 if (!cli_setatr(&cli1, fname, aRONLY, 0)) {
4296 printf("cli_setatr failed (%s)\n", cli_errstr(&cli1));
4297 return False;
4300 fnum1 = cli_open(&cli1, fname, O_RDONLY, DENY_WRITE);
4301 if (fnum1 == -1) {
4302 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
4303 return False;
4306 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
4307 fnum2 = cli_open(&cli1, fname, O_RDWR, DENY_ALL);
4309 cli_dos_error( &cli1, &eclass, &errnum);
4311 if (eclass != ERRDOS || errnum != ERRnoaccess) {
4312 printf("wrong error code (%x,%x) = %s\n", (unsigned int)eclass,
4313 (unsigned int)errnum, cli_errstr(&cli1) );
4314 correct = False;
4315 } else {
4316 printf("correct error code ERRDOS/ERRnoaccess returned\n");
4320 printf("finished open test 1\n");
4322 cli_close(&cli1, fnum1);
4324 /* Now try not readonly and ensure ERRbadshare is returned. */
4326 cli_setatr(&cli1, fname, 0, 0);
4328 fnum1 = cli_open(&cli1, fname, O_RDONLY, DENY_WRITE);
4329 if (fnum1 == -1) {
4330 printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
4331 return False;
4334 /* This will fail - but the error should be ERRshare. */
4335 fnum2 = cli_open(&cli1, fname, O_RDWR, DENY_ALL);
4337 cli_dos_error( &cli1, &eclass, &errnum);
4339 if (eclass != ERRDOS || errnum != ERRbadshare) {
4340 printf("wrong error code (%x,%x) = %s\n", (unsigned int)eclass,
4341 (unsigned int)errnum, cli_errstr(&cli1) );
4342 correct = False;
4343 } else {
4344 printf("correct error code ERRDOS/ERRbadshare returned\n");
4347 if (!cli_close(&cli1, fnum1)) {
4348 printf("close2 failed (%s)\n", cli_errstr(&cli1));
4349 return False;
4352 cli_unlink(&cli1, fname);
4354 printf("finished open test 2\n");
4356 /* Test truncate open disposition on file opened for read. */
4358 fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
4359 if (fnum1 == -1) {
4360 printf("(3) open (1) of %s failed (%s)\n", fname, cli_errstr(&cli1));
4361 return False;
4364 /* write 20 bytes. */
4366 memset(buf, '\0', 20);
4368 if (cli_write(&cli1, fnum1, 0, buf, 0, 20) != 20) {
4369 printf("write failed (%s)\n", cli_errstr(&cli1));
4370 correct = False;
4373 if (!cli_close(&cli1, fnum1)) {
4374 printf("(3) close1 failed (%s)\n", cli_errstr(&cli1));
4375 return False;
4378 /* Ensure size == 20. */
4379 if (!cli_getatr(&cli1, fname, NULL, &fsize, NULL)) {
4380 printf("(3) getatr failed (%s)\n", cli_errstr(&cli1));
4381 return False;
4384 if (fsize != 20) {
4385 printf("(3) file size != 20\n");
4386 return False;
4389 /* Now test if we can truncate a file opened for readonly. */
4391 fnum1 = cli_open(&cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE);
4392 if (fnum1 == -1) {
4393 printf("(3) open (2) of %s failed (%s)\n", fname, cli_errstr(&cli1));
4394 return False;
4397 if (!cli_close(&cli1, fnum1)) {
4398 printf("close2 failed (%s)\n", cli_errstr(&cli1));
4399 return False;
4402 /* Ensure size == 0. */
4403 if (!cli_getatr(&cli1, fname, NULL, &fsize, NULL)) {
4404 printf("(3) getatr failed (%s)\n", cli_errstr(&cli1));
4405 return False;
4408 if (fsize != 0) {
4409 printf("(3) file size != 0\n");
4410 return False;
4412 printf("finished open test 3\n");
4414 cli_unlink(&cli1, fname);
4417 printf("testing ctemp\n");
4419 char *tmp_path;
4420 fnum1 = cli_ctemp(&cli1, "\\", &tmp_path);
4421 if (fnum1 == -1) {
4422 printf("ctemp failed (%s)\n", cli_errstr(&cli1));
4423 return False;
4425 printf("ctemp gave path %s\n", tmp_path);
4426 cli_close(&cli1, fnum1);
4427 cli_unlink(&cli1, tmp_path);
4430 if (!close_connection(&cli1)) {
4431 correct = False;
4434 return correct;
4437 static void list_fn(file_info *finfo, const char *name, void *state)
4443 test directory listing speed
4445 static BOOL run_dirtest(int dummy)
4447 int i;
4448 static struct cli_state cli;
4449 int fnum;
4450 double t1;
4451 BOOL correct = True;
4453 printf("starting directory test\n");
4455 if (!open_connection(&cli)) {
4456 return False;
4459 cli_sockopt(&cli, sockops);
4461 srandom(0);
4462 for (i=0;i<numops;i++) {
4463 fstring fname;
4464 slprintf(fname, sizeof(fname), "%x", (int)random());
4465 fnum = cli_open(&cli, fname, O_RDWR|O_CREAT, DENY_NONE);
4466 if (fnum == -1) {
4467 fprintf(stderr,"Failed to open %s\n", fname);
4468 return False;
4470 cli_close(&cli, fnum);
4473 t1 = end_timer();
4475 printf("Matched %d\n", cli_list(&cli, "a*.*", 0, list_fn, NULL));
4476 printf("Matched %d\n", cli_list(&cli, "b*.*", 0, list_fn, NULL));
4477 printf("Matched %d\n", cli_list(&cli, "xyzabc", 0, list_fn, NULL));
4479 printf("dirtest core %g seconds\n", end_timer() - t1);
4481 srandom(0);
4482 for (i=0;i<numops;i++) {
4483 fstring fname;
4484 slprintf(fname, sizeof(fname), "%x", (int)random());
4485 cli_unlink(&cli, fname);
4488 if (!close_connection(&cli)) {
4489 correct = False;
4492 printf("finished dirtest\n");
4494 return correct;
4497 static double create_procs(BOOL (*fn)(int), BOOL *result)
4499 int i, status;
4500 volatile pid_t *child_status;
4501 volatile BOOL *child_status_out;
4502 int synccount;
4503 int tries = 8;
4505 synccount = 0;
4507 child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*nprocs);
4508 if (!child_status) {
4509 printf("Failed to setup shared memory\n");
4510 return -1;
4513 child_status_out = (volatile BOOL *)shm_setup(sizeof(BOOL)*nprocs);
4514 if (!child_status_out) {
4515 printf("Failed to setup result status shared memory\n");
4516 return -1;
4519 memset(child_status, 0, sizeof(pid_t)*nprocs);
4520 memset(child_status_out, True, sizeof(BOOL)*nprocs);
4522 start_timer();
4524 for (i=0;i<nprocs;i++) {
4525 procnum = i;
4526 if (fork() == 0) {
4527 pid_t mypid = getpid();
4528 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
4530 slprintf(myname,sizeof(myname),"CLIENT%d", i);
4532 while (1) {
4533 memset(&current_cli, 0, sizeof(current_cli));
4534 if (open_connection(&current_cli)) break;
4535 if (tries-- == 0) {
4536 printf("pid %d failed to start\n", (int)getpid());
4537 _exit(1);
4539 msleep(10);
4542 child_status[i] = getpid();
4544 while (child_status[i]) msleep(2);
4546 child_status_out[i] = fn(i);
4547 _exit(0);
4551 do {
4552 synccount = 0;
4553 for (i=0;i<nprocs;i++) {
4554 if (child_status[i]) synccount++;
4556 if (synccount == nprocs) break;
4557 msleep(10);
4558 } while (end_timer() < 30);
4560 if (synccount != nprocs) {
4561 printf("FAILED TO START %d CLIENTS (started %d)\n", nprocs, synccount);
4562 *result = False;
4563 return end_timer();
4566 /* start the client load */
4567 start_timer();
4569 for (i=0;i<nprocs;i++) {
4570 child_status[i] = 0;
4573 printf("%d clients started\n", nprocs);
4575 for (i=0;i<nprocs;i++) {
4576 waitpid(0, &status, 0);
4577 printf("*");
4580 printf("\n");
4582 for (i=0;i<nprocs;i++) {
4583 if (!child_status_out[i]) {
4584 *result = False;
4587 return end_timer();
4591 #define FLAG_MULTIPROC (1<<0)
4592 #define FLAG_MULTIUSER (1<<1)
4593 #define FLAG_MULTISHARE (1<<2)
4594 #define FLAG_PROBE (1<<3)
4596 static struct {
4597 char *name;
4598 BOOL (*fn)(int);
4599 unsigned flags;
4600 } torture_ops[] = {
4601 {"FDPASS", run_fdpasstest, 0},
4602 {"LOCK1", run_locktest1, 0},
4603 {"LOCK2", run_locktest2, 0},
4604 {"LOCK3", run_locktest3, 0},
4605 {"LOCK4", run_locktest4, 0},
4606 {"LOCK5", run_locktest5, 0},
4607 {"UNLINK", run_unlinktest, 0},
4608 {"BROWSE", run_browsetest, 0},
4609 {"ATTR", run_attrtest, 0},
4610 {"TRANS2", run_trans2test, 0},
4611 {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
4612 {"TORTURE",run_torture, FLAG_MULTIPROC},
4613 {"RANDOMIPC", run_randomipc, 0},
4614 {"NEGNOWAIT", run_negprot_nowait, 0},
4615 {"NBW95", run_nbw95, 0},
4616 {"NBWNT", run_nbwnt, 0},
4617 {"OPLOCK1", run_oplock1, 0},
4618 {"OPLOCK2", run_oplock2, 0},
4619 {"DIR", run_dirtest, 0},
4620 {"DENY1", run_denytest1, 0},
4621 {"DENY2", run_denytest2, 0},
4622 {"TCON", run_tcon_test, 0},
4623 {"RW1", run_readwritetest, 0},
4624 {"RW2", run_readwritemulti, FLAG_MULTIPROC},
4625 {"RW3", run_readwritelarge, 0},
4626 {"OPEN", run_opentest, 0},
4627 {"DELETE", run_deletetest, 0},
4628 {"W2K", run_w2ktest, 0},
4629 {"VU", run_vusertest, FLAG_MULTIUSER | FLAG_MULTISHARE},
4630 {NULL, NULL, 0}};
4634 /****************************************************************************
4635 run a specified test or "ALL"
4636 ****************************************************************************/
4638 static BOOL get_test_flags(char *name, BOOL *flags) {
4640 int i;
4642 BOOL all = strequal(name,"ALL") == 0;
4644 for (i=0;torture_ops[i].name;i++) {
4646 if (all || strequal(name, torture_ops[i].name)) {
4648 *flags |= torture_ops[i].flags;
4650 if(!all) {
4652 break;
4657 return True;
4660 static BOOL run_test(char *name)
4662 BOOL ret = True;
4663 BOOL result = True;
4664 int i;
4665 double t;
4666 if (strequal(name,"ALL")) {
4667 for (i=0;torture_ops[i].name;i++) {
4668 run_test(torture_ops[i].name);
4672 for (i=0;torture_ops[i].name;i++) {
4673 snprintf(randomfname, sizeof(randomfname), "\\XX%x",
4674 (unsigned)random());
4676 if (strequal(name, torture_ops[i].name)) {
4677 printf("Running %s\n", name);
4678 if (torture_ops[i].flags & FLAG_MULTIPROC) {
4679 t = create_procs(torture_ops[i].fn, &result);
4680 if (!result) {
4681 ret = False;
4682 printf("TEST %s FAILED!\n", name);
4685 } else {
4686 start_timer();
4687 if (!torture_ops[i].fn(0)) {
4688 ret = False;
4689 printf("TEST %s FAILED!\n", name);
4691 t = end_timer();
4693 printf("%s took %g secs\n\n", name, t);
4696 return ret;
4700 static void usage(void)
4702 int i;
4704 printf("Usage: smbtorture //server/share[,share...] <options> TEST1 TEST2 ...\n");
4706 printf("\t-d debuglevel\n");
4707 printf("\t-U user%%pass\n");
4708 printf("\t-u user%%pass[,user%%pass...]\n");
4709 printf("\t-N numprocs\n");
4710 printf("\t-n my_netbios_name\n");
4711 printf("\t-W workgroup\n");
4712 printf("\t-o num_operations\n");
4713 printf("\t-O socket_options\n");
4714 printf("\t-m maximum protocol\n");
4715 printf("\t-L use oplocks\n");
4716 printf("\n\n");
4718 printf("tests are:");
4719 for (i=0;torture_ops[i].name;i++) {
4720 printf(" %s", torture_ops[i].name);
4722 printf("\n");
4724 printf("default test is ALL\n");
4726 exit(1);
4729 static BOOL split_password_from_username(char *username, char *password) {
4731 char * pp = strchr(username,'%');
4732 if (pp) {
4733 *pp = 0;
4734 pstrcpy(password, pp+1);
4735 return True;
4738 return False;
4741 static BOOL extract_users(char *user_list) {
4743 const char *separators = ",";
4745 char *p = strtok(user_list, separators);
4747 while(p && nusers < MAX_USERS) {
4749 vusers[nusers].username[0] = '\0';
4750 vusers[nusers].password[0] = '\0';
4751 vusers[nusers].gotpass = False;
4753 pstrcpy(vusers[nusers].username, p);
4755 vusers[nusers].gotpass = split_password_from_username(vusers[nusers].username, vusers[nusers].password);
4757 nusers++;
4759 p = strtok(NULL, separators);
4762 return True;
4765 static BOOL extract_shares(char *share_list) {
4767 const char *separators = ",";
4769 char *p = strtok(share_list, separators);
4771 while(p && nshares < MAX_TIDS) {
4773 pstrcpy(shares[nshares], p);
4775 nshares++;
4777 p = strtok(NULL, separators);
4780 return True;
4783 /****************************************************************************
4784 main program
4785 ****************************************************************************/
4787 int main(int argc,char *argv[])
4789 int opt, i;
4790 char *p;
4791 int test_flags = 0;
4792 BOOL *gotpass = &vusers[0].gotpass;
4793 extern char *optarg;
4794 extern int optind;
4795 extern FILE *dbf;
4796 static pstring servicesf = CONFIGFILE;
4797 BOOL correct = True;
4798 fstring user_list;
4799 fstring share_list;
4801 dbf = stdout;
4803 #ifdef HAVE_SETBUFFER
4804 setbuffer(stdout, NULL, 0);
4805 #endif
4806 charset_initialise();
4808 codepage_initialise(lp_client_code_page());
4810 codepage_initialise(lp_client_code_page());
4812 lp_load(servicesf,True,False,False);
4813 load_interfaces();
4815 if (argc < 2) {
4816 usage();
4819 for(p = argv[1]; *p; p++)
4820 if(*p == '\\')
4821 *p = '/';
4823 if (strncmp(argv[1], "//", 2)) {
4824 usage();
4827 fstrcpy(host, &argv[1][2]);
4828 p = strchr(&host[2],'/');
4829 if (!p) {
4830 usage();
4833 *p = 0;
4834 fstrcpy(share_list, p+1);
4836 get_myname(myname);
4838 if (*username == 0 && getenv("LOGNAME")) {
4840 pstrcpy(username,getenv("LOGNAME"));
4843 argc--;
4844 argv++;
4846 fstrcpy(workgroup, lp_workgroup());
4848 while ((opt = getopt(argc, argv, "hW:U:u:n:N:O:o:m:Ld:")) != EOF) {
4849 switch (opt) {
4850 case 'W':
4851 fstrcpy(workgroup,optarg);
4852 break;
4853 case 'm':
4854 max_protocol = interpret_protocol(optarg, max_protocol);
4855 break;
4856 case 'N':
4857 nprocs = atoi(optarg);
4858 break;
4859 case 'o':
4860 numops = atoi(optarg);
4861 break;
4862 case 'd':
4863 DEBUGLEVEL = atoi(optarg);
4864 break;
4865 case 'O':
4866 sockops = optarg;
4867 break;
4868 case 'L':
4869 use_oplocks = True;
4870 break;
4871 case 'n':
4872 fstrcpy(myname, optarg);
4873 break;
4874 case 'U':
4875 pstrcpy(username,optarg);
4876 *gotpass = split_password_from_username(username, password);
4877 break;
4878 case 'u':
4879 pstrcpy(user_list, optarg);
4880 if(!extract_users(user_list)) {
4881 usage();
4883 break;
4884 default:
4885 printf("Unknown option %c (%d)\n", (char)opt, opt);
4886 usage();
4890 if (argc == 1) {
4891 get_test_flags("ALL", &test_flags);
4892 } else {
4893 for (i=1;i<argc;i++) {
4895 get_test_flags(argv[i], &test_flags);
4899 while (!*gotpass) {
4900 fstring s;
4901 snprintf(s, sizeof(s), "Password for user %s:", username);
4902 p = getpass(s);
4903 if (p) {
4904 pstrcpy(password, p);
4905 *gotpass = True;
4909 extract_shares(share_list);
4911 if(test_flags & FLAG_MULTIUSER) {
4913 if(nusers == 1) {
4915 /*generate another user from the one that is already specified*/
4917 vusers[nusers] = vusers[nusers-1];
4919 nusers++;
4922 for(i = 1; i < nusers; i++) {
4924 fstring s;
4926 if(vusers[i].gotpass) {
4928 continue;
4931 snprintf(s, sizeof(s), "Password for user %s:", vusers[i].username);
4933 p = getpass(s);
4934 if (p) {
4936 pstrcpy(vusers[i].password, p);
4937 vusers[i].gotpass = True;
4942 user_list[0] = '\0';
4944 for(i = 0; i < nusers; i++) {
4946 if(!vusers[i].gotpass) {
4948 continue;
4951 if(i) {
4953 fstrcat(user_list, ", ");
4956 fstrcat(user_list, vusers[i].username);
4959 printf("host=%s shares=%s users=%s myname=%s\n", host, share_list, user_list, myname);
4961 if (argc == 1) {
4962 correct = run_test("ALL");
4963 } else {
4964 for (i=1;i<argc;i++) {
4965 if (!run_test(argv[i])) {
4966 correct = False;
4971 if (correct) {
4972 return(0);
4973 } else {
4974 return(1);