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.
22 #include "libcli/raw/libcliraw.h"
23 #include "system/time.h"
25 #define CHECK_STATUS(status, correct) do { \
26 if (!NT_STATUS_EQUAL(status, correct)) { \
27 printf("(%s) Incorrect status %s - should be %s\n", \
28 __location__, nt_errstr(status), nt_errstr(correct)); \
33 #define CHECK_VALUE(v, correct) do { \
34 if ((v) != (correct)) { \
35 printf("(%s) Incorrect value %s=%d - should be %d\n", \
36 __location__, #v, v, correct); \
41 #define BASEDIR "\\testlock"
45 test SMBlock and SMBunlock ops
47 static BOOL test_lock(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
53 const char *fname = BASEDIR "\\test.txt";
55 if (!torture_setup_dir(cli, BASEDIR)) {
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 (!torture_setup_dir(cli, BASEDIR)) {
195 printf("Testing RAW_LOCK_LOCKX\n");
196 io.generic.level = RAW_LOCK_LOCKX;
198 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
200 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
205 io.lockx.level = RAW_LOCK_LOCKX;
206 io.lockx.in.fnum = fnum;
207 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
208 io.lockx.in.timeout = 0;
209 io.lockx.in.ulock_cnt = 0;
210 io.lockx.in.lock_cnt = 1;
211 lock[0].pid = cli->session->pid;
214 io.lockx.in.locks = &lock[0];
215 status = smb_raw_lock(cli->tree, &io);
216 CHECK_STATUS(status, NT_STATUS_OK);
219 printf("Trying 0xEEFFFFFF lock\n");
220 io.lockx.in.ulock_cnt = 0;
221 io.lockx.in.lock_cnt = 1;
222 lock[0].count = 4000;
223 lock[0].offset = 0xEEFFFFFF;
224 status = smb_raw_lock(cli->tree, &io);
225 CHECK_STATUS(status, NT_STATUS_OK);
227 status = smb_raw_lock(cli->tree, &io);
228 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
230 io.lockx.in.ulock_cnt = 1;
231 io.lockx.in.lock_cnt = 0;
232 status = smb_raw_lock(cli->tree, &io);
233 CHECK_STATUS(status, NT_STATUS_OK);
234 status = smb_raw_lock(cli->tree, &io);
235 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
237 printf("Trying 0xEF000000 lock\n");
238 io.lockx.in.ulock_cnt = 0;
239 io.lockx.in.lock_cnt = 1;
240 lock[0].count = 4000;
241 lock[0].offset = 0xEF000000;
242 status = smb_raw_lock(cli->tree, &io);
243 CHECK_STATUS(status, NT_STATUS_OK);
245 status = smb_raw_lock(cli->tree, &io);
246 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
248 io.lockx.in.ulock_cnt = 1;
249 io.lockx.in.lock_cnt = 0;
250 status = smb_raw_lock(cli->tree, &io);
251 CHECK_STATUS(status, NT_STATUS_OK);
252 status = smb_raw_lock(cli->tree, &io);
253 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
255 printf("Trying zero lock\n");
256 io.lockx.in.ulock_cnt = 0;
257 io.lockx.in.lock_cnt = 1;
260 status = smb_raw_lock(cli->tree, &io);
261 CHECK_STATUS(status, NT_STATUS_OK);
263 status = smb_raw_lock(cli->tree, &io);
264 CHECK_STATUS(status, NT_STATUS_OK);
266 io.lockx.in.ulock_cnt = 1;
267 io.lockx.in.lock_cnt = 0;
268 status = smb_raw_lock(cli->tree, &io);
269 CHECK_STATUS(status, NT_STATUS_OK);
270 status = smb_raw_lock(cli->tree, &io);
271 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
273 printf("Trying max lock\n");
274 io.lockx.in.ulock_cnt = 0;
275 io.lockx.in.lock_cnt = 1;
278 status = smb_raw_lock(cli->tree, &io);
279 CHECK_STATUS(status, NT_STATUS_OK);
281 status = smb_raw_lock(cli->tree, &io);
282 CHECK_STATUS(status, NT_STATUS_OK);
284 io.lockx.in.ulock_cnt = 1;
285 io.lockx.in.lock_cnt = 0;
286 status = smb_raw_lock(cli->tree, &io);
287 CHECK_STATUS(status, NT_STATUS_OK);
288 status = smb_raw_lock(cli->tree, &io);
289 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
291 printf("Trying 2^63\n");
292 io.lockx.in.ulock_cnt = 0;
293 io.lockx.in.lock_cnt = 1;
296 lock[0].offset <<= 63;
297 status = smb_raw_lock(cli->tree, &io);
298 CHECK_STATUS(status, NT_STATUS_OK);
300 status = smb_raw_lock(cli->tree, &io);
301 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
303 io.lockx.in.ulock_cnt = 1;
304 io.lockx.in.lock_cnt = 0;
305 status = smb_raw_lock(cli->tree, &io);
306 CHECK_STATUS(status, NT_STATUS_OK);
307 status = smb_raw_lock(cli->tree, &io);
308 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
310 printf("Trying 2^63 - 1\n");
311 io.lockx.in.ulock_cnt = 0;
312 io.lockx.in.lock_cnt = 1;
315 lock[0].offset <<= 63;
317 status = smb_raw_lock(cli->tree, &io);
318 CHECK_STATUS(status, NT_STATUS_OK);
320 status = smb_raw_lock(cli->tree, &io);
321 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
323 io.lockx.in.ulock_cnt = 1;
324 io.lockx.in.lock_cnt = 0;
325 status = smb_raw_lock(cli->tree, &io);
326 CHECK_STATUS(status, NT_STATUS_OK);
327 status = smb_raw_lock(cli->tree, &io);
328 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
330 printf("Trying max lock 2\n");
331 io.lockx.in.ulock_cnt = 0;
332 io.lockx.in.lock_cnt = 1;
335 status = smb_raw_lock(cli->tree, &io);
336 CHECK_STATUS(status, NT_STATUS_OK);
339 status = smb_raw_lock(cli->tree, &io);
340 CHECK_STATUS(status, NT_STATUS_OK);
342 io.lockx.in.ulock_cnt = 1;
343 io.lockx.in.lock_cnt = 0;
345 status = smb_raw_lock(cli->tree, &io);
346 CHECK_STATUS(status, NT_STATUS_OK);
347 status = smb_raw_lock(cli->tree, &io);
348 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
351 smbcli_close(cli->tree, fnum);
352 smb_raw_exit(cli->session);
353 smbcli_deltree(cli->tree, BASEDIR);
361 static BOOL test_pidhigh(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
364 struct smb_lock_entry lock[1];
368 const char *fname = BASEDIR "\\test.txt";
371 if (!torture_setup_dir(cli, BASEDIR)) {
375 printf("Testing high pid\n");
376 io.generic.level = RAW_LOCK_LOCKX;
378 cli->session->pid = 1;
380 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
382 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
387 if (smbcli_write(cli->tree, fnum, 0, &c, 0, 1) != 1) {
388 printf("Failed to write 1 byte - %s\n", smbcli_errstr(cli->tree));
393 io.lockx.level = RAW_LOCK_LOCKX;
394 io.lockx.in.fnum = fnum;
395 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
396 io.lockx.in.timeout = 0;
397 io.lockx.in.ulock_cnt = 0;
398 io.lockx.in.lock_cnt = 1;
399 lock[0].pid = cli->session->pid;
401 lock[0].count = 0xFFFFFFFF;
402 io.lockx.in.locks = &lock[0];
403 status = smb_raw_lock(cli->tree, &io);
404 CHECK_STATUS(status, NT_STATUS_OK);
406 if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
407 printf("Failed to read 1 byte - %s\n", smbcli_errstr(cli->tree));
412 cli->session->pid |= 0x10000;
414 cli->session->pid = 2;
416 if (smbcli_read(cli->tree, fnum, &c, 0, 1) == 1) {
417 printf("pid is incorrect handled for read with lock!\n");
422 cli->session->pid = 0x10001;
424 if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
425 printf("High pid is used on this server!\n");
428 printf("High pid is not used on this server (correct)\n");
432 smbcli_close(cli->tree, fnum);
433 smb_raw_exit(cli->session);
434 smbcli_deltree(cli->tree, BASEDIR);
440 test locking&X async operation
442 static BOOL test_async(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
445 struct smb_lock_entry lock[2];
449 const char *fname = BASEDIR "\\test.txt";
451 struct smbcli_request *req;
453 if (!torture_setup_dir(cli, BASEDIR)) {
457 printf("Testing LOCKING_ANDX_CANCEL_LOCK\n");
458 io.generic.level = RAW_LOCK_LOCKX;
460 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
462 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
467 io.lockx.level = RAW_LOCK_LOCKX;
468 io.lockx.in.fnum = fnum;
469 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
470 io.lockx.in.timeout = 0;
471 io.lockx.in.ulock_cnt = 0;
472 io.lockx.in.lock_cnt = 1;
473 lock[0].pid = cli->session->pid;
474 lock[0].offset = 100;
476 io.lockx.in.locks = &lock[0];
477 status = smb_raw_lock(cli->tree, &io);
478 CHECK_STATUS(status, NT_STATUS_OK);
482 printf("testing cancel by CANCEL_LOCK\n");
484 /* setup a timed lock */
485 io.lockx.in.timeout = 10000;
486 req = smb_raw_lock_send(cli->tree, &io);
488 printf("Failed to setup timed lock (%s)\n", __location__);
493 /* cancel the wrong range */
495 io.lockx.in.timeout = 0;
496 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
497 status = smb_raw_lock(cli->tree, &io);
498 CHECK_STATUS(status, NT_STATUS_UNSUCCESSFUL);
500 /* cancel with the wrong bits set */
501 lock[0].offset = 100;
502 io.lockx.in.timeout = 0;
503 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
504 status = smb_raw_lock(cli->tree, &io);
505 CHECK_STATUS(status, NT_STATUS_UNSUCCESSFUL);
507 /* cancel the right range */
508 lock[0].offset = 100;
509 io.lockx.in.timeout = 0;
510 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
511 status = smb_raw_lock(cli->tree, &io);
512 CHECK_STATUS(status, NT_STATUS_OK);
514 /* receive the failed lock request */
515 status = smbcli_request_simple_recv(req);
516 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
518 if (time(NULL) > t+2) {
519 printf("lock cancel was not immediate (%s)\n", __location__);
524 printf("testing cancel by unlock\n");
525 io.lockx.in.ulock_cnt = 0;
526 io.lockx.in.lock_cnt = 1;
527 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
528 io.lockx.in.timeout = 0;
529 status = smb_raw_lock(cli->tree, &io);
530 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
532 io.lockx.in.timeout = 5000;
533 req = smb_raw_lock_send(cli->tree, &io);
535 printf("Failed to setup timed lock (%s)\n", __location__);
540 io.lockx.in.ulock_cnt = 1;
541 io.lockx.in.lock_cnt = 0;
542 status = smb_raw_lock(cli->tree, &io);
543 CHECK_STATUS(status, NT_STATUS_OK);
545 status = smbcli_request_simple_recv(req);
546 CHECK_STATUS(status, NT_STATUS_OK);
548 if (time(NULL) > t+2) {
549 printf("lock cancel by unlock was not immediate (%s)\n", __location__);
555 printf("testing cancel by close\n");
556 io.lockx.in.ulock_cnt = 0;
557 io.lockx.in.lock_cnt = 1;
558 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
559 io.lockx.in.timeout = 0;
560 status = smb_raw_lock(cli->tree, &io);
561 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
563 io.lockx.in.timeout = 10000;
564 req = smb_raw_lock_send(cli->tree, &io);
566 printf("Failed to setup timed lock (%s)\n", __location__);
571 smbcli_close(cli->tree, fnum);
573 status = smbcli_request_simple_recv(req);
574 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
576 if (time(NULL) > t+2) {
577 printf("lock cancel by unlock was not immediate (%s)\n", __location__);
584 smbcli_close(cli->tree, fnum);
585 smb_raw_exit(cli->session);
586 smbcli_deltree(cli->tree, BASEDIR);
592 test LOCKING_ANDX_CHANGE_LOCKTYPE
594 static BOOL test_changetype(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
597 struct smb_lock_entry lock[2];
602 const char *fname = BASEDIR "\\test.txt";
604 if (!torture_setup_dir(cli, BASEDIR)) {
608 printf("Testing LOCKING_ANDX_CHANGE_LOCKTYPE\n");
609 io.generic.level = RAW_LOCK_LOCKX;
611 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
613 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
618 io.lockx.level = RAW_LOCK_LOCKX;
619 io.lockx.in.fnum = fnum;
620 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
621 io.lockx.in.timeout = 0;
622 io.lockx.in.ulock_cnt = 0;
623 io.lockx.in.lock_cnt = 1;
624 lock[0].pid = cli->session->pid;
625 lock[0].offset = 100;
627 io.lockx.in.locks = &lock[0];
628 status = smb_raw_lock(cli->tree, &io);
629 CHECK_STATUS(status, NT_STATUS_OK);
631 if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
632 printf("allowed write on read locked region (%s)\n", __location__);
637 /* windows server don't seem to support this */
638 io.lockx.in.mode = LOCKING_ANDX_CHANGE_LOCKTYPE;
639 status = smb_raw_lock(cli->tree, &io);
640 CHECK_STATUS(status, NT_STATUS_UNSUCCESSFUL);
642 if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
643 printf("allowed write after lock change (%s)\n", __location__);
649 smbcli_close(cli->tree, fnum);
650 smb_raw_exit(cli->session);
651 smbcli_deltree(cli->tree, BASEDIR);
657 basic testing of lock calls
659 BOOL torture_raw_lock(void)
661 struct smbcli_state *cli;
665 if (!torture_open_connection(&cli)) {
669 mem_ctx = talloc_init("torture_raw_lock");
671 ret &= test_lockx(cli, mem_ctx);
672 ret &= test_lock(cli, mem_ctx);
673 ret &= test_pidhigh(cli, mem_ctx);
674 ret &= test_async(cli, mem_ctx);
675 ret &= test_changetype(cli, mem_ctx);
677 torture_close_connection(cli);
678 talloc_free(mem_ctx);