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"
24 #define CHECK_STATUS(status, correct) do { \
25 if (!NT_STATUS_EQUAL(status, correct)) { \
26 printf("(%s) Incorrect status %s - should be %s\n", \
27 __location__, nt_errstr(status), nt_errstr(correct)); \
32 #define CHECK_VALUE(v, correct) do { \
33 if ((v) != (correct)) { \
34 printf("(%s) Incorrect value %s=%d - should be %d\n", \
35 __location__, #v, v, correct); \
40 #define BASEDIR "\\testlock"
44 test SMBlock and SMBunlock ops
46 static BOOL test_lock(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
52 const char *fname = BASEDIR "\\test.txt";
54 if (smbcli_deltree(cli->tree, BASEDIR) == -1 ||
55 NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, BASEDIR))) {
56 printf("Unable to setup %s - %s\n", BASEDIR, smbcli_errstr(cli->tree));
60 printf("Testing RAW_LOCK_LOCK\n");
61 io.generic.level = RAW_LOCK_LOCK;
63 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
65 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
70 printf("Trying 0/0 lock\n");
71 io.lock.level = RAW_LOCK_LOCK;
72 io.lock.in.fnum = fnum;
74 io.lock.in.offset = 0;
75 status = smb_raw_lock(cli->tree, &io);
76 CHECK_STATUS(status, NT_STATUS_OK);
78 status = smb_raw_lock(cli->tree, &io);
79 CHECK_STATUS(status, NT_STATUS_OK);
81 io.lock.level = RAW_LOCK_UNLOCK;
82 status = smb_raw_lock(cli->tree, &io);
83 CHECK_STATUS(status, NT_STATUS_OK);
85 printf("Trying 0/1 lock\n");
86 io.lock.level = RAW_LOCK_LOCK;
87 io.lock.in.fnum = fnum;
89 io.lock.in.offset = 0;
90 status = smb_raw_lock(cli->tree, &io);
91 CHECK_STATUS(status, NT_STATUS_OK);
93 status = smb_raw_lock(cli->tree, &io);
94 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
96 io.lock.level = RAW_LOCK_UNLOCK;
97 status = smb_raw_lock(cli->tree, &io);
98 CHECK_STATUS(status, NT_STATUS_OK);
99 io.lock.level = RAW_LOCK_UNLOCK;
100 status = smb_raw_lock(cli->tree, &io);
101 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
103 printf("Trying 0xEEFFFFFF lock\n");
104 io.lock.level = RAW_LOCK_LOCK;
105 io.lock.in.fnum = fnum;
106 io.lock.in.count = 4000;
107 io.lock.in.offset = 0xEEFFFFFF;
108 status = smb_raw_lock(cli->tree, &io);
109 CHECK_STATUS(status, NT_STATUS_OK);
111 status = smb_raw_lock(cli->tree, &io);
112 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
114 io.lock.level = RAW_LOCK_UNLOCK;
115 status = smb_raw_lock(cli->tree, &io);
116 CHECK_STATUS(status, NT_STATUS_OK);
117 io.lock.level = RAW_LOCK_UNLOCK;
118 status = smb_raw_lock(cli->tree, &io);
119 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
121 printf("Trying 0xEF000000 lock\n");
122 io.lock.level = RAW_LOCK_LOCK;
123 io.lock.in.fnum = fnum;
124 io.lock.in.count = 4000;
125 io.lock.in.offset = 0xEEFFFFFF;
126 status = smb_raw_lock(cli->tree, &io);
127 CHECK_STATUS(status, NT_STATUS_OK);
129 status = smb_raw_lock(cli->tree, &io);
130 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
132 io.lock.level = RAW_LOCK_UNLOCK;
133 status = smb_raw_lock(cli->tree, &io);
134 CHECK_STATUS(status, NT_STATUS_OK);
135 io.lock.level = RAW_LOCK_UNLOCK;
136 status = smb_raw_lock(cli->tree, &io);
137 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
139 printf("Trying max lock\n");
140 io.lock.level = RAW_LOCK_LOCK;
141 io.lock.in.fnum = fnum;
142 io.lock.in.count = 4000;
143 io.lock.in.offset = 0xEF000000;
144 status = smb_raw_lock(cli->tree, &io);
145 CHECK_STATUS(status, NT_STATUS_OK);
147 status = smb_raw_lock(cli->tree, &io);
148 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
150 io.lock.level = RAW_LOCK_UNLOCK;
151 status = smb_raw_lock(cli->tree, &io);
152 CHECK_STATUS(status, NT_STATUS_OK);
153 io.lock.level = RAW_LOCK_UNLOCK;
154 status = smb_raw_lock(cli->tree, &io);
155 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
157 printf("Trying wrong pid unlock\n");
158 io.lock.level = RAW_LOCK_LOCK;
159 io.lock.in.fnum = fnum;
160 io.lock.in.count = 4002;
161 io.lock.in.offset = 10001;
162 status = smb_raw_lock(cli->tree, &io);
163 CHECK_STATUS(status, NT_STATUS_OK);
165 io.lock.level = RAW_LOCK_UNLOCK;
166 status = smb_raw_lock(cli->tree, &io);
167 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
169 status = smb_raw_lock(cli->tree, &io);
170 CHECK_STATUS(status, NT_STATUS_OK);
173 smbcli_close(cli->tree, fnum);
174 smb_raw_exit(cli->session);
175 smbcli_deltree(cli->tree, BASEDIR);
183 static BOOL test_lockx(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
186 struct smb_lock_entry lock[1];
190 const char *fname = BASEDIR "\\test.txt";
192 if (smbcli_deltree(cli->tree, BASEDIR) == -1 ||
193 NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, BASEDIR))) {
194 printf("Unable to setup %s - %s\n", BASEDIR, smbcli_errstr(cli->tree));
198 printf("Testing RAW_LOCK_LOCKX\n");
199 io.generic.level = RAW_LOCK_LOCKX;
201 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
203 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
208 io.lockx.level = RAW_LOCK_LOCKX;
209 io.lockx.in.fnum = fnum;
210 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
211 io.lockx.in.timeout = 0;
212 io.lockx.in.ulock_cnt = 0;
213 io.lockx.in.lock_cnt = 1;
214 lock[0].pid = cli->session->pid;
217 io.lockx.in.locks = &lock[0];
218 status = smb_raw_lock(cli->tree, &io);
219 CHECK_STATUS(status, NT_STATUS_OK);
222 printf("Trying 0xEEFFFFFF lock\n");
223 io.lockx.in.ulock_cnt = 0;
224 io.lockx.in.lock_cnt = 1;
225 lock[0].count = 4000;
226 lock[0].offset = 0xEEFFFFFF;
227 status = smb_raw_lock(cli->tree, &io);
228 CHECK_STATUS(status, NT_STATUS_OK);
230 status = smb_raw_lock(cli->tree, &io);
231 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
233 io.lockx.in.ulock_cnt = 1;
234 io.lockx.in.lock_cnt = 0;
235 status = smb_raw_lock(cli->tree, &io);
236 CHECK_STATUS(status, NT_STATUS_OK);
237 status = smb_raw_lock(cli->tree, &io);
238 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
240 printf("Trying 0xEF000000 lock\n");
241 io.lockx.in.ulock_cnt = 0;
242 io.lockx.in.lock_cnt = 1;
243 lock[0].count = 4000;
244 lock[0].offset = 0xEF000000;
245 status = smb_raw_lock(cli->tree, &io);
246 CHECK_STATUS(status, NT_STATUS_OK);
248 status = smb_raw_lock(cli->tree, &io);
249 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
251 io.lockx.in.ulock_cnt = 1;
252 io.lockx.in.lock_cnt = 0;
253 status = smb_raw_lock(cli->tree, &io);
254 CHECK_STATUS(status, NT_STATUS_OK);
255 status = smb_raw_lock(cli->tree, &io);
256 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
258 printf("Trying zero lock\n");
259 io.lockx.in.ulock_cnt = 0;
260 io.lockx.in.lock_cnt = 1;
263 status = smb_raw_lock(cli->tree, &io);
264 CHECK_STATUS(status, NT_STATUS_OK);
266 status = smb_raw_lock(cli->tree, &io);
267 CHECK_STATUS(status, NT_STATUS_OK);
269 io.lockx.in.ulock_cnt = 1;
270 io.lockx.in.lock_cnt = 0;
271 status = smb_raw_lock(cli->tree, &io);
272 CHECK_STATUS(status, NT_STATUS_OK);
273 status = smb_raw_lock(cli->tree, &io);
274 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
276 printf("Trying max lock\n");
277 io.lockx.in.ulock_cnt = 0;
278 io.lockx.in.lock_cnt = 1;
281 status = smb_raw_lock(cli->tree, &io);
282 CHECK_STATUS(status, NT_STATUS_OK);
284 status = smb_raw_lock(cli->tree, &io);
285 CHECK_STATUS(status, NT_STATUS_OK);
287 io.lockx.in.ulock_cnt = 1;
288 io.lockx.in.lock_cnt = 0;
289 status = smb_raw_lock(cli->tree, &io);
290 CHECK_STATUS(status, NT_STATUS_OK);
291 status = smb_raw_lock(cli->tree, &io);
292 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
294 printf("Trying 2^63\n");
295 io.lockx.in.ulock_cnt = 0;
296 io.lockx.in.lock_cnt = 1;
299 lock[0].offset <<= 63;
300 status = smb_raw_lock(cli->tree, &io);
301 CHECK_STATUS(status, NT_STATUS_OK);
303 status = smb_raw_lock(cli->tree, &io);
304 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
306 io.lockx.in.ulock_cnt = 1;
307 io.lockx.in.lock_cnt = 0;
308 status = smb_raw_lock(cli->tree, &io);
309 CHECK_STATUS(status, NT_STATUS_OK);
310 status = smb_raw_lock(cli->tree, &io);
311 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
313 printf("Trying 2^63 - 1\n");
314 io.lockx.in.ulock_cnt = 0;
315 io.lockx.in.lock_cnt = 1;
318 lock[0].offset <<= 63;
320 status = smb_raw_lock(cli->tree, &io);
321 CHECK_STATUS(status, NT_STATUS_OK);
323 status = smb_raw_lock(cli->tree, &io);
324 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
326 io.lockx.in.ulock_cnt = 1;
327 io.lockx.in.lock_cnt = 0;
328 status = smb_raw_lock(cli->tree, &io);
329 CHECK_STATUS(status, NT_STATUS_OK);
330 status = smb_raw_lock(cli->tree, &io);
331 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
333 printf("Trying max lock 2\n");
334 io.lockx.in.ulock_cnt = 0;
335 io.lockx.in.lock_cnt = 1;
338 status = smb_raw_lock(cli->tree, &io);
339 CHECK_STATUS(status, NT_STATUS_OK);
342 status = smb_raw_lock(cli->tree, &io);
343 CHECK_STATUS(status, NT_STATUS_OK);
345 io.lockx.in.ulock_cnt = 1;
346 io.lockx.in.lock_cnt = 0;
348 status = smb_raw_lock(cli->tree, &io);
349 CHECK_STATUS(status, NT_STATUS_OK);
350 status = smb_raw_lock(cli->tree, &io);
351 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
354 smbcli_close(cli->tree, fnum);
355 smb_raw_exit(cli->session);
356 smbcli_deltree(cli->tree, BASEDIR);
364 static BOOL test_pidhigh(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
367 struct smb_lock_entry lock[1];
371 const char *fname = BASEDIR "\\test.txt";
374 if (smbcli_deltree(cli->tree, BASEDIR) == -1 ||
375 NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, BASEDIR))) {
376 printf("Unable to setup %s - %s\n", BASEDIR, smbcli_errstr(cli->tree));
380 printf("Testing high pid\n");
381 io.generic.level = RAW_LOCK_LOCKX;
383 cli->session->pid = 1;
385 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
387 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
392 if (smbcli_write(cli->tree, fnum, 0, &c, 0, 1) != 1) {
393 printf("Failed to write 1 byte - %s\n", smbcli_errstr(cli->tree));
398 io.lockx.level = RAW_LOCK_LOCKX;
399 io.lockx.in.fnum = fnum;
400 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
401 io.lockx.in.timeout = 0;
402 io.lockx.in.ulock_cnt = 0;
403 io.lockx.in.lock_cnt = 1;
404 lock[0].pid = cli->session->pid;
406 lock[0].count = 0xFFFFFFFF;
407 io.lockx.in.locks = &lock[0];
408 status = smb_raw_lock(cli->tree, &io);
409 CHECK_STATUS(status, NT_STATUS_OK);
411 if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
412 printf("Failed to read 1 byte - %s\n", smbcli_errstr(cli->tree));
417 cli->session->pid |= 0x10000;
419 cli->session->pid = 2;
421 if (smbcli_read(cli->tree, fnum, &c, 0, 1) == 1) {
422 printf("pid is incorrect handled for read with lock!\n");
427 cli->session->pid = 0x10001;
429 if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
430 printf("High pid is used on this server!\n");
433 printf("High pid is not used on this server (correct)\n");
437 smbcli_close(cli->tree, fnum);
438 smb_raw_exit(cli->session);
439 smbcli_deltree(cli->tree, BASEDIR);
445 test locking&X async operation
447 static BOOL test_async(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
450 struct smb_lock_entry lock[2];
454 const char *fname = BASEDIR "\\test.txt";
456 struct smbcli_request *req;
458 if (smbcli_deltree(cli->tree, BASEDIR) == -1 ||
459 NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, BASEDIR))) {
460 printf("Unable to setup %s - %s\n", BASEDIR, smbcli_errstr(cli->tree));
464 printf("Testing LOCKING_ANDX_CANCEL_LOCK\n");
465 io.generic.level = RAW_LOCK_LOCKX;
467 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
469 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
474 io.lockx.level = RAW_LOCK_LOCKX;
475 io.lockx.in.fnum = fnum;
476 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
477 io.lockx.in.timeout = 0;
478 io.lockx.in.ulock_cnt = 0;
479 io.lockx.in.lock_cnt = 1;
480 lock[0].pid = cli->session->pid;
481 lock[0].offset = 100;
483 io.lockx.in.locks = &lock[0];
484 status = smb_raw_lock(cli->tree, &io);
485 CHECK_STATUS(status, NT_STATUS_OK);
489 printf("testing cancel by CANCEL_LOCK\n");
491 /* setup a timed lock */
492 io.lockx.in.timeout = 10000;
493 req = smb_raw_lock_send(cli->tree, &io);
495 printf("Failed to setup timed lock (%s)\n", __location__);
500 /* cancel the wrong range */
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 with the wrong bits set */
508 lock[0].offset = 100;
509 io.lockx.in.timeout = 0;
510 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
511 status = smb_raw_lock(cli->tree, &io);
512 CHECK_STATUS(status, NT_STATUS_UNSUCCESSFUL);
514 /* cancel the right range */
515 lock[0].offset = 100;
516 io.lockx.in.timeout = 0;
517 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
518 status = smb_raw_lock(cli->tree, &io);
519 CHECK_STATUS(status, NT_STATUS_OK);
521 /* receive the failed lock request */
522 status = smbcli_request_simple_recv(req);
523 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
525 if (time(NULL) > t+2) {
526 printf("lock cancel was not immediate (%s)\n", __location__);
531 printf("testing cancel by unlock\n");
532 io.lockx.in.ulock_cnt = 0;
533 io.lockx.in.lock_cnt = 1;
534 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
535 io.lockx.in.timeout = 0;
536 status = smb_raw_lock(cli->tree, &io);
537 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
539 io.lockx.in.timeout = 5000;
540 req = smb_raw_lock_send(cli->tree, &io);
542 printf("Failed to setup timed lock (%s)\n", __location__);
547 io.lockx.in.ulock_cnt = 1;
548 io.lockx.in.lock_cnt = 0;
549 status = smb_raw_lock(cli->tree, &io);
550 CHECK_STATUS(status, NT_STATUS_OK);
552 status = smbcli_request_simple_recv(req);
553 CHECK_STATUS(status, NT_STATUS_OK);
555 if (time(NULL) > t+2) {
556 printf("lock cancel by unlock was not immediate (%s)\n", __location__);
562 printf("testing cancel by close\n");
563 io.lockx.in.ulock_cnt = 0;
564 io.lockx.in.lock_cnt = 1;
565 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
566 io.lockx.in.timeout = 0;
567 status = smb_raw_lock(cli->tree, &io);
568 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
570 io.lockx.in.timeout = 10000;
571 req = smb_raw_lock_send(cli->tree, &io);
573 printf("Failed to setup timed lock (%s)\n", __location__);
578 smbcli_close(cli->tree, fnum);
580 status = smbcli_request_simple_recv(req);
581 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
583 if (time(NULL) > t+2) {
584 printf("lock cancel by unlock was not immediate (%s)\n", __location__);
591 smbcli_close(cli->tree, fnum);
592 smb_raw_exit(cli->session);
593 smbcli_deltree(cli->tree, BASEDIR);
599 test LOCKING_ANDX_CHANGE_LOCKTYPE
601 static BOOL test_changetype(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
604 struct smb_lock_entry lock[2];
609 const char *fname = BASEDIR "\\test.txt";
611 if (smbcli_deltree(cli->tree, BASEDIR) == -1 ||
612 NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, BASEDIR))) {
613 printf("Unable to setup %s - %s\n", BASEDIR, smbcli_errstr(cli->tree));
617 printf("Testing LOCKING_ANDX_CHANGE_LOCKTYPE\n");
618 io.generic.level = RAW_LOCK_LOCKX;
620 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
622 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
627 io.lockx.level = RAW_LOCK_LOCKX;
628 io.lockx.in.fnum = fnum;
629 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
630 io.lockx.in.timeout = 0;
631 io.lockx.in.ulock_cnt = 0;
632 io.lockx.in.lock_cnt = 1;
633 lock[0].pid = cli->session->pid;
634 lock[0].offset = 100;
636 io.lockx.in.locks = &lock[0];
637 status = smb_raw_lock(cli->tree, &io);
638 CHECK_STATUS(status, NT_STATUS_OK);
640 if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
641 printf("allowed write on read locked region (%s)\n", __location__);
646 /* windows server don't seem to support this */
647 io.lockx.in.mode = LOCKING_ANDX_CHANGE_LOCKTYPE;
648 status = smb_raw_lock(cli->tree, &io);
649 CHECK_STATUS(status, NT_STATUS_UNSUCCESSFUL);
651 if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
652 printf("allowed write after lock change (%s)\n", __location__);
658 smbcli_close(cli->tree, fnum);
659 smb_raw_exit(cli->session);
660 smbcli_deltree(cli->tree, BASEDIR);
666 basic testing of lock calls
668 BOOL torture_raw_lock(void)
670 struct smbcli_state *cli;
674 if (!torture_open_connection(&cli)) {
678 mem_ctx = talloc_init("torture_raw_lock");
680 ret &= test_lockx(cli, mem_ctx);
681 ret &= test_lock(cli, mem_ctx);
682 ret &= test_pidhigh(cli, mem_ctx);
683 ret &= test_async(cli, mem_ctx);
684 ret &= test_changetype(cli, mem_ctx);
686 torture_close_connection(cli);
687 talloc_destroy(mem_ctx);