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 "torture/torture.h"
23 #include "libcli/raw/libcliraw.h"
24 #include "system/time.h"
25 #include "system/filesys.h"
27 #define CHECK_STATUS(status, correct) do { \
28 if (!NT_STATUS_EQUAL(status, correct)) { \
29 printf("(%s) Incorrect status %s - should be %s\n", \
30 __location__, nt_errstr(status), nt_errstr(correct)); \
35 #define CHECK_VALUE(v, correct) do { \
36 if ((v) != (correct)) { \
37 printf("(%s) Incorrect value %s=%d - should be %d\n", \
38 __location__, #v, v, correct); \
43 #define BASEDIR "\\testlock"
47 test SMBlock and SMBunlock ops
49 static BOOL test_lock(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
55 const char *fname = BASEDIR "\\test.txt";
57 if (!torture_setup_dir(cli, BASEDIR)) {
61 printf("Testing RAW_LOCK_LOCK\n");
62 io.generic.level = RAW_LOCK_LOCK;
64 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
66 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
71 printf("Trying 0/0 lock\n");
72 io.lock.level = RAW_LOCK_LOCK;
73 io.lock.in.fnum = fnum;
75 io.lock.in.offset = 0;
76 status = smb_raw_lock(cli->tree, &io);
77 CHECK_STATUS(status, NT_STATUS_OK);
79 status = smb_raw_lock(cli->tree, &io);
80 CHECK_STATUS(status, NT_STATUS_OK);
82 io.lock.level = RAW_LOCK_UNLOCK;
83 status = smb_raw_lock(cli->tree, &io);
84 CHECK_STATUS(status, NT_STATUS_OK);
86 printf("Trying 0/1 lock\n");
87 io.lock.level = RAW_LOCK_LOCK;
88 io.lock.in.fnum = fnum;
90 io.lock.in.offset = 0;
91 status = smb_raw_lock(cli->tree, &io);
92 CHECK_STATUS(status, NT_STATUS_OK);
94 status = smb_raw_lock(cli->tree, &io);
95 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
97 io.lock.level = RAW_LOCK_UNLOCK;
98 status = smb_raw_lock(cli->tree, &io);
99 CHECK_STATUS(status, NT_STATUS_OK);
100 io.lock.level = RAW_LOCK_UNLOCK;
101 status = smb_raw_lock(cli->tree, &io);
102 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
104 printf("Trying 0xEEFFFFFF lock\n");
105 io.lock.level = RAW_LOCK_LOCK;
106 io.lock.in.fnum = fnum;
107 io.lock.in.count = 4000;
108 io.lock.in.offset = 0xEEFFFFFF;
109 status = smb_raw_lock(cli->tree, &io);
110 CHECK_STATUS(status, NT_STATUS_OK);
112 status = smb_raw_lock(cli->tree, &io);
113 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
115 io.lock.level = RAW_LOCK_UNLOCK;
116 status = smb_raw_lock(cli->tree, &io);
117 CHECK_STATUS(status, NT_STATUS_OK);
118 io.lock.level = RAW_LOCK_UNLOCK;
119 status = smb_raw_lock(cli->tree, &io);
120 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
122 printf("Trying 0xEF000000 lock\n");
123 io.lock.level = RAW_LOCK_LOCK;
124 io.lock.in.fnum = fnum;
125 io.lock.in.count = 4000;
126 io.lock.in.offset = 0xEEFFFFFF;
127 status = smb_raw_lock(cli->tree, &io);
128 CHECK_STATUS(status, NT_STATUS_OK);
130 status = smb_raw_lock(cli->tree, &io);
131 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
133 io.lock.level = RAW_LOCK_UNLOCK;
134 status = smb_raw_lock(cli->tree, &io);
135 CHECK_STATUS(status, NT_STATUS_OK);
136 io.lock.level = RAW_LOCK_UNLOCK;
137 status = smb_raw_lock(cli->tree, &io);
138 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
140 printf("Trying max lock\n");
141 io.lock.level = RAW_LOCK_LOCK;
142 io.lock.in.fnum = fnum;
143 io.lock.in.count = 4000;
144 io.lock.in.offset = 0xEF000000;
145 status = smb_raw_lock(cli->tree, &io);
146 CHECK_STATUS(status, NT_STATUS_OK);
148 status = smb_raw_lock(cli->tree, &io);
149 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
151 io.lock.level = RAW_LOCK_UNLOCK;
152 status = smb_raw_lock(cli->tree, &io);
153 CHECK_STATUS(status, NT_STATUS_OK);
154 io.lock.level = RAW_LOCK_UNLOCK;
155 status = smb_raw_lock(cli->tree, &io);
156 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
158 printf("Trying wrong pid unlock\n");
159 io.lock.level = RAW_LOCK_LOCK;
160 io.lock.in.fnum = fnum;
161 io.lock.in.count = 4002;
162 io.lock.in.offset = 10001;
163 status = smb_raw_lock(cli->tree, &io);
164 CHECK_STATUS(status, NT_STATUS_OK);
166 io.lock.level = RAW_LOCK_UNLOCK;
167 status = smb_raw_lock(cli->tree, &io);
168 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
170 status = smb_raw_lock(cli->tree, &io);
171 CHECK_STATUS(status, NT_STATUS_OK);
174 smbcli_close(cli->tree, fnum);
175 smb_raw_exit(cli->session);
176 smbcli_deltree(cli->tree, BASEDIR);
184 static BOOL test_lockx(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
187 struct smb_lock_entry lock[1];
191 const char *fname = BASEDIR "\\test.txt";
193 if (!torture_setup_dir(cli, BASEDIR)) {
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 (!torture_setup_dir(cli, BASEDIR)) {
377 printf("Testing high pid\n");
378 io.generic.level = RAW_LOCK_LOCKX;
380 cli->session->pid = 1;
382 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
384 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
389 if (smbcli_write(cli->tree, fnum, 0, &c, 0, 1) != 1) {
390 printf("Failed to write 1 byte - %s\n", smbcli_errstr(cli->tree));
395 io.lockx.level = RAW_LOCK_LOCKX;
396 io.lockx.in.fnum = fnum;
397 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
398 io.lockx.in.timeout = 0;
399 io.lockx.in.ulock_cnt = 0;
400 io.lockx.in.lock_cnt = 1;
401 lock[0].pid = cli->session->pid;
403 lock[0].count = 0xFFFFFFFF;
404 io.lockx.in.locks = &lock[0];
405 status = smb_raw_lock(cli->tree, &io);
406 CHECK_STATUS(status, NT_STATUS_OK);
408 if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
409 printf("Failed to read 1 byte - %s\n", smbcli_errstr(cli->tree));
414 cli->session->pid |= 0x10000;
416 cli->session->pid = 2;
418 if (smbcli_read(cli->tree, fnum, &c, 0, 1) == 1) {
419 printf("pid is incorrect handled for read with lock!\n");
424 cli->session->pid = 0x10001;
426 if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
427 printf("High pid is used on this server!\n");
430 printf("High pid is not used on this server (correct)\n");
434 smbcli_close(cli->tree, fnum);
435 smb_raw_exit(cli->session);
436 smbcli_deltree(cli->tree, BASEDIR);
442 test locking&X async operation
444 static BOOL test_async(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
447 struct smb_lock_entry lock[2];
451 const char *fname = BASEDIR "\\test.txt";
453 struct smbcli_request *req;
455 if (!torture_setup_dir(cli, BASEDIR)) {
459 printf("Testing LOCKING_ANDX_CANCEL_LOCK\n");
460 io.generic.level = RAW_LOCK_LOCKX;
462 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
464 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
469 io.lockx.level = RAW_LOCK_LOCKX;
470 io.lockx.in.fnum = fnum;
471 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
472 io.lockx.in.timeout = 0;
473 io.lockx.in.ulock_cnt = 0;
474 io.lockx.in.lock_cnt = 1;
475 lock[0].pid = cli->session->pid;
476 lock[0].offset = 100;
478 io.lockx.in.locks = &lock[0];
479 status = smb_raw_lock(cli->tree, &io);
480 CHECK_STATUS(status, NT_STATUS_OK);
484 printf("testing cancel by CANCEL_LOCK\n");
486 /* setup a timed lock */
487 io.lockx.in.timeout = 10000;
488 req = smb_raw_lock_send(cli->tree, &io);
490 printf("Failed to setup timed lock (%s)\n", __location__);
495 /* cancel the wrong range */
497 io.lockx.in.timeout = 0;
498 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
499 status = smb_raw_lock(cli->tree, &io);
500 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
502 /* cancel with the wrong bits set */
503 lock[0].offset = 100;
504 io.lockx.in.timeout = 0;
505 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
506 status = smb_raw_lock(cli->tree, &io);
507 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
509 /* cancel the right range */
510 lock[0].offset = 100;
511 io.lockx.in.timeout = 0;
512 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
513 status = smb_raw_lock(cli->tree, &io);
514 CHECK_STATUS(status, NT_STATUS_OK);
516 /* receive the failed lock request */
517 status = smbcli_request_simple_recv(req);
518 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
520 if (time(NULL) > t+2) {
521 printf("lock cancel was not immediate (%s)\n", __location__);
526 printf("testing cancel by unlock\n");
527 io.lockx.in.ulock_cnt = 0;
528 io.lockx.in.lock_cnt = 1;
529 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
530 io.lockx.in.timeout = 0;
531 status = smb_raw_lock(cli->tree, &io);
532 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
534 io.lockx.in.timeout = 5000;
535 req = smb_raw_lock_send(cli->tree, &io);
537 printf("Failed to setup timed lock (%s)\n", __location__);
542 io.lockx.in.ulock_cnt = 1;
543 io.lockx.in.lock_cnt = 0;
544 status = smb_raw_lock(cli->tree, &io);
545 CHECK_STATUS(status, NT_STATUS_OK);
548 status = smbcli_request_simple_recv(req);
549 CHECK_STATUS(status, NT_STATUS_OK);
551 if (time(NULL) > t+2) {
552 printf("lock cancel by unlock was not immediate (%s) - took %d secs\n",
553 __location__, (int)(time(NULL)-t));
559 printf("testing cancel by close\n");
560 io.lockx.in.ulock_cnt = 0;
561 io.lockx.in.lock_cnt = 1;
562 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
563 io.lockx.in.timeout = 0;
564 status = smb_raw_lock(cli->tree, &io);
565 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
567 io.lockx.in.timeout = 10000;
568 req = smb_raw_lock_send(cli->tree, &io);
570 printf("Failed to setup timed lock (%s)\n", __location__);
575 smbcli_close(cli->tree, fnum);
577 status = smbcli_request_simple_recv(req);
578 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
580 if (time(NULL) > t+2) {
581 printf("lock cancel by unlock was not immediate (%s)\n", __location__);
588 smbcli_close(cli->tree, fnum);
589 smb_raw_exit(cli->session);
590 smbcli_deltree(cli->tree, BASEDIR);
596 test LOCKING_ANDX_CHANGE_LOCKTYPE
598 static BOOL test_changetype(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
601 struct smb_lock_entry lock[2];
606 const char *fname = BASEDIR "\\test.txt";
608 if (!torture_setup_dir(cli, BASEDIR)) {
612 printf("Testing LOCKING_ANDX_CHANGE_LOCKTYPE\n");
613 io.generic.level = RAW_LOCK_LOCKX;
615 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
617 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
622 io.lockx.level = RAW_LOCK_LOCKX;
623 io.lockx.in.fnum = fnum;
624 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
625 io.lockx.in.timeout = 0;
626 io.lockx.in.ulock_cnt = 0;
627 io.lockx.in.lock_cnt = 1;
628 lock[0].pid = cli->session->pid;
629 lock[0].offset = 100;
631 io.lockx.in.locks = &lock[0];
632 status = smb_raw_lock(cli->tree, &io);
633 CHECK_STATUS(status, NT_STATUS_OK);
635 if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
636 printf("allowed write on read locked region (%s)\n", __location__);
641 /* windows server don't seem to support this */
642 io.lockx.in.mode = LOCKING_ANDX_CHANGE_LOCKTYPE;
643 status = smb_raw_lock(cli->tree, &io);
644 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
646 if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
647 printf("allowed write after lock change (%s)\n", __location__);
653 smbcli_close(cli->tree, fnum);
654 smb_raw_exit(cli->session);
655 smbcli_deltree(cli->tree, BASEDIR);
661 basic testing of lock calls
663 BOOL torture_raw_lock(void)
665 struct smbcli_state *cli;
669 if (!torture_open_connection(&cli)) {
673 mem_ctx = talloc_init("torture_raw_lock");
675 ret &= test_lockx(cli, mem_ctx);
676 ret &= test_lock(cli, mem_ctx);
677 ret &= test_pidhigh(cli, mem_ctx);
678 ret &= test_async(cli, mem_ctx);
679 ret &= test_changetype(cli, mem_ctx);
681 torture_close_connection(cli);
682 talloc_free(mem_ctx);