1 /*
2 Unix SMB/CIFS implementation.
3 test suite for various lock operations
4 Copyright (C) Andrew Tridgell 2003
5
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.
10
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.
15
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.
19 */
20
21 #include "includes.h"
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"
27 #include "torture/util.h"
28 #include "libcli/composite/composite.h"
29 #include "libcli/smb_composite/smb_composite.h"
30 #include "lib/cmdline/popt_common.h"
31
32 #define CHECK_STATUS(status, correct) do { \
33 if (!NT_STATUS_EQUAL(status, correct)) { \
34 printf("(%s) Incorrect status %s - should be %s\n", \
35 __location__, nt_errstr(status), nt_errstr(correct)); \
36 ret = False; \
37 goto done; \
38 }} while (0)
39
40 #define BASEDIR "\\testlock"
41
42
43 /*
44 test SMBlock and SMBunlock ops
45 */
test_lock(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)46 static BOOL test_lock(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
47 {
48 union smb_lock io;
49 NTSTATUS status;
50 BOOL ret = True;
51 int fnum;
52 const char *fname = BASEDIR "\\test.txt";
53
54 if (!torture_setup_dir(cli, BASEDIR)) {
55 return False;
56 }
57
58 printf("Testing RAW_LOCK_LOCK\n");
59 io.generic.level = RAW_LOCK_LOCK;
60
61 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
62 if (fnum == -1) {
63 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
64 ret = False;
65 goto done;
66 }
67
68 printf("Trying 0/0 lock\n");
69 io.lock.level = RAW_LOCK_LOCK;
70 io.lock.in.file.fnum = fnum;
71 io.lock.in.count = 0;
72 io.lock.in.offset = 0;
73 status = smb_raw_lock(cli->tree, &io);
74 CHECK_STATUS(status, NT_STATUS_OK);
75 cli->session->pid++;
76 status = smb_raw_lock(cli->tree, &io);
77 CHECK_STATUS(status, NT_STATUS_OK);
78 cli->session->pid--;
79 io.lock.level = RAW_LOCK_UNLOCK;
80 status = smb_raw_lock(cli->tree, &io);
81 CHECK_STATUS(status, NT_STATUS_OK);
82
83 printf("Trying 0/1 lock\n");
84 io.lock.level = RAW_LOCK_LOCK;
85 io.lock.in.file.fnum = fnum;
86 io.lock.in.count = 1;
87 io.lock.in.offset = 0;
88 status = smb_raw_lock(cli->tree, &io);
89 CHECK_STATUS(status, NT_STATUS_OK);
90 cli->session->pid++;
91 status = smb_raw_lock(cli->tree, &io);
92 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
93 cli->session->pid--;
94 io.lock.level = RAW_LOCK_UNLOCK;
95 status = smb_raw_lock(cli->tree, &io);
96 CHECK_STATUS(status, NT_STATUS_OK);
97 io.lock.level = RAW_LOCK_UNLOCK;
98 status = smb_raw_lock(cli->tree, &io);
99 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
100
101 printf("Trying 0xEEFFFFFF lock\n");
102 io.lock.level = RAW_LOCK_LOCK;
103 io.lock.in.file.fnum = fnum;
104 io.lock.in.count = 4000;
105 io.lock.in.offset = 0xEEFFFFFF;
106 status = smb_raw_lock(cli->tree, &io);
107 CHECK_STATUS(status, NT_STATUS_OK);
108 cli->session->pid++;
109 status = smb_raw_lock(cli->tree, &io);
110 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
111 cli->session->pid--;
112 io.lock.level = RAW_LOCK_UNLOCK;
113 status = smb_raw_lock(cli->tree, &io);
114 CHECK_STATUS(status, NT_STATUS_OK);
115 io.lock.level = RAW_LOCK_UNLOCK;
116 status = smb_raw_lock(cli->tree, &io);
117 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
118
119 printf("Trying 0xEF000000 lock\n");
120 io.lock.level = RAW_LOCK_LOCK;
121 io.lock.in.file.fnum = fnum;
122 io.lock.in.count = 4000;
123 io.lock.in.offset = 0xEEFFFFFF;
124 status = smb_raw_lock(cli->tree, &io);
125 CHECK_STATUS(status, NT_STATUS_OK);
126 cli->session->pid++;
127 status = smb_raw_lock(cli->tree, &io);
128 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
129 cli->session->pid--;
130 io.lock.level = RAW_LOCK_UNLOCK;
131 status = smb_raw_lock(cli->tree, &io);
132 CHECK_STATUS(status, NT_STATUS_OK);
133 io.lock.level = RAW_LOCK_UNLOCK;
134 status = smb_raw_lock(cli->tree, &io);
135 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
136
137 printf("Trying max lock\n");
138 io.lock.level = RAW_LOCK_LOCK;
139 io.lock.in.file.fnum = fnum;
140 io.lock.in.count = 4000;
141 io.lock.in.offset = 0xEF000000;
142 status = smb_raw_lock(cli->tree, &io);
143 CHECK_STATUS(status, NT_STATUS_OK);
144 cli->session->pid++;
145 status = smb_raw_lock(cli->tree, &io);
146 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
147 cli->session->pid--;
148 io.lock.level = RAW_LOCK_UNLOCK;
149 status = smb_raw_lock(cli->tree, &io);
150 CHECK_STATUS(status, NT_STATUS_OK);
151 io.lock.level = RAW_LOCK_UNLOCK;
152 status = smb_raw_lock(cli->tree, &io);
153 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
154
155 printf("Trying wrong pid unlock\n");
156 io.lock.level = RAW_LOCK_LOCK;
157 io.lock.in.file.fnum = fnum;
158 io.lock.in.count = 4002;
159 io.lock.in.offset = 10001;
160 status = smb_raw_lock(cli->tree, &io);
161 CHECK_STATUS(status, NT_STATUS_OK);
162 cli->session->pid++;
163 io.lock.level = RAW_LOCK_UNLOCK;
164 status = smb_raw_lock(cli->tree, &io);
165 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
166 cli->session->pid--;
167 status = smb_raw_lock(cli->tree, &io);
168 CHECK_STATUS(status, NT_STATUS_OK);
169
170 done:
171 smbcli_close(cli->tree, fnum);
172 smb_raw_exit(cli->session);
173 smbcli_deltree(cli->tree, BASEDIR);
174 return ret;
175 }
176
177
178 /*
179 test locking&X ops
180 */
test_lockx(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)181 static BOOL test_lockx(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
182 {
183 union smb_lock io;
184 struct smb_lock_entry lock[1];
185 NTSTATUS status;
186 BOOL ret = True;
187 int fnum;
188 const char *fname = BASEDIR "\\test.txt";
189
190 if (!torture_setup_dir(cli, BASEDIR)) {
191 return False;
192 }
193
194 printf("Testing RAW_LOCK_LOCKX\n");
195 io.generic.level = RAW_LOCK_LOCKX;
196
197 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
198 if (fnum == -1) {
199 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
200 ret = False;
201 goto done;
202 }
203
204 io.lockx.level = RAW_LOCK_LOCKX;
205 io.lockx.in.file.fnum = fnum;
206 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
207 io.lockx.in.timeout = 0;
208 io.lockx.in.ulock_cnt = 0;
209 io.lockx.in.lock_cnt = 1;
210 lock[0].pid = cli->session->pid;
211 lock[0].offset = 10;
212 lock[0].count = 1;
213 io.lockx.in.locks = &lock[0];
214 status = smb_raw_lock(cli->tree, &io);
215 CHECK_STATUS(status, NT_STATUS_OK);
216
217
218 printf("Trying 0xEEFFFFFF lock\n");
219 io.lockx.in.ulock_cnt = 0;
220 io.lockx.in.lock_cnt = 1;
221 lock[0].count = 4000;
222 lock[0].offset = 0xEEFFFFFF;
223 status = smb_raw_lock(cli->tree, &io);
224 CHECK_STATUS(status, NT_STATUS_OK);
225 lock[0].pid++;
226 status = smb_raw_lock(cli->tree, &io);
227 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
228 lock[0].pid--;
229 io.lockx.in.ulock_cnt = 1;
230 io.lockx.in.lock_cnt = 0;
231 status = smb_raw_lock(cli->tree, &io);
232 CHECK_STATUS(status, NT_STATUS_OK);
233 status = smb_raw_lock(cli->tree, &io);
234 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
235
236 printf("Trying 0xEF000000 lock\n");
237 io.lockx.in.ulock_cnt = 0;
238 io.lockx.in.lock_cnt = 1;
239 lock[0].count = 4000;
240 lock[0].offset = 0xEF000000;
241 status = smb_raw_lock(cli->tree, &io);
242 CHECK_STATUS(status, NT_STATUS_OK);
243 lock[0].pid++;
244 status = smb_raw_lock(cli->tree, &io);
245 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
246 lock[0].pid--;
247 io.lockx.in.ulock_cnt = 1;
248 io.lockx.in.lock_cnt = 0;
249 status = smb_raw_lock(cli->tree, &io);
250 CHECK_STATUS(status, NT_STATUS_OK);
251 status = smb_raw_lock(cli->tree, &io);
252 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
253
254 printf("Trying zero lock\n");
255 io.lockx.in.ulock_cnt = 0;
256 io.lockx.in.lock_cnt = 1;
257 lock[0].count = 0;
258 lock[0].offset = ~0;
259 status = smb_raw_lock(cli->tree, &io);
260 CHECK_STATUS(status, NT_STATUS_OK);
261 lock[0].pid++;
262 status = smb_raw_lock(cli->tree, &io);
263 CHECK_STATUS(status, NT_STATUS_OK);
264 lock[0].pid--;
265 io.lockx.in.ulock_cnt = 1;
266 io.lockx.in.lock_cnt = 0;
267 status = smb_raw_lock(cli->tree, &io);
268 CHECK_STATUS(status, NT_STATUS_OK);
269 status = smb_raw_lock(cli->tree, &io);
270 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
271
272 printf("Trying max lock\n");
273 io.lockx.in.ulock_cnt = 0;
274 io.lockx.in.lock_cnt = 1;
275 lock[0].count = 0;
276 lock[0].offset = ~0;
277 status = smb_raw_lock(cli->tree, &io);
278 CHECK_STATUS(status, NT_STATUS_OK);
279 lock[0].pid++;
280 status = smb_raw_lock(cli->tree, &io);
281 CHECK_STATUS(status, NT_STATUS_OK);
282 lock[0].pid--;
283 io.lockx.in.ulock_cnt = 1;
284 io.lockx.in.lock_cnt = 0;
285 status = smb_raw_lock(cli->tree, &io);
286 CHECK_STATUS(status, NT_STATUS_OK);
287 status = smb_raw_lock(cli->tree, &io);
288 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
289
290 printf("Trying 2^63\n");
291 io.lockx.in.ulock_cnt = 0;
292 io.lockx.in.lock_cnt = 1;
293 lock[0].count = 1;
294 lock[0].offset = 1;
295 lock[0].offset <<= 63;
296 status = smb_raw_lock(cli->tree, &io);
297 CHECK_STATUS(status, NT_STATUS_OK);
298 lock[0].pid++;
299 status = smb_raw_lock(cli->tree, &io);
300 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
301 lock[0].pid--;
302 io.lockx.in.ulock_cnt = 1;
303 io.lockx.in.lock_cnt = 0;
304 status = smb_raw_lock(cli->tree, &io);
305 CHECK_STATUS(status, NT_STATUS_OK);
306 status = smb_raw_lock(cli->tree, &io);
307 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
308
309 printf("Trying 2^63 - 1\n");
310 io.lockx.in.ulock_cnt = 0;
311 io.lockx.in.lock_cnt = 1;
312 lock[0].count = 1;
313 lock[0].offset = 1;
314 lock[0].offset <<= 63;
315 lock[0].offset--;
316 status = smb_raw_lock(cli->tree, &io);
317 CHECK_STATUS(status, NT_STATUS_OK);
318 lock[0].pid++;
319 status = smb_raw_lock(cli->tree, &io);
320 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
321 lock[0].pid--;
322 io.lockx.in.ulock_cnt = 1;
323 io.lockx.in.lock_cnt = 0;
324 status = smb_raw_lock(cli->tree, &io);
325 CHECK_STATUS(status, NT_STATUS_OK);
326 status = smb_raw_lock(cli->tree, &io);
327 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
328
329 printf("Trying max lock 2\n");
330 io.lockx.in.ulock_cnt = 0;
331 io.lockx.in.lock_cnt = 1;
332 lock[0].count = 1;
333 lock[0].offset = ~0;
334 status = smb_raw_lock(cli->tree, &io);
335 CHECK_STATUS(status, NT_STATUS_OK);
336 lock[0].pid++;
337 lock[0].count = 2;
338 status = smb_raw_lock(cli->tree, &io);
339 CHECK_STATUS(status, NT_STATUS_OK);
340 lock[0].pid--;
341 io.lockx.in.ulock_cnt = 1;
342 io.lockx.in.lock_cnt = 0;
343 lock[0].count = 1;
344 status = smb_raw_lock(cli->tree, &io);
345 CHECK_STATUS(status, NT_STATUS_OK);
346 status = smb_raw_lock(cli->tree, &io);
347 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
348
349 done:
350 smbcli_close(cli->tree, fnum);
351 smb_raw_exit(cli->session);
352 smbcli_deltree(cli->tree, BASEDIR);
353 return ret;
354 }
355
356
357 /*
358 test high pid
359 */
test_pidhigh(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)360 static BOOL test_pidhigh(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
361 {
362 union smb_lock io;
363 struct smb_lock_entry lock[1];
364 NTSTATUS status;
365 BOOL ret = True;
366 int fnum;
367 const char *fname = BASEDIR "\\test.txt";
368 uint8_t c = 1;
369
370 if (!torture_setup_dir(cli, BASEDIR)) {
371 return False;
372 }
373
374 printf("Testing high pid\n");
375 io.generic.level = RAW_LOCK_LOCKX;
376
377 cli->session->pid = 1;
378
379 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
380 if (fnum == -1) {
381 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
382 ret = False;
383 goto done;
384 }
385
386 if (smbcli_write(cli->tree, fnum, 0, &c, 0, 1) != 1) {
387 printf("Failed to write 1 byte - %s\n", smbcli_errstr(cli->tree));
388 ret = False;
389 goto done;
390 }
391
392 io.lockx.level = RAW_LOCK_LOCKX;
393 io.lockx.in.file.fnum = fnum;
394 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
395 io.lockx.in.timeout = 0;
396 io.lockx.in.ulock_cnt = 0;
397 io.lockx.in.lock_cnt = 1;
398 lock[0].pid = cli->session->pid;
399 lock[0].offset = 0;
400 lock[0].count = 0xFFFFFFFF;
401 io.lockx.in.locks = &lock[0];
402 status = smb_raw_lock(cli->tree, &io);
403 CHECK_STATUS(status, NT_STATUS_OK);
404
405 if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
406 printf("Failed to read 1 byte - %s\n", smbcli_errstr(cli->tree));
407 ret = False;
408 goto done;
409 }
410
411 cli->session->pid |= 0x10000;
412
413 cli->session->pid = 2;
414
415 if (smbcli_read(cli->tree, fnum, &c, 0, 1) == 1) {
416 printf("pid is incorrect handled for read with lock!\n");
417 ret = False;
418 goto done;
419 }
420
421 cli->session->pid = 0x10001;
422
423 if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
424 printf("High pid is used on this server!\n");
425 ret = False;
426 } else {
427 printf("High pid is not used on this server (correct)\n");
428 }
429
430 done:
431 smbcli_close(cli->tree, fnum);
432 smb_raw_exit(cli->session);
433 smbcli_deltree(cli->tree, BASEDIR);
434 return ret;
435 }
436
437
438 /*
439 test locking&X async operation
440 */
test_async(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)441 static BOOL test_async(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
442 {
443 struct smbcli_session *session;
444 struct smb_composite_sesssetup setup;
445 struct smbcli_tree *tree;
446 union smb_tcon tcon;
447 const char *host, *share;
448 union smb_lock io;
449 struct smb_lock_entry lock[2];
450 NTSTATUS status;
451 BOOL ret = True;
452 int fnum;
453 const char *fname = BASEDIR "\\test.txt";
454 time_t t;
455 struct smbcli_request *req;
456
457 if (!torture_setup_dir(cli, BASEDIR)) {
458 return False;
459 }
460
461 printf("Testing LOCKING_ANDX_CANCEL_LOCK\n");
462 io.generic.level = RAW_LOCK_LOCKX;
463
464 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
465 if (fnum == -1) {
466 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
467 ret = False;
468 goto done;
469 }
470
471 io.lockx.level = RAW_LOCK_LOCKX;
472 io.lockx.in.file.fnum = fnum;
473 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
474 io.lockx.in.timeout = 0;
475 io.lockx.in.ulock_cnt = 0;
476 io.lockx.in.lock_cnt = 1;
477 lock[0].pid = cli->session->pid;
478 lock[0].offset = 100;
479 lock[0].count = 10;
480 io.lockx.in.locks = &lock[0];
481 status = smb_raw_lock(cli->tree, &io);
482 CHECK_STATUS(status, NT_STATUS_OK);
483
484 t = time(NULL);
485
486 printf("testing cancel by CANCEL_LOCK\n");
487
488 /* setup a timed lock */
489 io.lockx.in.timeout = 10000;
490 req = smb_raw_lock_send(cli->tree, &io);
491 if (req == NULL) {
492 printf("Failed to setup timed lock (%s)\n", __location__);
493 ret = False;
494 goto done;
495 }
496
497 /* cancel the wrong range */
498 lock[0].offset = 0;
499 io.lockx.in.timeout = 0;
500 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
501 status = smb_raw_lock(cli->tree, &io);
502 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
503
504 /* cancel with the wrong bits set */
505 lock[0].offset = 100;
506 io.lockx.in.timeout = 0;
507 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
508 status = smb_raw_lock(cli->tree, &io);
509 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
510
511 /* cancel the right range */
512 lock[0].offset = 100;
513 io.lockx.in.timeout = 0;
514 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
515 status = smb_raw_lock(cli->tree, &io);
516 CHECK_STATUS(status, NT_STATUS_OK);
517
518 /* receive the failed lock request */
519 status = smbcli_request_simple_recv(req);
520 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
521
522 if (time(NULL) > t+2) {
523 printf("lock cancel was not immediate (%s)\n", __location__);
524 ret = False;
525 goto done;
526 }
527
528 printf("testing cancel by unlock\n");
529 io.lockx.in.ulock_cnt = 0;
530 io.lockx.in.lock_cnt = 1;
531 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
532 io.lockx.in.timeout = 0;
533 status = smb_raw_lock(cli->tree, &io);
534 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
535
536 io.lockx.in.timeout = 5000;
537 req = smb_raw_lock_send(cli->tree, &io);
538 if (req == NULL) {
539 printf("Failed to setup timed lock (%s)\n", __location__);
540 ret = False;
541 goto done;
542 }
543
544 io.lockx.in.ulock_cnt = 1;
545 io.lockx.in.lock_cnt = 0;
546 status = smb_raw_lock(cli->tree, &io);
547 CHECK_STATUS(status, NT_STATUS_OK);
548
549 t = time(NULL);
550 status = smbcli_request_simple_recv(req);
551 CHECK_STATUS(status, NT_STATUS_OK);
552
553 if (time(NULL) > t+2) {
554 printf("lock cancel by unlock was not immediate (%s) - took %d secs\n",
555 __location__, (int)(time(NULL)-t));
556 ret = False;
557 goto done;
558 }
559
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);
567
568 t = time(NULL);
569 io.lockx.in.timeout = 10000;
570 req = smb_raw_lock_send(cli->tree, &io);
571 if (req == NULL) {
572 printf("Failed to setup timed lock (%s)\n", __location__);
573 ret = False;
574 goto done;
575 }
576
577 status = smbcli_close(cli->tree, fnum);
578 CHECK_STATUS(status, NT_STATUS_OK);
579
580 status = smbcli_request_simple_recv(req);
581 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
582
583 if (time(NULL) > t+2) {
584 printf("lock cancel by close was not immediate (%s)\n", __location__);
585 ret = False;
586 goto done;
587 }
588
589 printf("create a new sessions\n");
590 session = smbcli_session_init(cli->transport, mem_ctx, False);
591 setup.in.sesskey = cli->transport->negotiate.sesskey;
592 setup.in.capabilities = cli->transport->negotiate.capabilities;
593 setup.in.workgroup = lp_workgroup();
594 setup.in.credentials = cmdline_credentials;
595 status = smb_composite_sesssetup(session, &setup);
596 CHECK_STATUS(status, NT_STATUS_OK);
597 session->vuid = setup.out.vuid;
598
599 printf("create new tree context\n");
600 share = lp_parm_string(-1, "torture", "share");
601 host = lp_parm_string(-1, "torture", "host");
602 tree = smbcli_tree_init(session, mem_ctx, False);
603 tcon.generic.level = RAW_TCON_TCONX;
604 tcon.tconx.in.flags = 0;
605 tcon.tconx.in.password = data_blob(NULL, 0);
606 tcon.tconx.in.path = talloc_asprintf(mem_ctx, "\\\\%s\\%s", host, share);
607 tcon.tconx.in.device = "A:";
608 status = smb_raw_tcon(tree, mem_ctx, &tcon);
609 CHECK_STATUS(status, NT_STATUS_OK);
610 tree->tid = tcon.tconx.out.tid;
611
612 printf("testing cancel by exit\n");
613 fname = BASEDIR "\\test_exit.txt";
614 fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
615 if (fnum == -1) {
616 printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(tree));
617 ret = False;
618 goto done;
619 }
620 io.lockx.level = RAW_LOCK_LOCKX;
621 io.lockx.in.file.fnum = fnum;
622 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
623 io.lockx.in.timeout = 0;
624 io.lockx.in.ulock_cnt = 0;
625 io.lockx.in.lock_cnt = 1;
626 lock[0].pid = session->pid;
627 lock[0].offset = 100;
628 lock[0].count = 10;
629 io.lockx.in.locks = &lock[0];
630 status = smb_raw_lock(tree, &io);
631 CHECK_STATUS(status, NT_STATUS_OK);
632
633 io.lockx.in.ulock_cnt = 0;
634 io.lockx.in.lock_cnt = 1;
635 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
636 io.lockx.in.timeout = 0;
637 status = smb_raw_lock(tree, &io);
638 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
639
640 io.lockx.in.timeout = 10000;
641 t = time(NULL);
642 req = smb_raw_lock_send(tree, &io);
643 if (req == NULL) {
644 printf("Failed to setup timed lock (%s)\n", __location__);
645 ret = False;
646 goto done;
647 }
648
649 status = smb_raw_exit(session);
650 CHECK_STATUS(status, NT_STATUS_OK);
651
652 status = smbcli_request_simple_recv(req);
653 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
654
655 if (time(NULL) > t+2) {
656 printf("lock cancel by exit was not immediate (%s)\n", __location__);
657 ret = False;
658 goto done;
659 }
660
661 printf("testing cancel by ulogoff\n");
662 fname = BASEDIR "\\test_ulogoff.txt";
663 fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
664 if (fnum == -1) {
665 printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(tree));
666 ret = False;
667 goto done;
668 }
669 io.lockx.level = RAW_LOCK_LOCKX;
670 io.lockx.in.file.fnum = fnum;
671 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
672 io.lockx.in.timeout = 0;
673 io.lockx.in.ulock_cnt = 0;
674 io.lockx.in.lock_cnt = 1;
675 lock[0].pid = session->pid;
676 lock[0].offset = 100;
677 lock[0].count = 10;
678 io.lockx.in.locks = &lock[0];
679 status = smb_raw_lock(tree, &io);
680 CHECK_STATUS(status, NT_STATUS_OK);
681
682 io.lockx.in.ulock_cnt = 0;
683 io.lockx.in.lock_cnt = 1;
684 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
685 io.lockx.in.timeout = 0;
686 status = smb_raw_lock(tree, &io);
687 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
688
689 io.lockx.in.timeout = 10000;
690 t = time(NULL);
691 req = smb_raw_lock_send(tree, &io);
692 if (req == NULL) {
693 printf("Failed to setup timed lock (%s)\n", __location__);
694 ret = False;
695 goto done;
696 }
697
698 status = smb_raw_ulogoff(session);
699 CHECK_STATUS(status, NT_STATUS_OK);
700
701 status = smbcli_request_simple_recv(req);
702 if (NT_STATUS_EQUAL(NT_STATUS_FILE_LOCK_CONFLICT, status)) {
703 printf("lock not canceled by ulogoff - %s (ignored because of vfs_vifs fails it)\n",
704 nt_errstr(status));
705 smb_tree_disconnect(tree);
706 smb_raw_exit(session);
707 goto done;
708 }
709 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
710
711 if (time(NULL) > t+2) {
712 printf("lock cancel by ulogoff was not immediate (%s)\n", __location__);
713 ret = False;
714 goto done;
715 }
716
717 printf("testing cancel by tdis\n");
718 tree->session = cli->session;
719
720 fname = BASEDIR "\\test_tdis.txt";
721 fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
722 if (fnum == -1) {
723 printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(tree));
724 ret = False;
725 goto done;
726 }
727 io.lockx.level = RAW_LOCK_LOCKX;
728 io.lockx.in.file.fnum = fnum;
729 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
730 io.lockx.in.timeout = 0;
731 io.lockx.in.ulock_cnt = 0;
732 io.lockx.in.lock_cnt = 1;
733 lock[0].pid = cli->session->pid;
734 lock[0].offset = 100;
735 lock[0].count = 10;
736 io.lockx.in.locks = &lock[0];
737 status = smb_raw_lock(tree, &io);
738 CHECK_STATUS(status, NT_STATUS_OK);
739
740 status = smb_raw_lock(tree, &io);
741 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
742
743 io.lockx.in.timeout = 10000;
744 t = time(NULL);
745 req = smb_raw_lock_send(tree, &io);
746 if (req == NULL) {
747 printf("Failed to setup timed lock (%s)\n", __location__);
748 ret = False;
749 goto done;
750 }
751
752 status = smb_tree_disconnect(tree);
753 CHECK_STATUS(status, NT_STATUS_OK);
754
755 status = smbcli_request_simple_recv(req);
756 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
757
758 if (time(NULL) > t+2) {
759 printf("lock cancel by tdis was not immediate (%s)\n", __location__);
760 ret = False;
761 goto done;
762 }
763
764 done:
765 smb_raw_exit(cli->session);
766 smbcli_deltree(cli->tree, BASEDIR);
767 return ret;
768 }
769
770 /*
771 test NT_STATUS_LOCK_NOT_GRANTED vs. NT_STATUS_FILE_LOCK_CONFLICT
772 */
test_errorcode(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)773 static BOOL test_errorcode(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
774 {
775 union smb_lock io;
776 union smb_open op;
777 struct smb_lock_entry lock[2];
778 NTSTATUS status;
779 BOOL ret = True;
780 int fnum, fnum2;
781 const char *fname;
782 struct smbcli_request *req;
783 time_t start;
784 int t;
785
786 if (!torture_setup_dir(cli, BASEDIR)) {
787 return False;
788 }
789
790 printf("Testing LOCK_NOT_GRANTED vs. FILE_LOCK_CONFLICT\n");
791
792 printf("testing with timeout = 0\n");
793 fname = BASEDIR "\\test0.txt";
794 t = 0;
795
796 /*
797 * the first run is with t = 0,
798 * the second with t > 0 (=1)
799 */
800 next_run:
801 /*
802 * use the DENY_DOS mode, that creates two fnum's of one low-level file handle,
803 * this demonstrates that the cache is per fnum
804 */
805 op.openx.level = RAW_OPEN_OPENX;
806 op.openx.in.fname = fname;
807 op.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
808 op.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR | OPENX_MODE_DENY_DOS;
809 op.openx.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
810 op.openx.in.search_attrs = 0;
811 op.openx.in.file_attrs = 0;
812 op.openx.in.write_time = 0;
813 op.openx.in.size = 0;
814 op.openx.in.timeout = 0;
815
816 status = smb_raw_open(cli->tree, mem_ctx, &op);
817 CHECK_STATUS(status, NT_STATUS_OK);
818 fnum = op.openx.out.file.fnum;
819
820 status = smb_raw_open(cli->tree, mem_ctx, &op);
821 CHECK_STATUS(status, NT_STATUS_OK);
822 fnum2 = op.openx.out.file.fnum;
823
824 io.lockx.level = RAW_LOCK_LOCKX;
825 io.lockx.in.file.fnum = fnum;
826 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
827 io.lockx.in.timeout = t;
828 io.lockx.in.ulock_cnt = 0;
829 io.lockx.in.lock_cnt = 1;
830 lock[0].pid = cli->session->pid;
831 lock[0].offset = 100;
832 lock[0].count = 10;
833 io.lockx.in.locks = &lock[0];
834 status = smb_raw_lock(cli->tree, &io);
835 CHECK_STATUS(status, NT_STATUS_OK);
836
837 /*
838 * demonstrate that the first conflicting lock on each handle give LOCK_NOT_GRANTED
839 * this also demonstrates that the error code cache is per file handle
840 * (LOCK_NOT_GRANTED is only be used when timeout is 0!)
841 */
842 io.lockx.in.file.fnum = fnum2;
843 status = smb_raw_lock(cli->tree, &io);
844 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
845
846 io.lockx.in.file.fnum = fnum;
847 status = smb_raw_lock(cli->tree, &io);
848 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
849
850 /* demonstrate that each following conflict gives FILE_LOCK_CONFLICT */
851 io.lockx.in.file.fnum = fnum;
852 status = smb_raw_lock(cli->tree, &io);
853 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
854
855 io.lockx.in.file.fnum = fnum2;
856 status = smb_raw_lock(cli->tree, &io);
857 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
858
859 io.lockx.in.file.fnum = fnum;
860 status = smb_raw_lock(cli->tree, &io);
861 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
862
863 io.lockx.in.file.fnum = fnum2;
864 status = smb_raw_lock(cli->tree, &io);
865 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
866
867 /* demonstrate that the smbpid doesn't matter */
868 lock[0].pid++;
869 io.lockx.in.file.fnum = fnum;
870 status = smb_raw_lock(cli->tree, &io);
871 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
872
873 io.lockx.in.file.fnum = fnum2;
874 status = smb_raw_lock(cli->tree, &io);
875 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
876 lock[0].pid--;
877
878 /*
879 * demonstrate the a successful lock with count = 0 and the same offset,
880 * doesn't reset the error cache
881 */
882 lock[0].offset = 100;
883 lock[0].count = 0;
884 io.lockx.in.file.fnum = fnum;
885 status = smb_raw_lock(cli->tree, &io);
886 CHECK_STATUS(status, NT_STATUS_OK);
887
888 io.lockx.in.file.fnum = fnum2;
889 status = smb_raw_lock(cli->tree, &io);
890 CHECK_STATUS(status, NT_STATUS_OK);
891
892 lock[0].offset = 100;
893 lock[0].count = 10;
894 io.lockx.in.file.fnum = fnum;
895 status = smb_raw_lock(cli->tree, &io);
896 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
897
898 io.lockx.in.file.fnum = fnum2;
899 status = smb_raw_lock(cli->tree, &io);
900 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
901
902 /*
903 * demonstrate the a successful lock with count = 0 and outside the locked range,
904 * doesn't reset the error cache
905 */
906 lock[0].offset = 110;
907 lock[0].count = 0;
908 io.lockx.in.file.fnum = fnum;
909 status = smb_raw_lock(cli->tree, &io);
910 CHECK_STATUS(status, NT_STATUS_OK);
911
912 io.lockx.in.file.fnum = fnum2;
913 status = smb_raw_lock(cli->tree, &io);
914 CHECK_STATUS(status, NT_STATUS_OK);
915
916 lock[0].offset = 100;
917 lock[0].count = 10;
918 io.lockx.in.file.fnum = fnum;
919 status = smb_raw_lock(cli->tree, &io);
920 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
921
922 io.lockx.in.file.fnum = fnum2;
923 status = smb_raw_lock(cli->tree, &io);
924 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
925
926 lock[0].offset = 99;
927 lock[0].count = 0;
928 io.lockx.in.file.fnum = fnum;
929 status = smb_raw_lock(cli->tree, &io);
930 CHECK_STATUS(status, NT_STATUS_OK);
931
932 io.lockx.in.file.fnum = fnum2;
933 status = smb_raw_lock(cli->tree, &io);
934 CHECK_STATUS(status, NT_STATUS_OK);
935
936 lock[0].offset = 100;
937 lock[0].count = 10;
938 io.lockx.in.file.fnum = fnum;
939 status = smb_raw_lock(cli->tree, &io);
940 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
941
942 io.lockx.in.file.fnum = fnum2;
943 status = smb_raw_lock(cli->tree, &io);
944 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
945
946 /* demonstrate that a changing count doesn't reset the error cache */
947 lock[0].offset = 100;
948 lock[0].count = 5;
949 io.lockx.in.file.fnum = fnum;
950 status = smb_raw_lock(cli->tree, &io);
951 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
952
953 io.lockx.in.file.fnum = fnum2;
954 status = smb_raw_lock(cli->tree, &io);
955 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
956
957 lock[0].offset = 100;
958 lock[0].count = 15;
959 io.lockx.in.file.fnum = fnum;
960 status = smb_raw_lock(cli->tree, &io);
961 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
962
963 io.lockx.in.file.fnum = fnum2;
964 status = smb_raw_lock(cli->tree, &io);
965 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
966
967 /*
968 * demonstrate the a lock with count = 0 and inside the locked range,
969 * fails and resets the error cache
970 */
971 lock[0].offset = 101;
972 lock[0].count = 0;
973 io.lockx.in.file.fnum = fnum;
974 status = smb_raw_lock(cli->tree, &io);
975 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
976 status = smb_raw_lock(cli->tree, &io);
977 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
978
979 io.lockx.in.file.fnum = fnum2;
980 status = smb_raw_lock(cli->tree, &io);
981 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
982 status = smb_raw_lock(cli->tree, &io);
983 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
984
985 lock[0].offset = 100;
986 lock[0].count = 10;
987 io.lockx.in.file.fnum = fnum;
988 status = smb_raw_lock(cli->tree, &io);
989 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
990 status = smb_raw_lock(cli->tree, &io);
991 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
992
993 io.lockx.in.file.fnum = fnum2;
994 status = smb_raw_lock(cli->tree, &io);
995 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
996 status = smb_raw_lock(cli->tree, &io);
997 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
998
999 /* demonstrate the a changing offset, resets the error cache */
1000 lock[0].offset = 105;
1001 lock[0].count = 10;
1002 io.lockx.in.file.fnum = fnum;
1003 status = smb_raw_lock(cli->tree, &io);
1004 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1005 status = smb_raw_lock(cli->tree, &io);
1006 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1007
1008 io.lockx.in.file.fnum = fnum2;
1009 status = smb_raw_lock(cli->tree, &io);
1010 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1011 status = smb_raw_lock(cli->tree, &io);
1012 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1013
1014 lock[0].offset = 100;
1015 lock[0].count = 10;
1016 io.lockx.in.file.fnum = fnum;
1017 status = smb_raw_lock(cli->tree, &io);
1018 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1019 status = smb_raw_lock(cli->tree, &io);
1020 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1021
1022 io.lockx.in.file.fnum = fnum2;
1023 status = smb_raw_lock(cli->tree, &io);
1024 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1025 status = smb_raw_lock(cli->tree, &io);
1026 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1027
1028 lock[0].offset = 95;
1029 lock[0].count = 9;
1030 io.lockx.in.file.fnum = fnum;
1031 status = smb_raw_lock(cli->tree, &io);
1032 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1033 status = smb_raw_lock(cli->tree, &io);
1034 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1035
1036 io.lockx.in.file.fnum = fnum2;
1037 status = smb_raw_lock(cli->tree, &io);
1038 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1039 status = smb_raw_lock(cli->tree, &io);
1040 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1041
1042 lock[0].offset = 100;
1043 lock[0].count = 10;
1044 io.lockx.in.file.fnum = fnum;
1045 status = smb_raw_lock(cli->tree, &io);
1046 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1047 status = smb_raw_lock(cli->tree, &io);
1048 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1049
1050 io.lockx.in.file.fnum = fnum2;
1051 status = smb_raw_lock(cli->tree, &io);
1052 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1053 status = smb_raw_lock(cli->tree, &io);
1054 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1055
1056 /*
1057 * demonstrate the a successful lock in a different range,
1058 * doesn't reset the cache, the failing lock on the 2nd handle
1059 * resets the resets the cache
1060 */
1061 lock[0].offset = 120;
1062 lock[0].count = 15;
1063 io.lockx.in.file.fnum = fnum;
1064 status = smb_raw_lock(cli->tree, &io);
1065 CHECK_STATUS(status, NT_STATUS_OK);
1066
1067 io.lockx.in.file.fnum = fnum2;
1068 status = smb_raw_lock(cli->tree, &io);
1069 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1070
1071 lock[0].offset = 100;
1072 lock[0].count = 10;
1073 io.lockx.in.file.fnum = fnum;
1074 status = smb_raw_lock(cli->tree, &io);
1075 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1076 status = smb_raw_lock(cli->tree, &io);
1077 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1078
1079 io.lockx.in.file.fnum = fnum2;
1080 status = smb_raw_lock(cli->tree, &io);
1081 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1082 status = smb_raw_lock(cli->tree, &io);
1083 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1084
1085 /* end of the loop */
1086 if (t == 0) {
1087 smb_raw_exit(cli->session);
1088 printf("testing with timeout > 0 (=1)\n");
1089 fname = BASEDIR "\\test1.txt";
1090 t = 1;
1091 goto next_run;
1092 }
1093
1094 /*
1095 * the following 3 test sections demonstrate that
1096 * the cache is only set when the error is reported
1097 * to the client (after the timeout went by)
1098 */
1099 smb_raw_exit(cli->session);
1100 printf("testing a conflict while a lock is pending\n");
1101 fname = BASEDIR "\\test2.txt";
1102 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1103 if (fnum == -1) {
1104 printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(cli->tree));
1105 ret = False;
1106 goto done;
1107 }
1108 io.lockx.level = RAW_LOCK_LOCKX;
1109 io.lockx.in.file.fnum = fnum;
1110 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1111 io.lockx.in.timeout = 0;
1112 io.lockx.in.ulock_cnt = 0;
1113 io.lockx.in.lock_cnt = 1;
1114 lock[0].pid = cli->session->pid;
1115 lock[0].offset = 100;
1116 lock[0].count = 10;
1117 io.lockx.in.locks = &lock[0];
1118 status = smb_raw_lock(cli->tree, &io);
1119 CHECK_STATUS(status, NT_STATUS_OK);
1120
1121 start = time(NULL);
1122 io.lockx.in.timeout = 1000;
1123 req = smb_raw_lock_send(cli->tree, &io);
1124 if (req == NULL) {
1125 printf("Failed to setup timed lock (%s)\n", __location__);
1126 ret = False;
1127 goto done;
1128 }
1129
1130 io.lockx.in.timeout = 0;
1131 lock[0].offset = 105;
1132 lock[0].count = 10;
1133 status = smb_raw_lock(cli->tree, &io);
1134 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1135
1136 status = smbcli_request_simple_recv(req);
1137 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1138
1139 status = smb_raw_lock(cli->tree, &io);
1140 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1141
1142 if (time(NULL) < start+1) {
1143 printf("lock comes back to early (%s)\n", __location__);
1144 ret = False;
1145 goto done;
1146 }
1147
1148 smbcli_close(cli->tree, fnum);
1149 fname = BASEDIR "\\test3.txt";
1150 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1151 if (fnum == -1) {
1152 printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(cli->tree));
1153 ret = False;
1154 goto done;
1155 }
1156 io.lockx.level = RAW_LOCK_LOCKX;
1157 io.lockx.in.file.fnum = fnum;
1158 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1159 io.lockx.in.timeout = 0;
1160 io.lockx.in.ulock_cnt = 0;
1161 io.lockx.in.lock_cnt = 1;
1162 lock[0].pid = cli->session->pid;
1163 lock[0].offset = 100;
1164 lock[0].count = 10;
1165 io.lockx.in.locks = &lock[0];
1166 status = smb_raw_lock(cli->tree, &io);
1167 CHECK_STATUS(status, NT_STATUS_OK);
1168
1169 start = time(NULL);
1170 io.lockx.in.timeout = 1000;
1171 req = smb_raw_lock_send(cli->tree, &io);
1172 if (req == NULL) {
1173 printf("Failed to setup timed lock (%s)\n", __location__);
1174 ret = False;
1175 goto done;
1176 }
1177
1178 io.lockx.in.timeout = 0;
1179 lock[0].offset = 105;
1180 lock[0].count = 10;
1181 status = smb_raw_lock(cli->tree, &io);
1182 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1183
1184 status = smbcli_request_simple_recv(req);
1185 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1186
1187 lock[0].offset = 100;
1188 lock[0].count = 10;
1189 status = smb_raw_lock(cli->tree, &io);
1190 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1191
1192 if (time(NULL) < start+1) {
1193 printf("lock comes back to early (%s)\n", __location__);
1194 ret = False;
1195 goto done;
1196 }
1197
1198 smbcli_close(cli->tree, fnum);
1199 fname = BASEDIR "\\test4.txt";
1200 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1201 if (fnum == -1) {
1202 printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(cli->tree));
1203 ret = False;
1204 goto done;
1205 }
1206 io.lockx.level = RAW_LOCK_LOCKX;
1207 io.lockx.in.file.fnum = fnum;
1208 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1209 io.lockx.in.timeout = 0;
1210 io.lockx.in.ulock_cnt = 0;
1211 io.lockx.in.lock_cnt = 1;
1212 lock[0].pid = cli->session->pid;
1213 lock[0].offset = 100;
1214 lock[0].count = 10;
1215 io.lockx.in.locks = &lock[0];
1216 status = smb_raw_lock(cli->tree, &io);
1217 CHECK_STATUS(status, NT_STATUS_OK);
1218
1219 start = time(NULL);
1220 io.lockx.in.timeout = 1000;
1221 req = smb_raw_lock_send(cli->tree, &io);
1222 if (req == NULL) {
1223 printf("Failed to setup timed lock (%s)\n", __location__);
1224 ret = False;
1225 goto done;
1226 }
1227
1228 io.lockx.in.timeout = 0;
1229 status = smb_raw_lock(cli->tree, &io);
1230 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1231
1232 status = smbcli_request_simple_recv(req);
1233 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1234
1235 status = smb_raw_lock(cli->tree, &io);
1236 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1237
1238 if (time(NULL) < start+1) {
1239 printf("lock comes back to early (%s)\n", __location__);
1240 ret = False;
1241 goto done;
1242 }
1243
1244 done:
1245 smb_raw_exit(cli->session);
1246 smbcli_deltree(cli->tree, BASEDIR);
1247 return ret;
1248 }
1249
1250
1251 /*
1252 test LOCKING_ANDX_CHANGE_LOCKTYPE
1253 */
test_changetype(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)1254 static BOOL test_changetype(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
1255 {
1256 union smb_lock io;
1257 struct smb_lock_entry lock[2];
1258 NTSTATUS status;
1259 BOOL ret = True;
1260 int fnum;
1261 uint8_t c = 0;
1262 const char *fname = BASEDIR "\\test.txt";
1263
1264 if (!torture_setup_dir(cli, BASEDIR)) {
1265 return False;
1266 }
1267
1268 printf("Testing LOCKING_ANDX_CHANGE_LOCKTYPE\n");
1269 io.generic.level = RAW_LOCK_LOCKX;
1270
1271 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1272 if (fnum == -1) {
1273 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
1274 ret = False;
1275 goto done;
1276 }
1277
1278 io.lockx.level = RAW_LOCK_LOCKX;
1279 io.lockx.in.file.fnum = fnum;
1280 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1281 io.lockx.in.timeout = 0;
1282 io.lockx.in.ulock_cnt = 0;
1283 io.lockx.in.lock_cnt = 1;
1284 lock[0].pid = cli->session->pid;
1285 lock[0].offset = 100;
1286 lock[0].count = 10;
1287 io.lockx.in.locks = &lock[0];
1288 status = smb_raw_lock(cli->tree, &io);
1289 CHECK_STATUS(status, NT_STATUS_OK);
1290
1291 if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
1292 printf("allowed write on read locked region (%s)\n", __location__);
1293 ret = False;
1294 goto done;
1295 }
1296
1297 /* windows server don't seem to support this */
1298 io.lockx.in.mode = LOCKING_ANDX_CHANGE_LOCKTYPE;
1299 status = smb_raw_lock(cli->tree, &io);
1300 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
1301
1302 if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
1303 printf("allowed write after lock change (%s)\n", __location__);
1304 ret = False;
1305 goto done;
1306 }
1307
1308 done:
1309 smbcli_close(cli->tree, fnum);
1310 smb_raw_exit(cli->session);
1311 smbcli_deltree(cli->tree, BASEDIR);
1312 return ret;
1313 }
1314
1315
1316 /*
1317 basic testing of lock calls
1318 */
torture_raw_lock(struct torture_context * torture)1319 BOOL torture_raw_lock(struct torture_context *torture)
1320 {
1321 struct smbcli_state *cli;
1322 BOOL ret = True;
1323 TALLOC_CTX *mem_ctx;
1324
1325 if (!torture_open_connection(&cli, 0)) {
1326 return False;
1327 }
1328
1329 mem_ctx = talloc_init("torture_raw_lock");
1330
1331 ret &= test_lockx(cli, mem_ctx);
1332 ret &= test_lock(cli, mem_ctx);
1333 ret &= test_pidhigh(cli, mem_ctx);
1334 ret &= test_async(cli, mem_ctx);
1335 ret &= test_errorcode(cli, mem_ctx);
1336 ret &= test_changetype(cli, mem_ctx);
1337
1338 torture_close_connection(cli);
1339 talloc_free(mem_ctx);
1340 return ret;
1341 }
1342