s4:torture: remove an unused variable and bogus check from the defer_open test
[Samba.git] / source4 / torture / basic / base.c
blob5e5d6b9eecd725b5ebb5e8d721052a052a2ce8e4
1 /*
2 Unix SMB/CIFS implementation.
3 SMB torture tester
4 Copyright (C) Andrew Tridgell 1997-2003
5 Copyright (C) Jelmer Vernooij 2006
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
22 #include "torture/smbtorture.h"
23 #include "torture/basic/proto.h"
24 #include "libcli/libcli.h"
25 #include "libcli/raw/raw_proto.h"
26 #include "torture/util.h"
27 #include "system/filesys.h"
28 #include "system/time.h"
29 #include "libcli/resolve/resolve.h"
30 #include "lib/events/events.h"
31 #include "param/param.h"
34 #define CHECK_MAX_FAILURES(label) do { if (++failures >= torture_failures) goto label; } while (0)
37 static struct smbcli_state *open_nbt_connection(struct torture_context *tctx)
39 struct nbt_name called, calling;
40 struct smbcli_state *cli;
41 const char *host = torture_setting_string(tctx, "host", NULL);
42 struct smbcli_options options;
43 bool ok;
45 make_nbt_name_client(&calling, lpcfg_netbios_name(tctx->lp_ctx));
47 nbt_choose_called_name(NULL, &called, host, NBT_NAME_SERVER);
49 cli = smbcli_state_init(NULL);
50 if (!cli) {
51 torture_result(tctx, TORTURE_FAIL, "Failed initialize smbcli_struct to connect with %s\n", host);
52 goto failed;
55 lpcfg_smbcli_options(tctx->lp_ctx, &options);
57 ok = smbcli_socket_connect(cli, host, lpcfg_smb_ports(tctx->lp_ctx),
58 tctx->ev,
59 lpcfg_resolve_context(tctx->lp_ctx),
60 &options,
61 lpcfg_socket_options(tctx->lp_ctx),
62 &calling, &called);
63 if (!ok) {
64 torture_result(tctx, TORTURE_FAIL, "Failed to connect with %s\n", host);
65 goto failed;
68 cli->transport = smbcli_transport_init(cli->sock, cli,
69 true, &cli->options);
70 cli->sock = NULL;
71 if (!cli->transport) {
72 torture_result(tctx, TORTURE_FAIL, "smbcli_transport_init failed\n");
73 goto failed;
76 return cli;
78 failed:
79 talloc_free(cli);
80 return NULL;
83 static bool tcon_devtest(struct torture_context *tctx,
84 struct smbcli_state *cli,
85 const char *myshare, const char *devtype,
86 NTSTATUS expected_error)
88 bool status;
89 const char *password = torture_setting_string(tctx, "password", NULL);
91 status = NT_STATUS_IS_OK(smbcli_tconX(cli, myshare, devtype,
92 password));
94 torture_comment(tctx, "Trying share %s with devtype %s\n", myshare, devtype);
96 if (NT_STATUS_IS_OK(expected_error)) {
97 if (!status) {
98 torture_fail(tctx, talloc_asprintf(tctx,
99 "tconX to share %s with type %s "
100 "should have succeeded but failed",
101 myshare, devtype));
103 smbcli_tdis(cli);
104 } else {
105 if (status) {
106 torture_fail(tctx, talloc_asprintf(tctx,
107 "tconx to share %s with type %s "
108 "should have failed but succeeded",
109 myshare, devtype));
110 } else {
111 if (NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),
112 expected_error)) {
113 } else {
114 torture_fail(tctx, "Returned unexpected error");
118 return true;
124 test whether fnums and tids open on one VC are available on another (a major
125 security hole)
127 static bool run_fdpasstest(struct torture_context *tctx,
128 struct smbcli_state *cli1,
129 struct smbcli_state *cli2)
131 const char *fname = "\\fdpass.tst";
132 int fnum1, oldtid;
133 uint8_t buf[1024];
135 smbcli_unlink(cli1->tree, fname);
137 torture_comment(tctx, "Opening a file on connection 1\n");
139 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
140 torture_assert(tctx, fnum1 != -1,
141 talloc_asprintf(tctx,
142 "open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree)));
144 torture_comment(tctx, "writing to file on connection 1\n");
146 torture_assert(tctx,
147 smbcli_write(cli1->tree, fnum1, 0, "hello world\n", 0, 13) == 13,
148 talloc_asprintf(tctx,
149 "write failed (%s)\n", smbcli_errstr(cli1->tree)));
151 oldtid = cli2->tree->tid;
152 cli2->session->vuid = cli1->session->vuid;
153 cli2->tree->tid = cli1->tree->tid;
154 cli2->session->pid = cli1->session->pid;
156 torture_comment(tctx, "reading from file on connection 2\n");
158 torture_assert(tctx, smbcli_read(cli2->tree, fnum1, buf, 0, 13) != 13,
159 talloc_asprintf(tctx,
160 "read succeeded! nasty security hole [%s]\n", buf));
162 smbcli_close(cli1->tree, fnum1);
163 smbcli_unlink(cli1->tree, fname);
165 cli2->tree->tid = oldtid;
167 return true;
171 This checks how the getatr calls works
173 static bool run_attrtest(struct torture_context *tctx,
174 struct smbcli_state *cli)
176 int fnum;
177 time_t t, t2;
178 const char *fname = "\\attrib123456789.tst";
179 bool correct = true;
181 smbcli_unlink(cli->tree, fname);
182 fnum = smbcli_open(cli->tree, fname,
183 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
184 smbcli_close(cli->tree, fnum);
186 if (NT_STATUS_IS_ERR(smbcli_getatr(cli->tree, fname, NULL, NULL, &t))) {
187 torture_result(tctx, TORTURE_FAIL, "getatr failed (%s)\n", smbcli_errstr(cli->tree));
188 correct = false;
191 torture_comment(tctx, "New file time is %s", ctime(&t));
193 if (abs(t - time(NULL)) > 60*60*24*10) {
194 torture_result(tctx, TORTURE_FAIL, "ERROR: SMBgetatr bug. time is %s",
195 ctime(&t));
196 t = time(NULL);
197 correct = false;
200 t2 = t-60*60*24; /* 1 day ago */
202 torture_comment(tctx, "Setting file time to %s", ctime(&t2));
204 if (NT_STATUS_IS_ERR(smbcli_setatr(cli->tree, fname, 0, t2))) {
205 torture_comment(tctx, "setatr failed (%s)\n", smbcli_errstr(cli->tree));
206 correct = true;
209 if (NT_STATUS_IS_ERR(smbcli_getatr(cli->tree, fname, NULL, NULL, &t))) {
210 torture_comment(tctx, "getatr failed (%s)\n", smbcli_errstr(cli->tree));
211 correct = true;
214 torture_comment(tctx, "Retrieved file time as %s", ctime(&t));
216 if (t != t2) {
217 torture_comment(tctx, "ERROR: getatr/setatr bug. times are\n%s",
218 ctime(&t));
219 torture_comment(tctx, "%s", ctime(&t2));
220 correct = true;
223 smbcli_unlink(cli->tree, fname);
225 return correct;
229 This checks a couple of trans2 calls
231 static bool run_trans2test(struct torture_context *tctx,
232 struct smbcli_state *cli)
234 int fnum;
235 size_t size;
236 time_t c_time, a_time, m_time, w_time, m_time2;
237 const char *fname = "\\trans2.tst";
238 const char *dname = "\\trans2";
239 const char *fname2 = "\\trans2\\trans2.tst";
240 const char *pname;
241 bool correct = true;
243 smbcli_unlink(cli->tree, fname);
245 torture_comment(tctx, "Testing qfileinfo\n");
247 fnum = smbcli_open(cli->tree, fname,
248 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
249 if (NT_STATUS_IS_ERR(smbcli_qfileinfo(cli->tree, fnum, NULL, &size, &c_time, &a_time, &m_time,
250 NULL, NULL))) {
251 torture_result(tctx, TORTURE_FAIL, "ERROR: qfileinfo failed (%s)\n", smbcli_errstr(cli->tree));
252 correct = false;
255 torture_comment(tctx, "Testing NAME_INFO\n");
257 if (NT_STATUS_IS_ERR(smbcli_qfilename(cli->tree, fnum, &pname))) {
258 torture_result(tctx, TORTURE_FAIL, "ERROR: qfilename failed (%s)\n", smbcli_errstr(cli->tree));
259 correct = false;
262 if (!pname || strcmp(pname, fname)) {
263 torture_result(tctx, TORTURE_FAIL, "qfilename gave different name? [%s] [%s]\n",
264 fname, pname);
265 correct = false;
268 smbcli_close(cli->tree, fnum);
269 smbcli_unlink(cli->tree, fname);
271 fnum = smbcli_open(cli->tree, fname,
272 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
273 if (fnum == -1) {
274 torture_result(tctx, TORTURE_FAIL, "open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
275 return false;
277 smbcli_close(cli->tree, fnum);
279 torture_comment(tctx, "Checking for sticky create times\n");
281 if (NT_STATUS_IS_ERR(smbcli_qpathinfo(cli->tree, fname, &c_time, &a_time, &m_time, &size, NULL))) {
282 torture_result(tctx, TORTURE_FAIL, "ERROR: qpathinfo failed (%s)\n", smbcli_errstr(cli->tree));
283 correct = false;
284 } else {
285 time_t t = time(NULL);
287 if (c_time != m_time) {
288 torture_comment(tctx, "create time=%s", ctime(&c_time));
289 torture_comment(tctx, "modify time=%s", ctime(&m_time));
290 torture_comment(tctx, "This system appears to have sticky create times\n");
292 if ((abs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
293 torture_comment(tctx, "access time=%s", ctime(&a_time));
294 torture_result(tctx, TORTURE_FAIL, "This system appears to set a midnight access time\n");
295 correct = false;
298 if (abs(m_time - t) > 60*60*24*7) {
299 torture_result(tctx, TORTURE_FAIL, "ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
300 correct = false;
305 smbcli_unlink(cli->tree, fname);
306 fnum = smbcli_open(cli->tree, fname,
307 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
308 smbcli_close(cli->tree, fnum);
309 if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, fname, &c_time, &a_time, &m_time, &w_time, &size, NULL, NULL))) {
310 torture_result(tctx, TORTURE_FAIL, "ERROR: qpathinfo2 failed (%s)\n", smbcli_errstr(cli->tree));
311 correct = false;
312 } else {
313 if (w_time < 60*60*24*2) {
314 torture_comment(tctx, "write time=%s", ctime(&w_time));
315 torture_result(tctx, TORTURE_FAIL, "This system appears to set a initial 0 write time\n");
316 correct = false;
320 smbcli_unlink(cli->tree, fname);
323 /* check if the server updates the directory modification time
324 when creating a new file */
325 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, dname))) {
326 torture_result(tctx, TORTURE_FAIL, "ERROR: mkdir failed (%s)\n", smbcli_errstr(cli->tree));
327 correct = false;
329 sleep(3);
330 if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, "\\trans2\\", &c_time, &a_time, &m_time, &w_time, &size, NULL, NULL))) {
331 torture_result(tctx, TORTURE_FAIL, "ERROR: qpathinfo2 failed (%s)\n", smbcli_errstr(cli->tree));
332 correct = false;
335 fnum = smbcli_open(cli->tree, fname2,
336 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
337 smbcli_write(cli->tree, fnum, 0, &fnum, 0, sizeof(fnum));
338 smbcli_close(cli->tree, fnum);
339 if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, "\\trans2\\", &c_time, &a_time, &m_time2, &w_time, &size, NULL, NULL))) {
340 torture_result(tctx, TORTURE_FAIL, "ERROR: qpathinfo2 failed (%s)\n", smbcli_errstr(cli->tree));
341 correct = false;
342 } else {
343 if (m_time2 == m_time) {
344 torture_result(tctx, TORTURE_FAIL, "This system does not update directory modification times\n");
345 correct = false;
348 smbcli_unlink(cli->tree, fname2);
349 smbcli_rmdir(cli->tree, dname);
351 return correct;
354 /* send smb negprot commands, not reading the response */
355 static bool run_negprot_nowait(struct torture_context *tctx)
357 int i;
358 struct smbcli_state *cli, *cli2;
359 bool correct = true;
361 torture_comment(tctx, "starting negprot nowait test\n");
363 cli = open_nbt_connection(tctx);
364 if (!cli) {
365 return false;
368 torture_comment(tctx, "Filling send buffer\n");
370 for (i=0;i<100;i++) {
371 struct tevent_req *req;
372 req = smb_raw_negotiate_send(cli, tctx->ev,
373 cli->transport,
374 PROTOCOL_NT1);
375 tevent_loop_once(tctx->ev);
376 if (!tevent_req_is_in_progress(req)) {
377 NTSTATUS status;
379 status = smb_raw_negotiate_recv(req);
380 TALLOC_FREE(req);
381 if (i > 0) {
382 torture_comment(tctx, "Failed to fill pipe packet[%d] - %s (ignored)\n",
383 i+1, nt_errstr(status));
384 break;
385 } else {
386 torture_result(tctx, TORTURE_FAIL, "Failed to fill pipe - %s \n",
387 nt_errstr(status));
388 torture_close_connection(cli);
389 return false;
394 torture_comment(tctx, "Opening secondary connection\n");
395 if (!torture_open_connection(&cli2, tctx, 1)) {
396 torture_result(tctx, TORTURE_FAIL, "Failed to open secondary connection\n");
397 correct = false;
400 if (!torture_close_connection(cli2)) {
401 torture_result(tctx, TORTURE_FAIL, "Failed to close secondary connection\n");
402 correct = false;
405 torture_close_connection(cli);
407 return correct;
411 this checks to see if a secondary tconx can use open files from an
412 earlier tconx
414 static bool run_tcon_test(struct torture_context *tctx, struct smbcli_state *cli)
416 const char *fname = "\\tcontest.tmp";
417 int fnum1;
418 uint16_t cnum1, cnum2, cnum3;
419 uint16_t vuid1, vuid2;
420 uint8_t buf[4];
421 bool ret = true;
422 struct smbcli_tree *tree1;
423 const char *host = torture_setting_string(tctx, "host", NULL);
424 const char *share = torture_setting_string(tctx, "share", NULL);
425 const char *password = torture_setting_string(tctx, "password", NULL);
427 if (smbcli_deltree(cli->tree, fname) == -1) {
428 torture_comment(tctx, "unlink of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
431 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
432 if (fnum1 == -1) {
433 torture_result(tctx, TORTURE_FAIL, "open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
434 return false;
437 cnum1 = cli->tree->tid;
438 vuid1 = cli->session->vuid;
440 memset(buf, 0, 4); /* init buf so valgrind won't complain */
441 if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) != 4) {
442 torture_result(tctx, TORTURE_FAIL, "initial write failed (%s)\n", smbcli_errstr(cli->tree));
443 return false;
446 tree1 = cli->tree; /* save old tree connection */
447 if (NT_STATUS_IS_ERR(smbcli_tconX(cli, share, "?????", password))) {
448 torture_result(tctx, TORTURE_FAIL, "%s refused 2nd tree connect (%s)\n", host,
449 smbcli_errstr(cli->tree));
450 talloc_free(cli);
451 return false;
454 cnum2 = cli->tree->tid;
455 cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
456 vuid2 = cli->session->vuid + 1;
458 /* try a write with the wrong tid */
459 cli->tree->tid = cnum2;
461 if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
462 torture_result(tctx, TORTURE_FAIL, "* server allows write with wrong TID\n");
463 ret = false;
464 } else {
465 torture_comment(tctx, "server fails write with wrong TID : %s\n", smbcli_errstr(cli->tree));
469 /* try a write with an invalid tid */
470 cli->tree->tid = cnum3;
472 if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
473 torture_result(tctx, TORTURE_FAIL, "* server allows write with invalid TID\n");
474 ret = false;
475 } else {
476 torture_comment(tctx, "server fails write with invalid TID : %s\n", smbcli_errstr(cli->tree));
479 /* try a write with an invalid vuid */
480 cli->session->vuid = vuid2;
481 cli->tree->tid = cnum1;
483 if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
484 torture_result(tctx, TORTURE_FAIL, "* server allows write with invalid VUID\n");
485 ret = false;
486 } else {
487 torture_comment(tctx, "server fails write with invalid VUID : %s\n", smbcli_errstr(cli->tree));
490 cli->session->vuid = vuid1;
491 cli->tree->tid = cnum1;
493 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum1))) {
494 torture_result(tctx, TORTURE_FAIL, "close failed (%s)\n", smbcli_errstr(cli->tree));
495 return false;
498 cli->tree->tid = cnum2;
500 if (NT_STATUS_IS_ERR(smbcli_tdis(cli))) {
501 torture_result(tctx, TORTURE_FAIL, "secondary tdis failed (%s)\n", smbcli_errstr(cli->tree));
502 return false;
505 cli->tree = tree1; /* restore initial tree */
506 cli->tree->tid = cnum1;
508 smbcli_unlink(tree1, fname);
510 return ret;
514 checks for correct tconX support
516 static bool run_tcon_devtype_test(struct torture_context *tctx,
517 struct smbcli_state *cli1)
519 const char *share = torture_setting_string(tctx, "share", NULL);
521 if (!tcon_devtest(tctx, cli1, "IPC$", "A:", NT_STATUS_BAD_DEVICE_TYPE))
522 return false;
524 if (!tcon_devtest(tctx, cli1, "IPC$", "?????", NT_STATUS_OK))
525 return false;
527 if (!tcon_devtest(tctx, cli1, "IPC$", "LPT:", NT_STATUS_BAD_DEVICE_TYPE))
528 return false;
530 if (!tcon_devtest(tctx, cli1, "IPC$", "IPC", NT_STATUS_OK))
531 return false;
533 if (!tcon_devtest(tctx, cli1, "IPC$", "FOOBA", NT_STATUS_BAD_DEVICE_TYPE))
534 return false;
536 if (!tcon_devtest(tctx, cli1, share, "A:", NT_STATUS_OK))
537 return false;
539 if (!tcon_devtest(tctx, cli1, share, "?????", NT_STATUS_OK))
540 return false;
542 if (!tcon_devtest(tctx, cli1, share, "LPT:", NT_STATUS_BAD_DEVICE_TYPE))
543 return false;
545 if (!tcon_devtest(tctx, cli1, share, "IPC", NT_STATUS_BAD_DEVICE_TYPE))
546 return false;
548 if (!tcon_devtest(tctx, cli1, share, "FOOBA", NT_STATUS_BAD_DEVICE_TYPE))
549 return false;
551 return true;
554 static bool rw_torture2(struct torture_context *tctx,
555 struct smbcli_state *c1, struct smbcli_state *c2)
557 const char *lockfname = "\\torture2.lck";
558 int fnum1;
559 int fnum2;
560 int i;
561 uint8_t buf[131072];
562 uint8_t buf_rd[131072];
563 bool correct = true;
564 ssize_t bytes_read, bytes_written;
566 torture_assert(tctx, smbcli_deltree(c1->tree, lockfname) != -1,
567 talloc_asprintf(tctx,
568 "unlink failed (%s)", smbcli_errstr(c1->tree)));
570 fnum1 = smbcli_open(c1->tree, lockfname, O_RDWR | O_CREAT | O_EXCL,
571 DENY_NONE);
572 torture_assert(tctx, fnum1 != -1,
573 talloc_asprintf(tctx,
574 "first open read/write of %s failed (%s)",
575 lockfname, smbcli_errstr(c1->tree)));
576 fnum2 = smbcli_open(c2->tree, lockfname, O_RDONLY,
577 DENY_NONE);
578 torture_assert(tctx, fnum2 != -1,
579 talloc_asprintf(tctx,
580 "second open read-only of %s failed (%s)",
581 lockfname, smbcli_errstr(c2->tree)));
583 torture_comment(tctx, "Checking data integrity over %d ops\n",
584 torture_numops);
586 for (i=0;i<torture_numops;i++)
588 size_t buf_size = ((unsigned int)random()%(sizeof(buf)-1))+ 1;
589 if (i % 10 == 0) {
590 if (torture_setting_bool(tctx, "progress", true)) {
591 torture_comment(tctx, "%d\r", i); fflush(stdout);
595 generate_random_buffer(buf, buf_size);
597 if ((bytes_written = smbcli_write(c1->tree, fnum1, 0, buf, 0, buf_size)) != buf_size) {
598 torture_comment(tctx, "write failed (%s)\n", smbcli_errstr(c1->tree));
599 torture_result(tctx, TORTURE_FAIL, "wrote %d, expected %d\n", (int)bytes_written, (int)buf_size);
600 correct = false;
601 break;
604 if ((bytes_read = smbcli_read(c2->tree, fnum2, buf_rd, 0, buf_size)) != buf_size) {
605 torture_comment(tctx, "read failed (%s)\n", smbcli_errstr(c2->tree));
606 torture_result(tctx, TORTURE_FAIL, "read %d, expected %d\n", (int)bytes_read, (int)buf_size);
607 correct = false;
608 break;
611 torture_assert_mem_equal(tctx, buf_rd, buf, buf_size,
612 "read/write compare failed\n");
615 torture_assert_ntstatus_ok(tctx, smbcli_close(c2->tree, fnum2),
616 talloc_asprintf(tctx, "close failed (%s)", smbcli_errstr(c2->tree)));
617 torture_assert_ntstatus_ok(tctx, smbcli_close(c1->tree, fnum1),
618 talloc_asprintf(tctx, "close failed (%s)", smbcli_errstr(c1->tree)));
620 torture_assert_ntstatus_ok(tctx, smbcli_unlink(c1->tree, lockfname),
621 talloc_asprintf(tctx, "unlink failed (%s)", smbcli_errstr(c1->tree)));
623 torture_comment(tctx, "\n");
625 return correct;
630 static bool run_readwritetest(struct torture_context *tctx,
631 struct smbcli_state *cli1,
632 struct smbcli_state *cli2)
634 torture_comment(tctx, "Running readwritetest v1\n");
635 if (!rw_torture2(tctx, cli1, cli2))
636 return false;
638 torture_comment(tctx, "Running readwritetest v2\n");
640 if (!rw_torture2(tctx, cli1, cli1))
641 return false;
643 return true;
647 test the timing of deferred open requests
649 static bool run_deferopen(struct torture_context *tctx, struct smbcli_state *cli, int dummy)
651 const char *fname = "\\defer_open_test.dat";
652 int i = 0;
653 bool correct = true;
654 int nsec;
655 int msec;
656 double sec;
658 nsec = torture_setting_int(tctx, "sharedelay", 1000000);
659 msec = nsec / 1000;
660 sec = ((double)nsec) / ((double) 1000000);
662 torture_comment(tctx, "Testing deferred open requests.\n");
664 while (i < 4) {
665 int fnum = -1;
667 do {
668 struct timeval tv;
669 tv = timeval_current();
670 fnum = smbcli_nt_create_full(cli->tree, fname, 0,
671 SEC_RIGHTS_FILE_ALL,
672 FILE_ATTRIBUTE_NORMAL,
673 NTCREATEX_SHARE_ACCESS_NONE,
674 NTCREATEX_DISP_OPEN_IF, 0, 0);
675 if (fnum != -1) {
676 break;
678 if (NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),NT_STATUS_SHARING_VIOLATION)) {
679 double e = timeval_elapsed(&tv);
680 if (e < (0.5 * sec) || e > ((1.5 * sec) + 1)) {
681 torture_result(tctx, TORTURE_FAIL, "Timing incorrect %.2f violation 1 sec == %.2f\n",
682 e, sec);
683 return false;
686 } while (NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),NT_STATUS_SHARING_VIOLATION));
688 if (fnum == -1) {
689 torture_comment(tctx,"Failed to open %s, error=%s\n", fname, smbcli_errstr(cli->tree));
690 return false;
693 torture_comment(tctx, "pid %u open %d\n", (unsigned)getpid(), i);
695 smb_msleep(10 * msec);
696 i++;
697 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum))) {
698 torture_comment(tctx,"Failed to close %s, error=%s\n", fname, smbcli_errstr(cli->tree));
699 return false;
701 smb_msleep(2 * msec);
704 if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) {
705 /* All until the last unlink will fail with sharing violation
706 but also the last request can fail since the file could have
707 been successfully deleted by another (test) process */
708 NTSTATUS status = smbcli_nt_error(cli->tree);
709 if ((!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION))
710 && (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND))) {
711 torture_result(tctx, TORTURE_FAIL, "unlink of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
712 correct = false;
716 torture_comment(tctx, "deferred test finished\n");
717 return correct;
721 Try with a wrong vuid and check error message.
724 static bool run_vuidtest(struct torture_context *tctx,
725 struct smbcli_state *cli)
727 const char *fname = "\\vuid.tst";
728 int fnum;
729 size_t size;
730 time_t c_time, a_time, m_time;
732 NTSTATUS result;
734 smbcli_unlink(cli->tree, fname);
736 fnum = smbcli_open(cli->tree, fname,
737 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
739 cli->session->vuid += 1234;
741 torture_comment(tctx, "Testing qfileinfo with wrong vuid\n");
743 if (NT_STATUS_IS_OK(result = smbcli_qfileinfo(cli->tree, fnum, NULL,
744 &size, &c_time, &a_time,
745 &m_time, NULL, NULL))) {
746 torture_fail(tctx, "qfileinfo passed with wrong vuid");
749 if (!NT_STATUS_EQUAL(cli->transport->error.e.nt_status,
750 NT_STATUS_DOS(ERRSRV, ERRbaduid)) &&
751 !NT_STATUS_EQUAL(cli->transport->error.e.nt_status,
752 NT_STATUS_INVALID_HANDLE)) {
753 torture_fail(tctx, talloc_asprintf(tctx,
754 "qfileinfo should have returned DOS error "
755 "ERRSRV:ERRbaduid\n but returned %s",
756 smbcli_errstr(cli->tree)));
759 cli->session->vuid -= 1234;
761 torture_assert_ntstatus_ok(tctx, smbcli_close(cli->tree, fnum),
762 talloc_asprintf(tctx, "close failed (%s)", smbcli_errstr(cli->tree)));
764 smbcli_unlink(cli->tree, fname);
766 return true;
770 Test open mode returns on read-only files.
772 static bool run_opentest(struct torture_context *tctx, struct smbcli_state *cli1,
773 struct smbcli_state *cli2)
775 const char *fname = "\\readonly.file";
776 char *control_char_fname;
777 int fnum1, fnum2;
778 uint8_t buf[20];
779 size_t fsize;
780 bool correct = true;
781 char *tmp_path;
782 int failures = 0;
783 int i;
785 asprintf(&control_char_fname, "\\readonly.afile");
786 for (i = 1; i <= 0x1f; i++) {
787 control_char_fname[10] = i;
788 fnum1 = smbcli_nt_create_full(cli1->tree, control_char_fname, 0, SEC_FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
789 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
791 if (!check_error(__location__, cli1, ERRDOS, ERRinvalidname,
792 NT_STATUS_OBJECT_NAME_INVALID)) {
793 torture_result(tctx, TORTURE_FAIL, "Error code should be NT_STATUS_OBJECT_NAME_INVALID, was %s for file with %d char\n",
794 smbcli_errstr(cli1->tree), i);
795 failures++;
798 if (fnum1 != -1) {
799 smbcli_close(cli1->tree, fnum1);
801 smbcli_setatr(cli1->tree, control_char_fname, 0, 0);
802 smbcli_unlink(cli1->tree, control_char_fname);
804 free(control_char_fname);
806 if (!failures)
807 torture_comment(tctx, "Create file with control char names passed.\n");
809 smbcli_setatr(cli1->tree, fname, 0, 0);
810 smbcli_unlink(cli1->tree, fname);
812 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
813 if (fnum1 == -1) {
814 torture_result(tctx, TORTURE_FAIL, "open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
815 return false;
818 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
819 torture_result(tctx, TORTURE_FAIL, "close2 failed (%s)\n", smbcli_errstr(cli1->tree));
820 return false;
823 if (NT_STATUS_IS_ERR(smbcli_setatr(cli1->tree, fname, FILE_ATTRIBUTE_READONLY, 0))) {
824 torture_result(tctx, TORTURE_FAIL,
825 __location__ ": smbcli_setatr failed (%s)\n", smbcli_errstr(cli1->tree));
826 CHECK_MAX_FAILURES(error_test1);
827 return false;
830 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_WRITE);
831 if (fnum1 == -1) {
832 torture_result(tctx, TORTURE_FAIL,
833 __location__ ": open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
834 CHECK_MAX_FAILURES(error_test1);
835 return false;
838 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
839 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_ALL);
841 if (check_error(__location__, cli1, ERRDOS, ERRnoaccess,
842 NT_STATUS_ACCESS_DENIED)) {
843 torture_comment(tctx, "correct error code ERRDOS/ERRnoaccess returned\n");
846 torture_comment(tctx, "finished open test 1\n");
848 error_test1:
849 smbcli_close(cli1->tree, fnum1);
851 /* Now try not readonly and ensure ERRbadshare is returned. */
853 smbcli_setatr(cli1->tree, fname, 0, 0);
855 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_WRITE);
856 if (fnum1 == -1) {
857 torture_result(tctx, TORTURE_FAIL, "open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
858 return false;
861 /* This will fail - but the error should be ERRshare. */
862 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_ALL);
864 if (check_error(__location__, cli1, ERRDOS, ERRbadshare,
865 NT_STATUS_SHARING_VIOLATION)) {
866 torture_comment(tctx, "correct error code ERRDOS/ERRbadshare returned\n");
869 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
870 torture_result(tctx, TORTURE_FAIL, "close2 failed (%s)\n", smbcli_errstr(cli1->tree));
871 return false;
874 smbcli_unlink(cli1->tree, fname);
876 torture_comment(tctx, "finished open test 2\n");
878 /* Test truncate open disposition on file opened for read. */
880 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
881 if (fnum1 == -1) {
882 torture_result(tctx, TORTURE_FAIL, "(3) open (1) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
883 return false;
886 /* write 20 bytes. */
888 memset(buf, '\0', 20);
890 if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, 20) != 20) {
891 torture_result(tctx, TORTURE_FAIL, "write failed (%s)\n", smbcli_errstr(cli1->tree));
892 correct = false;
895 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
896 torture_result(tctx, TORTURE_FAIL, "(3) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
897 return false;
900 /* Ensure size == 20. */
901 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
902 torture_result(tctx, TORTURE_FAIL,
903 __location__ ": (3) getatr failed (%s)\n", smbcli_errstr(cli1->tree));
904 CHECK_MAX_FAILURES(error_test3);
905 return false;
908 if (fsize != 20) {
909 torture_result(tctx, TORTURE_FAIL,
910 __location__ ": (3) file size != 20\n");
911 CHECK_MAX_FAILURES(error_test3);
912 return false;
915 /* Now test if we can truncate a file opened for readonly. */
917 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY|O_TRUNC, DENY_NONE);
918 if (fnum1 == -1) {
919 torture_result(tctx, TORTURE_FAIL,
920 __location__ ": (3) open (2) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
921 CHECK_MAX_FAILURES(error_test3);
922 return false;
925 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
926 torture_result(tctx, TORTURE_FAIL,
927 __location__ ": close2 failed (%s)\n", smbcli_errstr(cli1->tree));
928 return false;
931 /* Ensure size == 0. */
932 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
933 torture_result(tctx, TORTURE_FAIL,
934 __location__ ": (3) getatr failed (%s)\n", smbcli_errstr(cli1->tree));
935 CHECK_MAX_FAILURES(error_test3);
936 return false;
939 if (fsize != 0) {
940 torture_result(tctx, TORTURE_FAIL,
941 __location__ ": (3) file size != 0\n");
942 CHECK_MAX_FAILURES(error_test3);
943 return false;
945 torture_comment(tctx, "finished open test 3\n");
946 error_test3:
948 fnum1 = fnum2 = -1;
949 smbcli_unlink(cli1->tree, fname);
952 torture_comment(tctx, "Testing ctemp\n");
953 fnum1 = smbcli_ctemp(cli1->tree, "\\", &tmp_path);
954 if (fnum1 == -1) {
955 torture_result(tctx, TORTURE_FAIL,
956 __location__ ": ctemp failed (%s)\n", smbcli_errstr(cli1->tree));
957 CHECK_MAX_FAILURES(error_test4);
958 return false;
960 torture_comment(tctx, "ctemp gave path %s\n", tmp_path);
962 error_test4:
963 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
964 torture_comment(tctx, "close of temp failed (%s)\n", smbcli_errstr(cli1->tree));
966 if (NT_STATUS_IS_ERR(smbcli_unlink(cli1->tree, tmp_path))) {
967 torture_comment(tctx, "unlink of temp failed (%s)\n", smbcli_errstr(cli1->tree));
970 /* Test the non-io opens... */
972 torture_comment(tctx, "Test #1 testing 2 non-io opens (no delete)\n");
973 fnum1 = fnum2 = -1;
974 smbcli_setatr(cli2->tree, fname, 0, 0);
975 smbcli_unlink(cli2->tree, fname);
977 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
978 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
980 if (fnum1 == -1) {
981 torture_result(tctx, TORTURE_FAIL,
982 __location__ ": Test 1 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
983 CHECK_MAX_FAILURES(error_test10);
984 return false;
987 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
988 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
989 if (fnum2 == -1) {
990 torture_result(tctx, TORTURE_FAIL,
991 __location__ ": Test 1 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
992 CHECK_MAX_FAILURES(error_test10);
993 return false;
996 torture_comment(tctx, "non-io open test #1 passed.\n");
997 error_test10:
999 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1000 torture_comment(tctx, "Test 1 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1002 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1003 torture_comment(tctx, "Test 1 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1006 torture_comment(tctx, "Test #2 testing 2 non-io opens (first with delete)\n");
1007 fnum1 = fnum2 = -1;
1008 smbcli_unlink(cli1->tree, fname);
1010 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1011 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1013 if (fnum1 == -1) {
1014 torture_result(tctx, TORTURE_FAIL,
1015 __location__ ": Test 2 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1016 CHECK_MAX_FAILURES(error_test20);
1017 return false;
1020 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1021 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1023 if (fnum2 == -1) {
1024 torture_result(tctx, TORTURE_FAIL,
1025 __location__ ": Test 2 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1026 CHECK_MAX_FAILURES(error_test20);
1027 return false;
1030 torture_comment(tctx, "non-io open test #2 passed.\n");
1031 error_test20:
1033 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1034 torture_comment(tctx, "Test 1 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1036 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1037 torture_comment(tctx, "Test 1 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1040 fnum1 = fnum2 = -1;
1041 smbcli_unlink(cli1->tree, fname);
1043 torture_comment(tctx, "Test #3 testing 2 non-io opens (second with delete)\n");
1045 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1046 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1048 if (fnum1 == -1) {
1049 torture_result(tctx, TORTURE_FAIL,
1050 __location__ ": Test 3 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1051 CHECK_MAX_FAILURES(error_test30);
1052 return false;
1055 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1056 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1058 if (fnum2 == -1) {
1059 torture_result(tctx, TORTURE_FAIL,
1060 __location__ ": Test 3 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1061 CHECK_MAX_FAILURES(error_test30);
1062 return false;
1065 torture_comment(tctx, "non-io open test #3 passed.\n");
1066 error_test30:
1068 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1069 torture_comment(tctx, "Test 3 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1071 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1072 torture_comment(tctx, "Test 3 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1075 torture_comment(tctx, "Test #4 testing 2 non-io opens (both with delete)\n");
1076 fnum1 = fnum2 = -1;
1077 smbcli_unlink(cli1->tree, fname);
1079 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1080 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1082 if (fnum1 == -1) {
1083 torture_result(tctx, TORTURE_FAIL,
1084 __location__ ": Test 4 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1085 CHECK_MAX_FAILURES(error_test40);
1086 return false;
1089 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1090 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1092 if (fnum2 != -1) {
1093 torture_result(tctx, TORTURE_FAIL,
1094 __location__ ": Test 4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1095 CHECK_MAX_FAILURES(error_test40);
1096 return false;
1099 torture_comment(tctx, "Test 4 open 2 of %s gave %s (correct error should be %s)\n", fname, smbcli_errstr(cli2->tree), "sharing violation");
1101 torture_comment(tctx, "non-io open test #4 passed.\n");
1102 error_test40:
1104 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1105 torture_comment(tctx, "Test 4 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1107 if (fnum2 != -1 && NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1108 torture_comment(tctx, "Test 4 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1111 torture_comment(tctx, "Test #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
1112 fnum1 = fnum2 = -1;
1113 smbcli_unlink(cli1->tree, fname);
1115 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1116 NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1118 if (fnum1 == -1) {
1119 torture_result(tctx, TORTURE_FAIL,
1120 __location__ ": Test 5 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1121 CHECK_MAX_FAILURES(error_test50);
1122 return false;
1125 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1126 NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1128 if (fnum2 == -1) {
1129 torture_result(tctx, TORTURE_FAIL,
1130 __location__ ": Test 5 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1131 CHECK_MAX_FAILURES(error_test50);
1132 return false;
1135 torture_comment(tctx, "non-io open test #5 passed.\n");
1136 error_test50:
1138 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1139 torture_comment(tctx, "Test 5 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1142 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1143 torture_comment(tctx, "Test 5 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1146 torture_comment(tctx, "Test #6 testing 1 non-io open, one io open\n");
1147 fnum1 = fnum2 = -1;
1148 smbcli_unlink(cli1->tree, fname);
1150 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
1151 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1153 if (fnum1 == -1) {
1154 torture_result(tctx, TORTURE_FAIL,
1155 __location__ ": Test 6 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1156 CHECK_MAX_FAILURES(error_test60);
1157 return false;
1160 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1161 NTCREATEX_SHARE_ACCESS_READ, NTCREATEX_DISP_OPEN_IF, 0, 0);
1163 if (fnum2 == -1) {
1164 torture_result(tctx, TORTURE_FAIL,
1165 __location__ ": Test 6 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1166 CHECK_MAX_FAILURES(error_test60);
1167 return false;
1170 torture_comment(tctx, "non-io open test #6 passed.\n");
1171 error_test60:
1173 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1174 torture_comment(tctx, "Test 6 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1177 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1178 torture_comment(tctx, "Test 6 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1181 torture_comment(tctx, "Test #7 testing 1 non-io open, one io open with delete\n");
1182 fnum1 = fnum2 = -1;
1183 smbcli_unlink(cli1->tree, fname);
1185 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
1186 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1188 if (fnum1 == -1) {
1189 torture_result(tctx, TORTURE_FAIL,
1190 __location__ ": Test 7 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1191 CHECK_MAX_FAILURES(error_test70);
1192 return false;
1195 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1196 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1198 if (fnum2 != -1) {
1199 torture_result(tctx, TORTURE_FAIL,
1200 __location__ ": Test 7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1201 CHECK_MAX_FAILURES(error_test70);
1202 return false;
1205 torture_comment(tctx, "Test 7 open 2 of %s gave %s (correct error should be %s)\n", fname, smbcli_errstr(cli2->tree), "sharing violation");
1207 torture_comment(tctx, "non-io open test #7 passed.\n");
1208 error_test70:
1210 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1211 torture_comment(tctx, "Test 7 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1213 if (fnum2 != -1 && NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1214 torture_comment(tctx, "Test 7 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1217 torture_comment(tctx, "Test #8 testing one normal open, followed by lock, followed by open with truncate\n");
1218 fnum1 = fnum2 = -1;
1219 smbcli_unlink(cli1->tree, fname);
1221 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1222 if (fnum1 == -1) {
1223 torture_result(tctx, TORTURE_FAIL, "(8) open (1) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1224 return false;
1227 /* write 20 bytes. */
1229 memset(buf, '\0', 20);
1231 if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, 20) != 20) {
1232 torture_result(tctx, TORTURE_FAIL, "(8) write failed (%s)\n", smbcli_errstr(cli1->tree));
1233 correct = false;
1236 /* Ensure size == 20. */
1237 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
1238 torture_result(tctx, TORTURE_FAIL,
1239 __location__ ": (8) getatr (1) failed (%s)\n", smbcli_errstr(cli1->tree));
1240 CHECK_MAX_FAILURES(error_test80);
1241 return false;
1244 if (fsize != 20) {
1245 torture_result(tctx, TORTURE_FAIL,
1246 __location__ ": (8) file size %lu != 20\n", (unsigned long)fsize);
1247 CHECK_MAX_FAILURES(error_test80);
1248 return false;
1251 /* Get an exclusive lock on the open file. */
1252 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
1253 torture_result(tctx, TORTURE_FAIL,
1254 __location__ ": (8) lock1 failed (%s)\n", smbcli_errstr(cli1->tree));
1255 CHECK_MAX_FAILURES(error_test80);
1256 return false;
1259 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR|O_TRUNC, DENY_NONE);
1260 if (fnum1 == -1) {
1261 torture_result(tctx, TORTURE_FAIL, "(8) open (2) of %s with truncate failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1262 return false;
1265 /* Ensure size == 0. */
1266 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
1267 torture_result(tctx, TORTURE_FAIL,
1268 __location__ ": (8) getatr (2) failed (%s)\n", smbcli_errstr(cli1->tree));
1269 CHECK_MAX_FAILURES(error_test80);
1270 return false;
1273 if (fsize != 0) {
1274 torture_result(tctx, TORTURE_FAIL,
1275 __location__ ": (8) file size %lu != 0\n", (unsigned long)fsize);
1276 CHECK_MAX_FAILURES(error_test80);
1277 return false;
1280 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1281 torture_result(tctx, TORTURE_FAIL, "(8) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
1282 return false;
1285 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum2))) {
1286 torture_result(tctx, TORTURE_FAIL, "(8) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
1287 return false;
1290 error_test80:
1292 torture_comment(tctx, "open test #8 passed.\n");
1294 smbcli_unlink(cli1->tree, fname);
1296 return failures > 0 ? false : correct;
1299 /* FIRST_DESIRED_ACCESS 0xf019f */
1300 #define FIRST_DESIRED_ACCESS SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA|SEC_FILE_APPEND_DATA|\
1301 SEC_FILE_READ_EA| /* 0xf */ \
1302 SEC_FILE_WRITE_EA|SEC_FILE_READ_ATTRIBUTE| /* 0x90 */ \
1303 SEC_FILE_WRITE_ATTRIBUTE| /* 0x100 */ \
1304 SEC_STD_DELETE|SEC_STD_READ_CONTROL|\
1305 SEC_STD_WRITE_DAC|SEC_STD_WRITE_OWNER /* 0xf0000 */
1306 /* SECOND_DESIRED_ACCESS 0xe0080 */
1307 #define SECOND_DESIRED_ACCESS SEC_FILE_READ_ATTRIBUTE| /* 0x80 */ \
1308 SEC_STD_READ_CONTROL|SEC_STD_WRITE_DAC|\
1309 SEC_STD_WRITE_OWNER /* 0xe0000 */
1311 #if 0
1312 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTE| /* 0x80 */ \
1313 READ_CONTROL|WRITE_DAC|\
1314 SEC_FILE_READ_DATA|\
1315 WRITE_OWNER /* */
1316 #endif
1321 Test ntcreate calls made by xcopy
1323 static bool run_xcopy(struct torture_context *tctx,
1324 struct smbcli_state *cli1)
1326 const char *fname = "\\test.txt";
1327 int fnum1, fnum2;
1329 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1330 FIRST_DESIRED_ACCESS,
1331 FILE_ATTRIBUTE_ARCHIVE,
1332 NTCREATEX_SHARE_ACCESS_NONE,
1333 NTCREATEX_DISP_OVERWRITE_IF,
1334 0x4044, 0);
1336 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx,
1337 "First open failed - %s", smbcli_errstr(cli1->tree)));
1339 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1340 SECOND_DESIRED_ACCESS, 0,
1341 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN,
1342 0x200000, 0);
1343 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx,
1344 "second open failed - %s", smbcli_errstr(cli1->tree)));
1346 return true;
1349 static bool run_iometer(struct torture_context *tctx,
1350 struct smbcli_state *cli)
1352 const char *fname = "\\iobw.tst";
1353 int fnum;
1354 size_t filesize;
1355 NTSTATUS status;
1356 char buf[2048];
1357 int ops;
1359 memset(buf, 0, sizeof(buf));
1361 status = smbcli_getatr(cli->tree, fname, NULL, &filesize, NULL);
1362 torture_assert_ntstatus_ok(tctx, status,
1363 talloc_asprintf(tctx, "smbcli_getatr failed: %s", nt_errstr(status)));
1365 torture_comment(tctx, "size: %d\n", (int)filesize);
1367 filesize -= (sizeof(buf) - 1);
1369 fnum = smbcli_nt_create_full(cli->tree, fname, 0x16,
1370 0x2019f, 0, 0x3, 3, 0x42, 0x3);
1371 torture_assert(tctx, fnum != -1, talloc_asprintf(tctx, "open failed: %s",
1372 smbcli_errstr(cli->tree)));
1374 ops = 0;
1376 while (true) {
1377 int i, num_reads, num_writes;
1379 num_reads = random() % 10;
1380 num_writes = random() % 3;
1382 for (i=0; i<num_reads; i++) {
1383 ssize_t res;
1384 if (ops++ > torture_numops) {
1385 return true;
1387 res = smbcli_read(cli->tree, fnum, buf,
1388 random() % filesize, sizeof(buf));
1389 torture_assert(tctx, res == sizeof(buf),
1390 talloc_asprintf(tctx, "read failed: %s",
1391 smbcli_errstr(cli->tree)));
1393 for (i=0; i<num_writes; i++) {
1394 ssize_t res;
1395 if (ops++ > torture_numops) {
1396 return true;
1398 res = smbcli_write(cli->tree, fnum, 0, buf,
1399 random() % filesize, sizeof(buf));
1400 torture_assert(tctx, res == sizeof(buf),
1401 talloc_asprintf(tctx, "read failed: %s",
1402 smbcli_errstr(cli->tree)));
1408 tries variants of chkpath
1410 static bool torture_chkpath_test(struct torture_context *tctx,
1411 struct smbcli_state *cli)
1413 int fnum;
1414 bool ret;
1416 torture_comment(tctx, "Testing valid and invalid paths\n");
1418 /* cleanup from an old run */
1419 smbcli_rmdir(cli->tree, "\\chkpath.dir\\dir2");
1420 smbcli_unlink(cli->tree, "\\chkpath.dir\\*");
1421 smbcli_rmdir(cli->tree, "\\chkpath.dir");
1423 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\chkpath.dir"))) {
1424 torture_result(tctx, TORTURE_FAIL, "mkdir1 failed : %s\n", smbcli_errstr(cli->tree));
1425 return false;
1428 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\chkpath.dir\\dir2"))) {
1429 torture_result(tctx, TORTURE_FAIL, "mkdir2 failed : %s\n", smbcli_errstr(cli->tree));
1430 return false;
1433 fnum = smbcli_open(cli->tree, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1434 if (fnum == -1) {
1435 torture_result(tctx, TORTURE_FAIL, "open1 failed (%s)\n", smbcli_errstr(cli->tree));
1436 return false;
1438 smbcli_close(cli->tree, fnum);
1440 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir"))) {
1441 torture_result(tctx, TORTURE_FAIL, "chkpath1 failed: %s\n", smbcli_errstr(cli->tree));
1442 ret = false;
1445 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\dir2"))) {
1446 torture_result(tctx, TORTURE_FAIL, "chkpath2 failed: %s\n", smbcli_errstr(cli->tree));
1447 ret = false;
1450 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\foo.txt"))) {
1451 ret = check_error(__location__, cli, ERRDOS, ERRbadpath,
1452 NT_STATUS_NOT_A_DIRECTORY);
1453 } else {
1454 torture_result(tctx, TORTURE_FAIL, "* chkpath on a file should fail\n");
1455 ret = false;
1458 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\bar.txt"))) {
1459 ret = check_error(__location__, cli, ERRDOS, ERRbadpath,
1460 NT_STATUS_OBJECT_NAME_NOT_FOUND);
1461 } else {
1462 torture_result(tctx, TORTURE_FAIL, "* chkpath on a non existent file should fail\n");
1463 ret = false;
1466 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\dirxx\\bar.txt"))) {
1467 ret = check_error(__location__, cli, ERRDOS, ERRbadpath,
1468 NT_STATUS_OBJECT_PATH_NOT_FOUND);
1469 } else {
1470 torture_result(tctx, TORTURE_FAIL, "* chkpath on a non existent component should fail\n");
1471 ret = false;
1474 smbcli_rmdir(cli->tree, "\\chkpath.dir\\dir2");
1475 smbcli_unlink(cli->tree, "\\chkpath.dir\\*");
1476 smbcli_rmdir(cli->tree, "\\chkpath.dir");
1478 return ret;
1482 * This is a test to excercise some weird Samba3 error paths.
1485 static bool torture_samba3_errorpaths(struct torture_context *tctx)
1487 bool nt_status_support;
1488 struct smbcli_state *cli_nt = NULL, *cli_dos = NULL;
1489 bool result = false;
1490 int fnum;
1491 const char *os2_fname = ".+,;=[].";
1492 const char *dname = "samba3_errordir";
1493 union smb_open io;
1494 NTSTATUS status;
1496 nt_status_support = lpcfg_nt_status_support(tctx->lp_ctx);
1498 if (!lpcfg_set_cmdline(tctx->lp_ctx, "nt status support", "yes")) {
1499 torture_result(tctx, TORTURE_FAIL, "Could not set 'nt status support = yes'\n");
1500 goto fail;
1503 if (!torture_open_connection(&cli_nt, tctx, 0)) {
1504 goto fail;
1507 if (!lpcfg_set_cmdline(tctx->lp_ctx, "nt status support", "no")) {
1508 torture_result(tctx, TORTURE_FAIL, "Could not set 'nt status support = yes'\n");
1509 goto fail;
1512 if (!torture_open_connection(&cli_dos, tctx, 1)) {
1513 goto fail;
1516 if (!lpcfg_set_cmdline(tctx->lp_ctx, "nt status support",
1517 nt_status_support ? "yes":"no")) {
1518 torture_result(tctx, TORTURE_FAIL, "Could not reset 'nt status support = yes'");
1519 goto fail;
1522 smbcli_unlink(cli_nt->tree, os2_fname);
1523 smbcli_rmdir(cli_nt->tree, dname);
1525 if (!NT_STATUS_IS_OK(smbcli_mkdir(cli_nt->tree, dname))) {
1526 torture_result(tctx, TORTURE_FAIL, "smbcli_mkdir(%s) failed: %s\n", dname,
1527 smbcli_errstr(cli_nt->tree));
1528 goto fail;
1531 io.generic.level = RAW_OPEN_NTCREATEX;
1532 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1533 io.ntcreatex.in.root_fid.fnum = 0;
1534 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1535 io.ntcreatex.in.alloc_size = 1024*1024;
1536 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
1537 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1538 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1539 io.ntcreatex.in.create_options = 0;
1540 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1541 io.ntcreatex.in.security_flags = 0;
1542 io.ntcreatex.in.fname = dname;
1544 status = smb_raw_open(cli_nt->tree, tctx, &io);
1545 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1546 torture_result(tctx, TORTURE_FAIL, "(%s) incorrect status %s should be %s\n",
1547 __location__, nt_errstr(status),
1548 nt_errstr(NT_STATUS_OBJECT_NAME_COLLISION));
1549 goto fail;
1551 status = smb_raw_open(cli_dos->tree, tctx, &io);
1552 if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS, ERRfilexists))) {
1553 torture_result(tctx, TORTURE_FAIL, "(%s) incorrect status %s should be %s\n",
1554 __location__, nt_errstr(status),
1555 nt_errstr(NT_STATUS_DOS(ERRDOS, ERRfilexists)));
1556 goto fail;
1559 status = smbcli_mkdir(cli_nt->tree, dname);
1560 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1561 torture_result(tctx, TORTURE_FAIL, "(%s) incorrect status %s should be %s\n",
1562 __location__, nt_errstr(status),
1563 nt_errstr(NT_STATUS_OBJECT_NAME_COLLISION));
1564 goto fail;
1566 status = smbcli_mkdir(cli_dos->tree, dname);
1567 if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS, ERRnoaccess))) {
1568 torture_result(tctx, TORTURE_FAIL, "(%s) incorrect status %s should be %s\n",
1569 __location__, nt_errstr(status),
1570 nt_errstr(NT_STATUS_DOS(ERRDOS, ERRnoaccess)));
1571 goto fail;
1575 union smb_mkdir md;
1576 md.t2mkdir.level = RAW_MKDIR_T2MKDIR;
1577 md.t2mkdir.in.path = dname;
1578 md.t2mkdir.in.num_eas = 0;
1579 md.t2mkdir.in.eas = NULL;
1581 status = smb_raw_mkdir(cli_nt->tree, &md);
1582 if (!NT_STATUS_EQUAL(status,
1583 NT_STATUS_OBJECT_NAME_COLLISION)) {
1584 torture_comment(
1585 tctx, "(%s) incorrect status %s should be "
1586 "NT_STATUS_OBJECT_NAME_COLLISION\n",
1587 __location__, nt_errstr(status));
1588 goto fail;
1590 status = smb_raw_mkdir(cli_dos->tree, &md);
1591 if (!NT_STATUS_EQUAL(status,
1592 NT_STATUS_DOS(ERRDOS, ERRrename))) {
1593 torture_result(tctx, TORTURE_FAIL, "(%s) incorrect status %s "
1594 "should be ERRDOS:ERRrename\n",
1595 __location__, nt_errstr(status));
1596 goto fail;
1600 io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1601 status = smb_raw_open(cli_nt->tree, tctx, &io);
1602 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1603 torture_result(tctx, TORTURE_FAIL, "(%s) incorrect status %s should be %s\n",
1604 __location__, nt_errstr(status),
1605 nt_errstr(NT_STATUS_OBJECT_NAME_COLLISION));
1606 goto fail;
1609 status = smb_raw_open(cli_dos->tree, tctx, &io);
1610 if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS, ERRfilexists))) {
1611 torture_result(tctx, TORTURE_FAIL, "(%s) incorrect status %s should be %s\n",
1612 __location__, nt_errstr(status),
1613 nt_errstr(NT_STATUS_DOS(ERRDOS, ERRfilexists)));
1614 goto fail;
1618 /* Test an invalid DOS deny mode */
1619 const char *fname = "test.txt";
1621 fnum = smbcli_open(cli_nt->tree, fname, O_RDWR | O_CREAT, 5);
1622 if (fnum != -1) {
1623 torture_result(tctx, TORTURE_FAIL, "Open(%s) with invalid deny mode succeeded -- "
1624 "expected failure\n", fname);
1625 smbcli_close(cli_nt->tree, fnum);
1626 goto fail;
1628 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli_nt->tree),
1629 NT_STATUS_DOS(ERRDOS,ERRbadaccess))) {
1630 torture_result(tctx, TORTURE_FAIL, "Expected DOS error ERRDOS/ERRbadaccess, "
1631 "got %s\n", smbcli_errstr(cli_nt->tree));
1632 goto fail;
1635 fnum = smbcli_open(cli_dos->tree, fname, O_RDWR | O_CREAT, 5);
1636 if (fnum != -1) {
1637 torture_result(tctx, TORTURE_FAIL, "Open(%s) with invalid deny mode succeeded -- "
1638 "expected failure\n", fname);
1639 smbcli_close(cli_nt->tree, fnum);
1640 goto fail;
1642 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli_nt->tree),
1643 NT_STATUS_DOS(ERRDOS,ERRbadaccess))) {
1644 torture_result(tctx, TORTURE_FAIL, "Expected DOS error ERRDOS:ERRbadaccess, "
1645 "got %s\n", smbcli_errstr(cli_nt->tree));
1646 goto fail;
1652 * Samba 3.0.23 has a bug that an existing file can be opened
1653 * as a directory using ntcreate&x. Test this.
1656 const char *fname = "\\test_dir.txt";
1658 fnum = smbcli_open(cli_nt->tree, fname, O_RDWR|O_CREAT,
1659 DENY_NONE);
1660 if (fnum == -1) {
1661 d_printf("(%s) smbcli_open failed: %s\n", __location__,
1662 smbcli_errstr(cli_nt->tree));
1664 smbcli_close(cli_nt->tree, fnum);
1666 io.generic.level = RAW_OPEN_NTCREATEX;
1667 io.ntcreatex.in.root_fid.fnum = 0;
1668 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1669 io.ntcreatex.in.alloc_size = 0;
1670 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
1671 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1672 NTCREATEX_SHARE_ACCESS_WRITE|
1673 NTCREATEX_SHARE_ACCESS_DELETE;
1674 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1675 io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1676 io.ntcreatex.in.impersonation =
1677 NTCREATEX_IMPERSONATION_ANONYMOUS;
1678 io.ntcreatex.in.security_flags = 0;
1679 io.ntcreatex.in.fname = fname;
1680 io.ntcreatex.in.flags = 0;
1682 status = smb_raw_open(cli_nt->tree, tctx, &io);
1683 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_A_DIRECTORY)) {
1684 torture_result(tctx, TORTURE_FAIL, "ntcreate as dir gave %s, "
1685 "expected NT_STATUS_NOT_A_DIRECTORY\n",
1686 nt_errstr(status));
1687 result = false;
1690 if (NT_STATUS_IS_OK(status)) {
1691 smbcli_close(cli_nt->tree, io.ntcreatex.out.file.fnum);
1694 status = smb_raw_open(cli_dos->tree, tctx, &io);
1695 if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS,
1696 ERRbaddirectory))) {
1697 torture_result(tctx, TORTURE_FAIL, "ntcreate as dir gave %s, "
1698 "expected NT_STATUS_NOT_A_DIRECTORY\n",
1699 nt_errstr(status));
1700 result = false;
1703 if (NT_STATUS_IS_OK(status)) {
1704 smbcli_close(cli_dos->tree,
1705 io.ntcreatex.out.file.fnum);
1708 smbcli_unlink(cli_nt->tree, fname);
1711 if (!torture_setting_bool(tctx, "samba3", false)) {
1712 goto done;
1715 fnum = smbcli_open(cli_dos->tree, os2_fname,
1716 O_RDWR | O_CREAT | O_TRUNC,
1717 DENY_NONE);
1718 if (fnum != -1) {
1719 torture_result(tctx, TORTURE_FAIL, "Open(%s) succeeded -- expected failure\n",
1720 os2_fname);
1721 smbcli_close(cli_dos->tree, fnum);
1722 goto fail;
1725 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli_dos->tree),
1726 NT_STATUS_DOS(ERRDOS, ERRcannotopen))) {
1727 torture_result(tctx, TORTURE_FAIL, "Expected DOS error ERRDOS/ERRcannotopen, got %s\n",
1728 smbcli_errstr(cli_dos->tree));
1729 goto fail;
1732 fnum = smbcli_open(cli_nt->tree, os2_fname,
1733 O_RDWR | O_CREAT | O_TRUNC,
1734 DENY_NONE);
1735 if (fnum != -1) {
1736 torture_result(tctx, TORTURE_FAIL, "Open(%s) succeeded -- expected failure\n",
1737 os2_fname);
1738 smbcli_close(cli_nt->tree, fnum);
1739 goto fail;
1742 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli_nt->tree),
1743 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1744 torture_result(tctx, TORTURE_FAIL, "Expected error NT_STATUS_OBJECT_NAME_NOT_FOUND, "
1745 "got %s\n", smbcli_errstr(cli_nt->tree));
1746 goto fail;
1749 done:
1750 result = true;
1752 fail:
1753 if (cli_dos != NULL) {
1754 torture_close_connection(cli_dos);
1756 if (cli_nt != NULL) {
1757 torture_close_connection(cli_nt);
1760 return result;
1764 This checks file/dir birthtime
1766 static void list_fn(struct clilist_file_info *finfo, const char *name,
1767 void *state){
1769 /* Just to change dir access time*/
1770 sleep(5);
1774 static bool run_birthtimetest(struct torture_context *tctx,
1775 struct smbcli_state *cli)
1777 int fnum;
1778 size_t size;
1779 time_t c_time, a_time, m_time, w_time, c_time1;
1780 const char *fname = "\\birthtime.tst";
1781 const char *dname = "\\birthtime";
1782 const char *fname2 = "\\birthtime\\birthtime.tst";
1783 bool correct = true;
1784 uint8_t buf[16];
1787 smbcli_unlink(cli->tree, fname);
1789 torture_comment(tctx, "Testing Birthtime for File\n");
1791 /* Save File birthtime/creationtime */
1792 fnum = smbcli_open(cli->tree, fname, O_RDWR | O_CREAT | O_TRUNC,
1793 DENY_NONE);
1794 if (NT_STATUS_IS_ERR(smbcli_qfileinfo(cli->tree, fnum, NULL, &size,
1795 &c_time, &a_time, &m_time, NULL, NULL))) {
1796 torture_result(tctx, TORTURE_FAIL, "ERROR: qfileinfo failed (%s)\n",
1797 smbcli_errstr(cli->tree));
1798 correct = false;
1800 smbcli_close(cli->tree, fnum);
1802 sleep(10);
1804 /* Change in File attribute changes file change time*/
1805 smbcli_setatr(cli->tree, fname, FILE_ATTRIBUTE_SYSTEM, 0);
1807 fnum = smbcli_open(cli->tree, fname, O_RDWR | O_CREAT , DENY_NONE);
1808 /* Writing updates modification time*/
1809 smbcli_smbwrite(cli->tree, fnum, &fname, 0, sizeof(fname));
1810 /*Reading updates access time */
1811 smbcli_read(cli->tree, fnum, buf, 0, 13);
1812 smbcli_close(cli->tree, fnum);
1814 if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, fname, &c_time1,
1815 &a_time, &m_time, &w_time, &size, NULL, NULL))) {
1816 torture_result(tctx, TORTURE_FAIL, "ERROR: qpathinfo2 failed (%s)\n",
1817 smbcli_errstr(cli->tree));
1818 correct = false;
1819 } else {
1820 fprintf(stdout, "c_time = %li, c_time1 = %li\n",
1821 (long) c_time, (long) c_time1);
1822 if (c_time1 != c_time) {
1823 torture_result(tctx, TORTURE_FAIL, "This system updated file \
1824 birth times! Not expected!\n");
1825 correct = false;
1828 smbcli_unlink(cli->tree, fname);
1830 torture_comment(tctx, "Testing Birthtime for Directory\n");
1832 /* check if the server does not update the directory birth time
1833 when creating a new file */
1834 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, dname))) {
1835 torture_result(tctx, TORTURE_FAIL, "ERROR: mkdir failed (%s)\n",
1836 smbcli_errstr(cli->tree));
1837 correct = false;
1839 sleep(3);
1840 if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, "\\birthtime\\",
1841 &c_time,&a_time,&m_time,&w_time, &size, NULL, NULL))){
1842 torture_result(tctx, TORTURE_FAIL, "ERROR: qpathinfo2 failed (%s)\n",
1843 smbcli_errstr(cli->tree));
1844 correct = false;
1847 /* Creating a new file changes dir modification time and change time*/
1848 smbcli_unlink(cli->tree, fname2);
1849 fnum = smbcli_open(cli->tree, fname2, O_RDWR | O_CREAT | O_TRUNC,
1850 DENY_NONE);
1851 smbcli_smbwrite(cli->tree, fnum, &fnum, 0, sizeof(fnum));
1852 smbcli_read(cli->tree, fnum, buf, 0, 13);
1853 smbcli_close(cli->tree, fnum);
1855 /* dir listing changes dir access time*/
1856 smbcli_list(cli->tree, "\\birthtime\\*", 0, list_fn, cli );
1858 if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, "\\birthtime\\",
1859 &c_time1, &a_time, &m_time,&w_time,&size,NULL,NULL))){
1860 torture_result(tctx, TORTURE_FAIL, "ERROR: qpathinfo2 failed (%s)\n",
1861 smbcli_errstr(cli->tree));
1862 correct = false;
1863 } else {
1864 fprintf(stdout, "c_time = %li, c_time1 = %li\n",
1865 (long) c_time, (long) c_time1);
1866 if (c_time1 != c_time) {
1867 torture_result(tctx, TORTURE_FAIL, "This system updated directory \
1868 birth times! Not Expected!\n");
1869 correct = false;
1872 smbcli_unlink(cli->tree, fname2);
1873 smbcli_rmdir(cli->tree, dname);
1875 return correct;
1879 NTSTATUS torture_base_init(void)
1881 struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "base");
1883 torture_suite_add_2smb_test(suite, "fdpass", run_fdpasstest);
1884 torture_suite_add_suite(suite, torture_base_locktest(suite));
1885 torture_suite_add_1smb_test(suite, "unlink", torture_unlinktest);
1886 torture_suite_add_1smb_test(suite, "attr", run_attrtest);
1887 torture_suite_add_1smb_test(suite, "trans2", run_trans2test);
1888 torture_suite_add_1smb_test(suite, "birthtime", run_birthtimetest);
1889 torture_suite_add_simple_test(suite, "negnowait", run_negprot_nowait);
1890 torture_suite_add_1smb_test(suite, "dir1", torture_dirtest1);
1891 torture_suite_add_1smb_test(suite, "dir2", torture_dirtest2);
1892 torture_suite_add_1smb_test(suite, "deny1", torture_denytest1);
1893 torture_suite_add_2smb_test(suite, "deny2", torture_denytest2);
1894 torture_suite_add_2smb_test(suite, "deny3", torture_denytest3);
1895 torture_suite_add_1smb_test(suite, "denydos", torture_denydos_sharing);
1896 torture_suite_add_smb_multi_test(suite, "ntdeny1", torture_ntdenytest1);
1897 torture_suite_add_2smb_test(suite, "ntdeny2", torture_ntdenytest2);
1898 torture_suite_add_1smb_test(suite, "tcon", run_tcon_test);
1899 torture_suite_add_1smb_test(suite, "tcondev", run_tcon_devtype_test);
1900 torture_suite_add_1smb_test(suite, "vuid", run_vuidtest);
1901 torture_suite_add_2smb_test(suite, "rw1", run_readwritetest);
1902 torture_suite_add_2smb_test(suite, "open", run_opentest);
1903 torture_suite_add_smb_multi_test(suite, "defer_open", run_deferopen);
1904 torture_suite_add_1smb_test(suite, "xcopy", run_xcopy);
1905 torture_suite_add_1smb_test(suite, "iometer", run_iometer);
1906 torture_suite_add_1smb_test(suite, "rename", torture_test_rename);
1907 torture_suite_add_suite(suite, torture_test_delete());
1908 torture_suite_add_1smb_test(suite, "properties", torture_test_properties);
1909 torture_suite_add_1smb_test(suite, "mangle", torture_mangle);
1910 torture_suite_add_1smb_test(suite, "openattr", torture_openattrtest);
1911 torture_suite_add_1smb_test(suite, "winattr", torture_winattrtest);
1912 torture_suite_add_suite(suite, torture_charset(suite));
1913 torture_suite_add_1smb_test(suite, "chkpath", torture_chkpath_test);
1914 torture_suite_add_1smb_test(suite, "secleak", torture_sec_leak);
1915 torture_suite_add_simple_test(suite, "disconnect", torture_disconnect);
1916 torture_suite_add_suite(suite, torture_delay_write());
1917 torture_suite_add_simple_test(suite, "samba3error", torture_samba3_errorpaths);
1918 torture_suite_add_1smb_test(suite, "casetable", torture_casetable);
1919 torture_suite_add_1smb_test(suite, "utable", torture_utable);
1920 torture_suite_add_simple_test(suite, "smb", torture_smb_scan);
1921 torture_suite_add_suite(suite, torture_trans2_aliases(suite));
1922 torture_suite_add_1smb_test(suite, "trans2-scan", torture_trans2_scan);
1923 torture_suite_add_1smb_test(suite, "nttrans", torture_nttrans_scan);
1924 torture_suite_add_1smb_test(suite, "createx_access", torture_createx_access);
1925 torture_suite_add_2smb_test(suite, "createx_sharemodes_file", torture_createx_sharemodes_file);
1926 torture_suite_add_2smb_test(suite, "createx_sharemodes_dir", torture_createx_sharemodes_dir);
1927 torture_suite_add_1smb_test(suite, "maximum_allowed", torture_maximum_allowed);
1929 torture_suite_add_simple_test(suite, "bench-holdcon", torture_holdcon);
1930 torture_suite_add_1smb_test(suite, "bench-holdopen", torture_holdopen);
1931 torture_suite_add_simple_test(suite, "bench-readwrite", run_benchrw);
1932 torture_suite_add_smb_multi_test(suite, "bench-torture", run_torture);
1933 torture_suite_add_1smb_test(suite, "scan-pipe_number", run_pipe_number);
1934 torture_suite_add_1smb_test(suite, "scan-ioctl", torture_ioctl_test);
1935 torture_suite_add_1smb_test(suite, "scan-maxfid", torture_maxfid_test);
1937 suite->description = talloc_strdup(suite,
1938 "Basic SMB tests (imported from the original smbtorture)");
1940 torture_register_suite(suite);
1942 return NT_STATUS_OK;