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"
24 #include "system/filesys.h"
26 #define CHECK_STATUS(status, correct) do { \
27 if (!NT_STATUS_EQUAL(status, correct)) { \
28 printf("(%s) Incorrect status %s - should be %s\n", \
29 __location__, nt_errstr(status), nt_errstr(correct)); \
34 #define CHECK_VALUE(v, correct) do { \
35 if ((v) != (correct)) { \
36 printf("(%s) Incorrect value %s=%d - should be %d\n", \
37 __location__, #v, v, correct); \
42 #define BASEDIR "\\testlock"
46 test SMBlock and SMBunlock ops
48 static BOOL test_lock(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
54 const char *fname = BASEDIR "\\test.txt";
56 if (!torture_setup_dir(cli, BASEDIR)) {
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 (!torture_setup_dir(cli, BASEDIR)) {
196 printf("Testing RAW_LOCK_LOCKX\n");
197 io.generic.level = RAW_LOCK_LOCKX;
199 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
201 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
206 io.lockx.level = RAW_LOCK_LOCKX;
207 io.lockx.in.fnum = fnum;
208 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
209 io.lockx.in.timeout = 0;
210 io.lockx.in.ulock_cnt = 0;
211 io.lockx.in.lock_cnt = 1;
212 lock[0].pid = cli->session->pid;
215 io.lockx.in.locks = &lock[0];
216 status = smb_raw_lock(cli->tree, &io);
217 CHECK_STATUS(status, NT_STATUS_OK);
220 printf("Trying 0xEEFFFFFF lock\n");
221 io.lockx.in.ulock_cnt = 0;
222 io.lockx.in.lock_cnt = 1;
223 lock[0].count = 4000;
224 lock[0].offset = 0xEEFFFFFF;
225 status = smb_raw_lock(cli->tree, &io);
226 CHECK_STATUS(status, NT_STATUS_OK);
228 status = smb_raw_lock(cli->tree, &io);
229 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
231 io.lockx.in.ulock_cnt = 1;
232 io.lockx.in.lock_cnt = 0;
233 status = smb_raw_lock(cli->tree, &io);
234 CHECK_STATUS(status, NT_STATUS_OK);
235 status = smb_raw_lock(cli->tree, &io);
236 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
238 printf("Trying 0xEF000000 lock\n");
239 io.lockx.in.ulock_cnt = 0;
240 io.lockx.in.lock_cnt = 1;
241 lock[0].count = 4000;
242 lock[0].offset = 0xEF000000;
243 status = smb_raw_lock(cli->tree, &io);
244 CHECK_STATUS(status, NT_STATUS_OK);
246 status = smb_raw_lock(cli->tree, &io);
247 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
249 io.lockx.in.ulock_cnt = 1;
250 io.lockx.in.lock_cnt = 0;
251 status = smb_raw_lock(cli->tree, &io);
252 CHECK_STATUS(status, NT_STATUS_OK);
253 status = smb_raw_lock(cli->tree, &io);
254 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
256 printf("Trying zero lock\n");
257 io.lockx.in.ulock_cnt = 0;
258 io.lockx.in.lock_cnt = 1;
261 status = smb_raw_lock(cli->tree, &io);
262 CHECK_STATUS(status, NT_STATUS_OK);
264 status = smb_raw_lock(cli->tree, &io);
265 CHECK_STATUS(status, NT_STATUS_OK);
267 io.lockx.in.ulock_cnt = 1;
268 io.lockx.in.lock_cnt = 0;
269 status = smb_raw_lock(cli->tree, &io);
270 CHECK_STATUS(status, NT_STATUS_OK);
271 status = smb_raw_lock(cli->tree, &io);
272 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
274 printf("Trying max lock\n");
275 io.lockx.in.ulock_cnt = 0;
276 io.lockx.in.lock_cnt = 1;
279 status = smb_raw_lock(cli->tree, &io);
280 CHECK_STATUS(status, NT_STATUS_OK);
282 status = smb_raw_lock(cli->tree, &io);
283 CHECK_STATUS(status, NT_STATUS_OK);
285 io.lockx.in.ulock_cnt = 1;
286 io.lockx.in.lock_cnt = 0;
287 status = smb_raw_lock(cli->tree, &io);
288 CHECK_STATUS(status, NT_STATUS_OK);
289 status = smb_raw_lock(cli->tree, &io);
290 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
292 printf("Trying 2^63\n");
293 io.lockx.in.ulock_cnt = 0;
294 io.lockx.in.lock_cnt = 1;
297 lock[0].offset <<= 63;
298 status = smb_raw_lock(cli->tree, &io);
299 CHECK_STATUS(status, NT_STATUS_OK);
301 status = smb_raw_lock(cli->tree, &io);
302 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
304 io.lockx.in.ulock_cnt = 1;
305 io.lockx.in.lock_cnt = 0;
306 status = smb_raw_lock(cli->tree, &io);
307 CHECK_STATUS(status, NT_STATUS_OK);
308 status = smb_raw_lock(cli->tree, &io);
309 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
311 printf("Trying 2^63 - 1\n");
312 io.lockx.in.ulock_cnt = 0;
313 io.lockx.in.lock_cnt = 1;
316 lock[0].offset <<= 63;
318 status = smb_raw_lock(cli->tree, &io);
319 CHECK_STATUS(status, NT_STATUS_OK);
321 status = smb_raw_lock(cli->tree, &io);
322 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
324 io.lockx.in.ulock_cnt = 1;
325 io.lockx.in.lock_cnt = 0;
326 status = smb_raw_lock(cli->tree, &io);
327 CHECK_STATUS(status, NT_STATUS_OK);
328 status = smb_raw_lock(cli->tree, &io);
329 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
331 printf("Trying max lock 2\n");
332 io.lockx.in.ulock_cnt = 0;
333 io.lockx.in.lock_cnt = 1;
336 status = smb_raw_lock(cli->tree, &io);
337 CHECK_STATUS(status, NT_STATUS_OK);
340 status = smb_raw_lock(cli->tree, &io);
341 CHECK_STATUS(status, NT_STATUS_OK);
343 io.lockx.in.ulock_cnt = 1;
344 io.lockx.in.lock_cnt = 0;
346 status = smb_raw_lock(cli->tree, &io);
347 CHECK_STATUS(status, NT_STATUS_OK);
348 status = smb_raw_lock(cli->tree, &io);
349 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
352 smbcli_close(cli->tree, fnum);
353 smb_raw_exit(cli->session);
354 smbcli_deltree(cli->tree, BASEDIR);
362 static BOOL test_pidhigh(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
365 struct smb_lock_entry lock[1];
369 const char *fname = BASEDIR "\\test.txt";
372 if (!torture_setup_dir(cli, BASEDIR)) {
376 printf("Testing high pid\n");
377 io.generic.level = RAW_LOCK_LOCKX;
379 cli->session->pid = 1;
381 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
383 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
388 if (smbcli_write(cli->tree, fnum, 0, &c, 0, 1) != 1) {
389 printf("Failed to write 1 byte - %s\n", smbcli_errstr(cli->tree));
394 io.lockx.level = RAW_LOCK_LOCKX;
395 io.lockx.in.fnum = fnum;
396 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
397 io.lockx.in.timeout = 0;
398 io.lockx.in.ulock_cnt = 0;
399 io.lockx.in.lock_cnt = 1;
400 lock[0].pid = cli->session->pid;
402 lock[0].count = 0xFFFFFFFF;
403 io.lockx.in.locks = &lock[0];
404 status = smb_raw_lock(cli->tree, &io);
405 CHECK_STATUS(status, NT_STATUS_OK);
407 if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
408 printf("Failed to read 1 byte - %s\n", smbcli_errstr(cli->tree));
413 cli->session->pid |= 0x10000;
415 cli->session->pid = 2;
417 if (smbcli_read(cli->tree, fnum, &c, 0, 1) == 1) {
418 printf("pid is incorrect handled for read with lock!\n");
423 cli->session->pid = 0x10001;
425 if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
426 printf("High pid is used on this server!\n");
429 printf("High pid is not used on this server (correct)\n");
433 smbcli_close(cli->tree, fnum);
434 smb_raw_exit(cli->session);
435 smbcli_deltree(cli->tree, BASEDIR);
441 test locking&X async operation
443 static BOOL test_async(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
446 struct smb_lock_entry lock[2];
450 const char *fname = BASEDIR "\\test.txt";
452 struct smbcli_request *req;
454 if (!torture_setup_dir(cli, BASEDIR)) {
458 printf("Testing LOCKING_ANDX_CANCEL_LOCK\n");
459 io.generic.level = RAW_LOCK_LOCKX;
461 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
463 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
468 io.lockx.level = RAW_LOCK_LOCKX;
469 io.lockx.in.fnum = fnum;
470 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
471 io.lockx.in.timeout = 0;
472 io.lockx.in.ulock_cnt = 0;
473 io.lockx.in.lock_cnt = 1;
474 lock[0].pid = cli->session->pid;
475 lock[0].offset = 100;
477 io.lockx.in.locks = &lock[0];
478 status = smb_raw_lock(cli->tree, &io);
479 CHECK_STATUS(status, NT_STATUS_OK);
483 printf("testing cancel by CANCEL_LOCK\n");
485 /* setup a timed lock */
486 io.lockx.in.timeout = 10000;
487 req = smb_raw_lock_send(cli->tree, &io);
489 printf("Failed to setup timed lock (%s)\n", __location__);
494 /* cancel the wrong range */
496 io.lockx.in.timeout = 0;
497 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
498 status = smb_raw_lock(cli->tree, &io);
499 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
501 /* cancel with the wrong bits set */
502 lock[0].offset = 100;
503 io.lockx.in.timeout = 0;
504 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
505 status = smb_raw_lock(cli->tree, &io);
506 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
508 /* cancel the right range */
509 lock[0].offset = 100;
510 io.lockx.in.timeout = 0;
511 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
512 status = smb_raw_lock(cli->tree, &io);
513 CHECK_STATUS(status, NT_STATUS_OK);
515 /* receive the failed lock request */
516 status = smbcli_request_simple_recv(req);
517 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
519 if (time(NULL) > t+2) {
520 printf("lock cancel was not immediate (%s)\n", __location__);
525 printf("testing cancel by unlock\n");
526 io.lockx.in.ulock_cnt = 0;
527 io.lockx.in.lock_cnt = 1;
528 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
529 io.lockx.in.timeout = 0;
530 status = smb_raw_lock(cli->tree, &io);
531 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
533 io.lockx.in.timeout = 5000;
534 req = smb_raw_lock_send(cli->tree, &io);
536 printf("Failed to setup timed lock (%s)\n", __location__);
541 io.lockx.in.ulock_cnt = 1;
542 io.lockx.in.lock_cnt = 0;
543 status = smb_raw_lock(cli->tree, &io);
544 CHECK_STATUS(status, NT_STATUS_OK);
547 status = smbcli_request_simple_recv(req);
548 CHECK_STATUS(status, NT_STATUS_OK);
550 if (time(NULL) > t+2) {
551 printf("lock cancel by unlock was not immediate (%s) - took %d secs\n",
552 __location__, (int)(time(NULL)-t));
558 printf("testing cancel by close\n");
559 io.lockx.in.ulock_cnt = 0;
560 io.lockx.in.lock_cnt = 1;
561 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
562 io.lockx.in.timeout = 0;
563 status = smb_raw_lock(cli->tree, &io);
564 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
566 io.lockx.in.timeout = 10000;
567 req = smb_raw_lock_send(cli->tree, &io);
569 printf("Failed to setup timed lock (%s)\n", __location__);
574 smbcli_close(cli->tree, fnum);
576 status = smbcli_request_simple_recv(req);
577 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
579 if (time(NULL) > t+2) {
580 printf("lock cancel by unlock was not immediate (%s)\n", __location__);
587 smbcli_close(cli->tree, fnum);
588 smb_raw_exit(cli->session);
589 smbcli_deltree(cli->tree, BASEDIR);
595 test LOCKING_ANDX_CHANGE_LOCKTYPE
597 static BOOL test_changetype(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
600 struct smb_lock_entry lock[2];
605 const char *fname = BASEDIR "\\test.txt";
607 if (!torture_setup_dir(cli, BASEDIR)) {
611 printf("Testing LOCKING_ANDX_CHANGE_LOCKTYPE\n");
612 io.generic.level = RAW_LOCK_LOCKX;
614 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
616 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
621 io.lockx.level = RAW_LOCK_LOCKX;
622 io.lockx.in.fnum = fnum;
623 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
624 io.lockx.in.timeout = 0;
625 io.lockx.in.ulock_cnt = 0;
626 io.lockx.in.lock_cnt = 1;
627 lock[0].pid = cli->session->pid;
628 lock[0].offset = 100;
630 io.lockx.in.locks = &lock[0];
631 status = smb_raw_lock(cli->tree, &io);
632 CHECK_STATUS(status, NT_STATUS_OK);
634 if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
635 printf("allowed write on read locked region (%s)\n", __location__);
640 /* windows server don't seem to support this */
641 io.lockx.in.mode = LOCKING_ANDX_CHANGE_LOCKTYPE;
642 status = smb_raw_lock(cli->tree, &io);
643 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
645 if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
646 printf("allowed write after lock change (%s)\n", __location__);
652 smbcli_close(cli->tree, fnum);
653 smb_raw_exit(cli->session);
654 smbcli_deltree(cli->tree, BASEDIR);
660 basic testing of lock calls
662 BOOL torture_raw_lock(void)
664 struct smbcli_state *cli;
668 if (!torture_open_connection(&cli)) {
672 mem_ctx = talloc_init("torture_raw_lock");
674 ret &= test_lockx(cli, mem_ctx);
675 ret &= test_lock(cli, mem_ctx);
676 ret &= test_pidhigh(cli, mem_ctx);
677 ret &= test_async(cli, mem_ctx);
678 ret &= test_changetype(cli, mem_ctx);
680 torture_close_connection(cli);
681 talloc_free(mem_ctx);