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"
26 #include "libcli/libcli.h"
28 #define CHECK_STATUS(status, correct) do { \
29 if (!NT_STATUS_EQUAL(status, correct)) { \
30 printf("(%s) Incorrect status %s - should be %s\n", \
31 __location__, nt_errstr(status), nt_errstr(correct)); \
36 #define CHECK_VALUE(v, correct) do { \
37 if ((v) != (correct)) { \
38 printf("(%s) Incorrect value %s=%d - should be %d\n", \
39 __location__, #v, v, correct); \
44 #define BASEDIR "\\testlock"
48 test SMBlock and SMBunlock ops
50 static BOOL test_lock(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
56 const char *fname = BASEDIR "\\test.txt";
58 if (!torture_setup_dir(cli, BASEDIR)) {
62 printf("Testing RAW_LOCK_LOCK\n");
63 io.generic.level = RAW_LOCK_LOCK;
65 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
67 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
72 printf("Trying 0/0 lock\n");
73 io.lock.level = RAW_LOCK_LOCK;
74 io.lock.file.fnum = fnum;
76 io.lock.in.offset = 0;
77 status = smb_raw_lock(cli->tree, &io);
78 CHECK_STATUS(status, NT_STATUS_OK);
80 status = smb_raw_lock(cli->tree, &io);
81 CHECK_STATUS(status, NT_STATUS_OK);
83 io.lock.level = RAW_LOCK_UNLOCK;
84 status = smb_raw_lock(cli->tree, &io);
85 CHECK_STATUS(status, NT_STATUS_OK);
87 printf("Trying 0/1 lock\n");
88 io.lock.level = RAW_LOCK_LOCK;
89 io.lock.file.fnum = fnum;
91 io.lock.in.offset = 0;
92 status = smb_raw_lock(cli->tree, &io);
93 CHECK_STATUS(status, NT_STATUS_OK);
95 status = smb_raw_lock(cli->tree, &io);
96 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
98 io.lock.level = RAW_LOCK_UNLOCK;
99 status = smb_raw_lock(cli->tree, &io);
100 CHECK_STATUS(status, NT_STATUS_OK);
101 io.lock.level = RAW_LOCK_UNLOCK;
102 status = smb_raw_lock(cli->tree, &io);
103 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
105 printf("Trying 0xEEFFFFFF lock\n");
106 io.lock.level = RAW_LOCK_LOCK;
107 io.lock.file.fnum = fnum;
108 io.lock.in.count = 4000;
109 io.lock.in.offset = 0xEEFFFFFF;
110 status = smb_raw_lock(cli->tree, &io);
111 CHECK_STATUS(status, NT_STATUS_OK);
113 status = smb_raw_lock(cli->tree, &io);
114 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
116 io.lock.level = RAW_LOCK_UNLOCK;
117 status = smb_raw_lock(cli->tree, &io);
118 CHECK_STATUS(status, NT_STATUS_OK);
119 io.lock.level = RAW_LOCK_UNLOCK;
120 status = smb_raw_lock(cli->tree, &io);
121 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
123 printf("Trying 0xEF000000 lock\n");
124 io.lock.level = RAW_LOCK_LOCK;
125 io.lock.file.fnum = fnum;
126 io.lock.in.count = 4000;
127 io.lock.in.offset = 0xEEFFFFFF;
128 status = smb_raw_lock(cli->tree, &io);
129 CHECK_STATUS(status, NT_STATUS_OK);
131 status = smb_raw_lock(cli->tree, &io);
132 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
134 io.lock.level = RAW_LOCK_UNLOCK;
135 status = smb_raw_lock(cli->tree, &io);
136 CHECK_STATUS(status, NT_STATUS_OK);
137 io.lock.level = RAW_LOCK_UNLOCK;
138 status = smb_raw_lock(cli->tree, &io);
139 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
141 printf("Trying max lock\n");
142 io.lock.level = RAW_LOCK_LOCK;
143 io.lock.file.fnum = fnum;
144 io.lock.in.count = 4000;
145 io.lock.in.offset = 0xEF000000;
146 status = smb_raw_lock(cli->tree, &io);
147 CHECK_STATUS(status, NT_STATUS_OK);
149 status = smb_raw_lock(cli->tree, &io);
150 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
152 io.lock.level = RAW_LOCK_UNLOCK;
153 status = smb_raw_lock(cli->tree, &io);
154 CHECK_STATUS(status, NT_STATUS_OK);
155 io.lock.level = RAW_LOCK_UNLOCK;
156 status = smb_raw_lock(cli->tree, &io);
157 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
159 printf("Trying wrong pid unlock\n");
160 io.lock.level = RAW_LOCK_LOCK;
161 io.lock.file.fnum = fnum;
162 io.lock.in.count = 4002;
163 io.lock.in.offset = 10001;
164 status = smb_raw_lock(cli->tree, &io);
165 CHECK_STATUS(status, NT_STATUS_OK);
167 io.lock.level = RAW_LOCK_UNLOCK;
168 status = smb_raw_lock(cli->tree, &io);
169 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
171 status = smb_raw_lock(cli->tree, &io);
172 CHECK_STATUS(status, NT_STATUS_OK);
175 smbcli_close(cli->tree, fnum);
176 smb_raw_exit(cli->session);
177 smbcli_deltree(cli->tree, BASEDIR);
185 static BOOL test_lockx(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
188 struct smb_lock_entry lock[1];
192 const char *fname = BASEDIR "\\test.txt";
194 if (!torture_setup_dir(cli, BASEDIR)) {
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.file.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 (!torture_setup_dir(cli, BASEDIR)) {
378 printf("Testing high pid\n");
379 io.generic.level = RAW_LOCK_LOCKX;
381 cli->session->pid = 1;
383 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
385 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
390 if (smbcli_write(cli->tree, fnum, 0, &c, 0, 1) != 1) {
391 printf("Failed to write 1 byte - %s\n", smbcli_errstr(cli->tree));
396 io.lockx.level = RAW_LOCK_LOCKX;
397 io.lockx.file.fnum = fnum;
398 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
399 io.lockx.in.timeout = 0;
400 io.lockx.in.ulock_cnt = 0;
401 io.lockx.in.lock_cnt = 1;
402 lock[0].pid = cli->session->pid;
404 lock[0].count = 0xFFFFFFFF;
405 io.lockx.in.locks = &lock[0];
406 status = smb_raw_lock(cli->tree, &io);
407 CHECK_STATUS(status, NT_STATUS_OK);
409 if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
410 printf("Failed to read 1 byte - %s\n", smbcli_errstr(cli->tree));
415 cli->session->pid |= 0x10000;
417 cli->session->pid = 2;
419 if (smbcli_read(cli->tree, fnum, &c, 0, 1) == 1) {
420 printf("pid is incorrect handled for read with lock!\n");
425 cli->session->pid = 0x10001;
427 if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
428 printf("High pid is used on this server!\n");
431 printf("High pid is not used on this server (correct)\n");
435 smbcli_close(cli->tree, fnum);
436 smb_raw_exit(cli->session);
437 smbcli_deltree(cli->tree, BASEDIR);
443 test locking&X async operation
445 static BOOL test_async(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
448 struct smb_lock_entry lock[2];
452 const char *fname = BASEDIR "\\test.txt";
454 struct smbcli_request *req;
456 if (!torture_setup_dir(cli, BASEDIR)) {
460 printf("Testing LOCKING_ANDX_CANCEL_LOCK\n");
461 io.generic.level = RAW_LOCK_LOCKX;
463 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
465 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
470 io.lockx.level = RAW_LOCK_LOCKX;
471 io.lockx.file.fnum = fnum;
472 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
473 io.lockx.in.timeout = 0;
474 io.lockx.in.ulock_cnt = 0;
475 io.lockx.in.lock_cnt = 1;
476 lock[0].pid = cli->session->pid;
477 lock[0].offset = 100;
479 io.lockx.in.locks = &lock[0];
480 status = smb_raw_lock(cli->tree, &io);
481 CHECK_STATUS(status, NT_STATUS_OK);
485 printf("testing cancel by CANCEL_LOCK\n");
487 /* setup a timed lock */
488 io.lockx.in.timeout = 10000;
489 req = smb_raw_lock_send(cli->tree, &io);
491 printf("Failed to setup timed lock (%s)\n", __location__);
496 /* cancel the wrong range */
498 io.lockx.in.timeout = 0;
499 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
500 status = smb_raw_lock(cli->tree, &io);
501 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
503 /* cancel with the wrong bits set */
504 lock[0].offset = 100;
505 io.lockx.in.timeout = 0;
506 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
507 status = smb_raw_lock(cli->tree, &io);
508 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
510 /* cancel the right range */
511 lock[0].offset = 100;
512 io.lockx.in.timeout = 0;
513 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
514 status = smb_raw_lock(cli->tree, &io);
515 CHECK_STATUS(status, NT_STATUS_OK);
517 /* receive the failed lock request */
518 status = smbcli_request_simple_recv(req);
519 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
521 if (time(NULL) > t+2) {
522 printf("lock cancel was not immediate (%s)\n", __location__);
527 printf("testing cancel by unlock\n");
528 io.lockx.in.ulock_cnt = 0;
529 io.lockx.in.lock_cnt = 1;
530 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
531 io.lockx.in.timeout = 0;
532 status = smb_raw_lock(cli->tree, &io);
533 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
535 io.lockx.in.timeout = 5000;
536 req = smb_raw_lock_send(cli->tree, &io);
538 printf("Failed to setup timed lock (%s)\n", __location__);
543 io.lockx.in.ulock_cnt = 1;
544 io.lockx.in.lock_cnt = 0;
545 status = smb_raw_lock(cli->tree, &io);
546 CHECK_STATUS(status, NT_STATUS_OK);
549 status = smbcli_request_simple_recv(req);
550 CHECK_STATUS(status, NT_STATUS_OK);
552 if (time(NULL) > t+2) {
553 printf("lock cancel by unlock was not immediate (%s) - took %d secs\n",
554 __location__, (int)(time(NULL)-t));
560 printf("testing cancel by close\n");
561 io.lockx.in.ulock_cnt = 0;
562 io.lockx.in.lock_cnt = 1;
563 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
564 io.lockx.in.timeout = 0;
565 status = smb_raw_lock(cli->tree, &io);
566 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
568 io.lockx.in.timeout = 10000;
569 req = smb_raw_lock_send(cli->tree, &io);
571 printf("Failed to setup timed lock (%s)\n", __location__);
576 smbcli_close(cli->tree, fnum);
578 status = smbcli_request_simple_recv(req);
579 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
581 if (time(NULL) > t+2) {
582 printf("lock cancel by unlock was not immediate (%s)\n", __location__);
589 smbcli_close(cli->tree, fnum);
590 smb_raw_exit(cli->session);
591 smbcli_deltree(cli->tree, BASEDIR);
597 test LOCKING_ANDX_CHANGE_LOCKTYPE
599 static BOOL test_changetype(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
602 struct smb_lock_entry lock[2];
607 const char *fname = BASEDIR "\\test.txt";
609 if (!torture_setup_dir(cli, BASEDIR)) {
613 printf("Testing LOCKING_ANDX_CHANGE_LOCKTYPE\n");
614 io.generic.level = RAW_LOCK_LOCKX;
616 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
618 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
623 io.lockx.level = RAW_LOCK_LOCKX;
624 io.lockx.file.fnum = fnum;
625 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
626 io.lockx.in.timeout = 0;
627 io.lockx.in.ulock_cnt = 0;
628 io.lockx.in.lock_cnt = 1;
629 lock[0].pid = cli->session->pid;
630 lock[0].offset = 100;
632 io.lockx.in.locks = &lock[0];
633 status = smb_raw_lock(cli->tree, &io);
634 CHECK_STATUS(status, NT_STATUS_OK);
636 if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
637 printf("allowed write on read locked region (%s)\n", __location__);
642 /* windows server don't seem to support this */
643 io.lockx.in.mode = LOCKING_ANDX_CHANGE_LOCKTYPE;
644 status = smb_raw_lock(cli->tree, &io);
645 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
647 if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
648 printf("allowed write after lock change (%s)\n", __location__);
654 smbcli_close(cli->tree, fnum);
655 smb_raw_exit(cli->session);
656 smbcli_deltree(cli->tree, BASEDIR);
662 basic testing of lock calls
664 BOOL torture_raw_lock(void)
666 struct smbcli_state *cli;
670 if (!torture_open_connection(&cli)) {
674 mem_ctx = talloc_init("torture_raw_lock");
676 ret &= test_lockx(cli, mem_ctx);
677 ret &= test_lock(cli, mem_ctx);
678 ret &= test_pidhigh(cli, mem_ctx);
679 ret &= test_async(cli, mem_ctx);
680 ret &= test_changetype(cli, mem_ctx);
682 torture_close_connection(cli);
683 talloc_free(mem_ctx);