2 Unix SMB/CIFS implementation.
3 test suite for various lock operations
4 Copyright (C) Andrew Tridgell 2003
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #define CHECK_STATUS(status, correct) do { \
24 if (!NT_STATUS_EQUAL(status, correct)) { \
25 printf("(%s) Incorrect status %s - should be %s\n", \
26 __location__, nt_errstr(status), nt_errstr(correct)); \
31 #define CHECK_VALUE(v, correct) do { \
32 if ((v) != (correct)) { \
33 printf("(%s) Incorrect value %s=%d - should be %d\n", \
34 __location__, #v, v, correct); \
39 #define BASEDIR "\\testlock"
43 test SMBlock and SMBunlock ops
45 static BOOL test_lock(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
51 const char *fname = BASEDIR "\\test.txt";
53 if (smbcli_deltree(cli->tree, BASEDIR) == -1 ||
54 NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, BASEDIR))) {
55 printf("Unable to setup %s - %s\n", BASEDIR, smbcli_errstr(cli->tree));
59 printf("Testing RAW_LOCK_LOCK\n");
60 io.generic.level = RAW_LOCK_LOCK;
62 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
64 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
69 printf("Trying 0/0 lock\n");
70 io.lock.level = RAW_LOCK_LOCK;
71 io.lock.in.fnum = fnum;
73 io.lock.in.offset = 0;
74 status = smb_raw_lock(cli->tree, &io);
75 CHECK_STATUS(status, NT_STATUS_OK);
77 status = smb_raw_lock(cli->tree, &io);
78 CHECK_STATUS(status, NT_STATUS_OK);
80 io.lock.level = RAW_LOCK_UNLOCK;
81 status = smb_raw_lock(cli->tree, &io);
82 CHECK_STATUS(status, NT_STATUS_OK);
84 printf("Trying 0/1 lock\n");
85 io.lock.level = RAW_LOCK_LOCK;
86 io.lock.in.fnum = fnum;
88 io.lock.in.offset = 0;
89 status = smb_raw_lock(cli->tree, &io);
90 CHECK_STATUS(status, NT_STATUS_OK);
92 status = smb_raw_lock(cli->tree, &io);
93 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
95 io.lock.level = RAW_LOCK_UNLOCK;
96 status = smb_raw_lock(cli->tree, &io);
97 CHECK_STATUS(status, NT_STATUS_OK);
98 io.lock.level = RAW_LOCK_UNLOCK;
99 status = smb_raw_lock(cli->tree, &io);
100 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
102 printf("Trying 0xEEFFFFFF lock\n");
103 io.lock.level = RAW_LOCK_LOCK;
104 io.lock.in.fnum = fnum;
105 io.lock.in.count = 4000;
106 io.lock.in.offset = 0xEEFFFFFF;
107 status = smb_raw_lock(cli->tree, &io);
108 CHECK_STATUS(status, NT_STATUS_OK);
110 status = smb_raw_lock(cli->tree, &io);
111 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
113 io.lock.level = RAW_LOCK_UNLOCK;
114 status = smb_raw_lock(cli->tree, &io);
115 CHECK_STATUS(status, NT_STATUS_OK);
116 io.lock.level = RAW_LOCK_UNLOCK;
117 status = smb_raw_lock(cli->tree, &io);
118 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
120 printf("Trying 0xEF000000 lock\n");
121 io.lock.level = RAW_LOCK_LOCK;
122 io.lock.in.fnum = fnum;
123 io.lock.in.count = 4000;
124 io.lock.in.offset = 0xEEFFFFFF;
125 status = smb_raw_lock(cli->tree, &io);
126 CHECK_STATUS(status, NT_STATUS_OK);
128 status = smb_raw_lock(cli->tree, &io);
129 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
131 io.lock.level = RAW_LOCK_UNLOCK;
132 status = smb_raw_lock(cli->tree, &io);
133 CHECK_STATUS(status, NT_STATUS_OK);
134 io.lock.level = RAW_LOCK_UNLOCK;
135 status = smb_raw_lock(cli->tree, &io);
136 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
138 printf("Trying max lock\n");
139 io.lock.level = RAW_LOCK_LOCK;
140 io.lock.in.fnum = fnum;
141 io.lock.in.count = 4000;
142 io.lock.in.offset = 0xEF000000;
143 status = smb_raw_lock(cli->tree, &io);
144 CHECK_STATUS(status, NT_STATUS_OK);
146 status = smb_raw_lock(cli->tree, &io);
147 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
149 io.lock.level = RAW_LOCK_UNLOCK;
150 status = smb_raw_lock(cli->tree, &io);
151 CHECK_STATUS(status, NT_STATUS_OK);
152 io.lock.level = RAW_LOCK_UNLOCK;
153 status = smb_raw_lock(cli->tree, &io);
154 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
156 printf("Trying wrong pid unlock\n");
157 io.lock.level = RAW_LOCK_LOCK;
158 io.lock.in.fnum = fnum;
159 io.lock.in.count = 4002;
160 io.lock.in.offset = 10001;
161 status = smb_raw_lock(cli->tree, &io);
162 CHECK_STATUS(status, NT_STATUS_OK);
164 io.lock.level = RAW_LOCK_UNLOCK;
165 status = smb_raw_lock(cli->tree, &io);
166 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
168 status = smb_raw_lock(cli->tree, &io);
169 CHECK_STATUS(status, NT_STATUS_OK);
172 smbcli_close(cli->tree, fnum);
173 smb_raw_exit(cli->session);
174 smbcli_deltree(cli->tree, BASEDIR);
182 static BOOL test_lockx(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
185 struct smb_lock_entry lock[1];
189 const char *fname = BASEDIR "\\test.txt";
191 if (smbcli_deltree(cli->tree, BASEDIR) == -1 ||
192 NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, BASEDIR))) {
193 printf("Unable to setup %s - %s\n", BASEDIR, smbcli_errstr(cli->tree));
197 printf("Testing RAW_LOCK_LOCKX\n");
198 io.generic.level = RAW_LOCK_LOCKX;
200 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
202 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
207 io.lockx.level = RAW_LOCK_LOCKX;
208 io.lockx.in.fnum = fnum;
209 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
210 io.lockx.in.timeout = 0;
211 io.lockx.in.ulock_cnt = 0;
212 io.lockx.in.lock_cnt = 1;
213 lock[0].pid = cli->session->pid;
216 io.lockx.in.locks = &lock[0];
217 status = smb_raw_lock(cli->tree, &io);
218 CHECK_STATUS(status, NT_STATUS_OK);
221 printf("Trying 0xEEFFFFFF lock\n");
222 io.lockx.in.ulock_cnt = 0;
223 io.lockx.in.lock_cnt = 1;
224 lock[0].count = 4000;
225 lock[0].offset = 0xEEFFFFFF;
226 status = smb_raw_lock(cli->tree, &io);
227 CHECK_STATUS(status, NT_STATUS_OK);
229 status = smb_raw_lock(cli->tree, &io);
230 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
232 io.lockx.in.ulock_cnt = 1;
233 io.lockx.in.lock_cnt = 0;
234 status = smb_raw_lock(cli->tree, &io);
235 CHECK_STATUS(status, NT_STATUS_OK);
236 status = smb_raw_lock(cli->tree, &io);
237 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
239 printf("Trying 0xEF000000 lock\n");
240 io.lockx.in.ulock_cnt = 0;
241 io.lockx.in.lock_cnt = 1;
242 lock[0].count = 4000;
243 lock[0].offset = 0xEF000000;
244 status = smb_raw_lock(cli->tree, &io);
245 CHECK_STATUS(status, NT_STATUS_OK);
247 status = smb_raw_lock(cli->tree, &io);
248 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
250 io.lockx.in.ulock_cnt = 1;
251 io.lockx.in.lock_cnt = 0;
252 status = smb_raw_lock(cli->tree, &io);
253 CHECK_STATUS(status, NT_STATUS_OK);
254 status = smb_raw_lock(cli->tree, &io);
255 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
257 printf("Trying zero lock\n");
258 io.lockx.in.ulock_cnt = 0;
259 io.lockx.in.lock_cnt = 1;
262 status = smb_raw_lock(cli->tree, &io);
263 CHECK_STATUS(status, NT_STATUS_OK);
265 status = smb_raw_lock(cli->tree, &io);
266 CHECK_STATUS(status, NT_STATUS_OK);
268 io.lockx.in.ulock_cnt = 1;
269 io.lockx.in.lock_cnt = 0;
270 status = smb_raw_lock(cli->tree, &io);
271 CHECK_STATUS(status, NT_STATUS_OK);
272 status = smb_raw_lock(cli->tree, &io);
273 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
275 printf("Trying max lock\n");
276 io.lockx.in.ulock_cnt = 0;
277 io.lockx.in.lock_cnt = 1;
280 status = smb_raw_lock(cli->tree, &io);
281 CHECK_STATUS(status, NT_STATUS_OK);
283 status = smb_raw_lock(cli->tree, &io);
284 CHECK_STATUS(status, NT_STATUS_OK);
286 io.lockx.in.ulock_cnt = 1;
287 io.lockx.in.lock_cnt = 0;
288 status = smb_raw_lock(cli->tree, &io);
289 CHECK_STATUS(status, NT_STATUS_OK);
290 status = smb_raw_lock(cli->tree, &io);
291 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
293 printf("Trying 2^63\n");
294 io.lockx.in.ulock_cnt = 0;
295 io.lockx.in.lock_cnt = 1;
298 lock[0].offset <<= 63;
299 status = smb_raw_lock(cli->tree, &io);
300 CHECK_STATUS(status, NT_STATUS_OK);
302 status = smb_raw_lock(cli->tree, &io);
303 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
305 io.lockx.in.ulock_cnt = 1;
306 io.lockx.in.lock_cnt = 0;
307 status = smb_raw_lock(cli->tree, &io);
308 CHECK_STATUS(status, NT_STATUS_OK);
309 status = smb_raw_lock(cli->tree, &io);
310 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
312 printf("Trying 2^63 - 1\n");
313 io.lockx.in.ulock_cnt = 0;
314 io.lockx.in.lock_cnt = 1;
317 lock[0].offset <<= 63;
319 status = smb_raw_lock(cli->tree, &io);
320 CHECK_STATUS(status, NT_STATUS_OK);
322 status = smb_raw_lock(cli->tree, &io);
323 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
325 io.lockx.in.ulock_cnt = 1;
326 io.lockx.in.lock_cnt = 0;
327 status = smb_raw_lock(cli->tree, &io);
328 CHECK_STATUS(status, NT_STATUS_OK);
329 status = smb_raw_lock(cli->tree, &io);
330 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
332 printf("Trying max lock 2\n");
333 io.lockx.in.ulock_cnt = 0;
334 io.lockx.in.lock_cnt = 1;
337 status = smb_raw_lock(cli->tree, &io);
338 CHECK_STATUS(status, NT_STATUS_OK);
341 status = smb_raw_lock(cli->tree, &io);
342 CHECK_STATUS(status, NT_STATUS_OK);
344 io.lockx.in.ulock_cnt = 1;
345 io.lockx.in.lock_cnt = 0;
347 status = smb_raw_lock(cli->tree, &io);
348 CHECK_STATUS(status, NT_STATUS_OK);
349 status = smb_raw_lock(cli->tree, &io);
350 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
353 smbcli_close(cli->tree, fnum);
354 smb_raw_exit(cli->session);
355 smbcli_deltree(cli->tree, BASEDIR);
363 static BOOL test_pidhigh(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
366 struct smb_lock_entry lock[1];
370 const char *fname = BASEDIR "\\test.txt";
373 if (smbcli_deltree(cli->tree, BASEDIR) == -1 ||
374 NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, BASEDIR))) {
375 printf("Unable to setup %s - %s\n", BASEDIR, smbcli_errstr(cli->tree));
379 printf("Testing high pid\n");
380 io.generic.level = RAW_LOCK_LOCKX;
382 cli->session->pid = 1;
384 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
386 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
391 if (smbcli_write(cli->tree, fnum, 0, &c, 0, 1) != 1) {
392 printf("Failed to write 1 byte - %s\n", smbcli_errstr(cli->tree));
397 io.lockx.level = RAW_LOCK_LOCKX;
398 io.lockx.in.fnum = fnum;
399 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
400 io.lockx.in.timeout = 0;
401 io.lockx.in.ulock_cnt = 0;
402 io.lockx.in.lock_cnt = 1;
403 lock[0].pid = cli->session->pid;
405 lock[0].count = 0xFFFFFFFF;
406 io.lockx.in.locks = &lock[0];
407 status = smb_raw_lock(cli->tree, &io);
408 CHECK_STATUS(status, NT_STATUS_OK);
410 if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
411 printf("Failed to read 1 byte - %s\n", smbcli_errstr(cli->tree));
416 cli->session->pid |= 0x10000;
418 cli->session->pid = 2;
420 if (smbcli_read(cli->tree, fnum, &c, 0, 1) == 1) {
421 printf("pid is incorrect handled for read with lock!\n");
426 cli->session->pid = 0x10001;
428 if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
429 printf("High pid is used on this server!\n");
432 printf("High pid is not used on this server (correct)\n");
436 smbcli_close(cli->tree, fnum);
437 smb_raw_exit(cli->session);
438 smbcli_deltree(cli->tree, BASEDIR);
444 test locking&X async operation
446 static BOOL test_async(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
449 struct smb_lock_entry lock[2];
453 const char *fname = BASEDIR "\\test.txt";
455 struct smbcli_request *req;
457 if (smbcli_deltree(cli->tree, BASEDIR) == -1 ||
458 NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, BASEDIR))) {
459 printf("Unable to setup %s - %s\n", BASEDIR, smbcli_errstr(cli->tree));
463 printf("Testing LOCKING_ANDX_CANCEL_LOCK\n");
464 io.generic.level = RAW_LOCK_LOCKX;
466 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
468 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
473 io.lockx.level = RAW_LOCK_LOCKX;
474 io.lockx.in.fnum = fnum;
475 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
476 io.lockx.in.timeout = 0;
477 io.lockx.in.ulock_cnt = 0;
478 io.lockx.in.lock_cnt = 1;
479 lock[0].pid = cli->session->pid;
480 lock[0].offset = 100;
482 io.lockx.in.locks = &lock[0];
483 status = smb_raw_lock(cli->tree, &io);
484 CHECK_STATUS(status, NT_STATUS_OK);
488 printf("testing cancel by CANCEL_LOCK\n");
490 /* setup a timed lock */
491 io.lockx.in.timeout = 10000;
492 req = smb_raw_lock_send(cli->tree, &io);
494 printf("Failed to setup timed lock (%s)\n", __location__);
499 /* cancel the wrong range */
501 io.lockx.in.timeout = 0;
502 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
503 status = smb_raw_lock(cli->tree, &io);
504 CHECK_STATUS(status, NT_STATUS_UNSUCCESSFUL);
506 /* cancel with the wrong bits set */
507 lock[0].offset = 100;
508 io.lockx.in.timeout = 0;
509 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
510 status = smb_raw_lock(cli->tree, &io);
511 CHECK_STATUS(status, NT_STATUS_UNSUCCESSFUL);
513 /* cancel the right range */
514 lock[0].offset = 100;
515 io.lockx.in.timeout = 0;
516 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
517 status = smb_raw_lock(cli->tree, &io);
518 CHECK_STATUS(status, NT_STATUS_OK);
520 /* receive the failed lock request */
521 status = smbcli_request_simple_recv(req);
522 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
524 if (time(NULL) > t+2) {
525 printf("lock cancel was not immediate (%s)\n", __location__);
530 printf("testing cancel by unlock\n");
531 io.lockx.in.ulock_cnt = 0;
532 io.lockx.in.lock_cnt = 1;
533 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
534 io.lockx.in.timeout = 0;
535 status = smb_raw_lock(cli->tree, &io);
536 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
538 io.lockx.in.timeout = 5000;
539 req = smb_raw_lock_send(cli->tree, &io);
541 printf("Failed to setup timed lock (%s)\n", __location__);
546 io.lockx.in.ulock_cnt = 1;
547 io.lockx.in.lock_cnt = 0;
548 status = smb_raw_lock(cli->tree, &io);
549 CHECK_STATUS(status, NT_STATUS_OK);
551 status = smbcli_request_simple_recv(req);
552 CHECK_STATUS(status, NT_STATUS_OK);
554 if (time(NULL) > t+2) {
555 printf("lock cancel by unlock was not immediate (%s)\n", __location__);
561 printf("testing cancel by close\n");
562 io.lockx.in.ulock_cnt = 0;
563 io.lockx.in.lock_cnt = 1;
564 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
565 io.lockx.in.timeout = 0;
566 status = smb_raw_lock(cli->tree, &io);
567 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
569 io.lockx.in.timeout = 10000;
570 req = smb_raw_lock_send(cli->tree, &io);
572 printf("Failed to setup timed lock (%s)\n", __location__);
577 smbcli_close(cli->tree, fnum);
579 status = smbcli_request_simple_recv(req);
580 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
582 if (time(NULL) > t+2) {
583 printf("lock cancel by unlock was not immediate (%s)\n", __location__);
590 smbcli_close(cli->tree, fnum);
591 smb_raw_exit(cli->session);
592 smbcli_deltree(cli->tree, BASEDIR);
598 test LOCKING_ANDX_CHANGE_LOCKTYPE
600 static BOOL test_changetype(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
603 struct smb_lock_entry lock[2];
608 const char *fname = BASEDIR "\\test.txt";
610 if (smbcli_deltree(cli->tree, BASEDIR) == -1 ||
611 NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, BASEDIR))) {
612 printf("Unable to setup %s - %s\n", BASEDIR, smbcli_errstr(cli->tree));
616 printf("Testing LOCKING_ANDX_CHANGE_LOCKTYPE\n");
617 io.generic.level = RAW_LOCK_LOCKX;
619 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
621 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
626 io.lockx.level = RAW_LOCK_LOCKX;
627 io.lockx.in.fnum = fnum;
628 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
629 io.lockx.in.timeout = 0;
630 io.lockx.in.ulock_cnt = 0;
631 io.lockx.in.lock_cnt = 1;
632 lock[0].pid = cli->session->pid;
633 lock[0].offset = 100;
635 io.lockx.in.locks = &lock[0];
636 status = smb_raw_lock(cli->tree, &io);
637 CHECK_STATUS(status, NT_STATUS_OK);
639 if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
640 printf("allowed write on read locked region (%s)\n", __location__);
645 /* windows server don't seem to support this */
646 io.lockx.in.mode = LOCKING_ANDX_CHANGE_LOCKTYPE;
647 status = smb_raw_lock(cli->tree, &io);
648 CHECK_STATUS(status, NT_STATUS_UNSUCCESSFUL);
650 if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
651 printf("allowed write after lock change (%s)\n", __location__);
657 smbcli_close(cli->tree, fnum);
658 smb_raw_exit(cli->session);
659 smbcli_deltree(cli->tree, BASEDIR);
665 basic testing of lock calls
667 BOOL torture_raw_lock(void)
669 struct smbcli_state *cli;
673 if (!torture_open_connection(&cli)) {
677 mem_ctx = talloc_init("torture_raw_lock");
679 ret &= test_lockx(cli, mem_ctx);
680 ret &= test_lock(cli, mem_ctx);
681 ret &= test_pidhigh(cli, mem_ctx);
682 ret &= test_async(cli, mem_ctx);
683 ret &= test_changetype(cli, mem_ctx);
685 torture_close_connection(cli);
686 talloc_destroy(mem_ctx);