s4:torture:base: move i++ down in loop in run_deferopen()
[Samba.git] / source4 / torture / basic / base.c
blobc7a7d8dc321c0997b9e5ad7c7a146d52053a3ed6
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;
657 NTSTATUS status;
659 nsec = torture_setting_int(tctx, "sharedelay", 1000000);
660 msec = nsec / 1000;
661 sec = ((double)nsec) / ((double) 1000000);
663 torture_comment(tctx, "pid %u: Testing deferred open requests.\n",
664 (unsigned)getpid());
666 while (i < 4) {
667 int fnum = -1;
669 do {
670 struct timeval tv;
671 tv = timeval_current();
672 fnum = smbcli_nt_create_full(cli->tree, fname, 0,
673 SEC_RIGHTS_FILE_ALL,
674 FILE_ATTRIBUTE_NORMAL,
675 NTCREATEX_SHARE_ACCESS_NONE,
676 NTCREATEX_DISP_OPEN_IF, 0, 0);
677 if (fnum != -1) {
678 break;
680 if (NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),NT_STATUS_SHARING_VIOLATION)) {
681 double e = timeval_elapsed(&tv);
682 if (e < (0.5 * sec) || e > ((1.5 * sec) + 1)) {
683 torture_result(tctx, TORTURE_FAIL, "Timing incorrect %.2f violation 1 sec == %.2f\n",
684 e, sec);
685 return false;
688 } while (NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),NT_STATUS_SHARING_VIOLATION));
690 torture_assert(tctx, fnum != -1,
691 talloc_asprintf(tctx,
692 "pid %u: Failed to open %s, error=%s\n",
693 (unsigned)getpid(), fname,
694 smbcli_errstr(cli->tree)));
696 torture_comment(tctx, "pid %u: open %d\n", (unsigned)getpid(), i);
698 smb_msleep(10 * msec);
700 status = smbcli_close(cli->tree, fnum);
701 torture_assert(tctx, !NT_STATUS_IS_ERR(status),
702 talloc_asprintf(tctx,
703 "pid %u: Failed to close %s, "
704 "error=%s\n",
705 (unsigned)getpid(), fname,
706 smbcli_errstr(cli->tree)));
708 smb_msleep(2 * msec);
710 i++;
713 if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) {
714 /* All until the last unlink will fail with sharing violation
715 but also the last request can fail since the file could have
716 been successfully deleted by another (test) process */
717 status = smbcli_nt_error(cli->tree);
718 if ((!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION))
719 && (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND))) {
720 torture_result(tctx, TORTURE_FAIL, "unlink of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
721 correct = false;
725 torture_comment(tctx, "pid %u: deferred test finished\n",
726 (unsigned)getpid());
727 return correct;
731 Try with a wrong vuid and check error message.
734 static bool run_vuidtest(struct torture_context *tctx,
735 struct smbcli_state *cli)
737 const char *fname = "\\vuid.tst";
738 int fnum;
739 size_t size;
740 time_t c_time, a_time, m_time;
742 NTSTATUS result;
744 smbcli_unlink(cli->tree, fname);
746 fnum = smbcli_open(cli->tree, fname,
747 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
749 cli->session->vuid += 1234;
751 torture_comment(tctx, "Testing qfileinfo with wrong vuid\n");
753 if (NT_STATUS_IS_OK(result = smbcli_qfileinfo(cli->tree, fnum, NULL,
754 &size, &c_time, &a_time,
755 &m_time, NULL, NULL))) {
756 torture_fail(tctx, "qfileinfo passed with wrong vuid");
759 if (!NT_STATUS_EQUAL(cli->transport->error.e.nt_status,
760 NT_STATUS_DOS(ERRSRV, ERRbaduid)) &&
761 !NT_STATUS_EQUAL(cli->transport->error.e.nt_status,
762 NT_STATUS_INVALID_HANDLE)) {
763 torture_fail(tctx, talloc_asprintf(tctx,
764 "qfileinfo should have returned DOS error "
765 "ERRSRV:ERRbaduid\n but returned %s",
766 smbcli_errstr(cli->tree)));
769 cli->session->vuid -= 1234;
771 torture_assert_ntstatus_ok(tctx, smbcli_close(cli->tree, fnum),
772 talloc_asprintf(tctx, "close failed (%s)", smbcli_errstr(cli->tree)));
774 smbcli_unlink(cli->tree, fname);
776 return true;
780 Test open mode returns on read-only files.
782 static bool run_opentest(struct torture_context *tctx, struct smbcli_state *cli1,
783 struct smbcli_state *cli2)
785 const char *fname = "\\readonly.file";
786 char *control_char_fname;
787 int fnum1, fnum2;
788 uint8_t buf[20];
789 size_t fsize;
790 bool correct = true;
791 char *tmp_path;
792 int failures = 0;
793 int i;
795 asprintf(&control_char_fname, "\\readonly.afile");
796 for (i = 1; i <= 0x1f; i++) {
797 control_char_fname[10] = i;
798 fnum1 = smbcli_nt_create_full(cli1->tree, control_char_fname, 0, SEC_FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
799 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
801 if (!check_error(__location__, cli1, ERRDOS, ERRinvalidname,
802 NT_STATUS_OBJECT_NAME_INVALID)) {
803 torture_result(tctx, TORTURE_FAIL, "Error code should be NT_STATUS_OBJECT_NAME_INVALID, was %s for file with %d char\n",
804 smbcli_errstr(cli1->tree), i);
805 failures++;
808 if (fnum1 != -1) {
809 smbcli_close(cli1->tree, fnum1);
811 smbcli_setatr(cli1->tree, control_char_fname, 0, 0);
812 smbcli_unlink(cli1->tree, control_char_fname);
814 free(control_char_fname);
816 if (!failures)
817 torture_comment(tctx, "Create file with control char names passed.\n");
819 smbcli_setatr(cli1->tree, fname, 0, 0);
820 smbcli_unlink(cli1->tree, fname);
822 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
823 if (fnum1 == -1) {
824 torture_result(tctx, TORTURE_FAIL, "open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
825 return false;
828 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
829 torture_result(tctx, TORTURE_FAIL, "close2 failed (%s)\n", smbcli_errstr(cli1->tree));
830 return false;
833 if (NT_STATUS_IS_ERR(smbcli_setatr(cli1->tree, fname, FILE_ATTRIBUTE_READONLY, 0))) {
834 torture_result(tctx, TORTURE_FAIL,
835 __location__ ": smbcli_setatr failed (%s)\n", smbcli_errstr(cli1->tree));
836 CHECK_MAX_FAILURES(error_test1);
837 return false;
840 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_WRITE);
841 if (fnum1 == -1) {
842 torture_result(tctx, TORTURE_FAIL,
843 __location__ ": open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
844 CHECK_MAX_FAILURES(error_test1);
845 return false;
848 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
849 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_ALL);
851 if (check_error(__location__, cli1, ERRDOS, ERRnoaccess,
852 NT_STATUS_ACCESS_DENIED)) {
853 torture_comment(tctx, "correct error code ERRDOS/ERRnoaccess returned\n");
856 torture_comment(tctx, "finished open test 1\n");
858 error_test1:
859 smbcli_close(cli1->tree, fnum1);
861 /* Now try not readonly and ensure ERRbadshare is returned. */
863 smbcli_setatr(cli1->tree, fname, 0, 0);
865 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_WRITE);
866 if (fnum1 == -1) {
867 torture_result(tctx, TORTURE_FAIL, "open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
868 return false;
871 /* This will fail - but the error should be ERRshare. */
872 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_ALL);
874 if (check_error(__location__, cli1, ERRDOS, ERRbadshare,
875 NT_STATUS_SHARING_VIOLATION)) {
876 torture_comment(tctx, "correct error code ERRDOS/ERRbadshare returned\n");
879 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
880 torture_result(tctx, TORTURE_FAIL, "close2 failed (%s)\n", smbcli_errstr(cli1->tree));
881 return false;
884 smbcli_unlink(cli1->tree, fname);
886 torture_comment(tctx, "finished open test 2\n");
888 /* Test truncate open disposition on file opened for read. */
890 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
891 if (fnum1 == -1) {
892 torture_result(tctx, TORTURE_FAIL, "(3) open (1) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
893 return false;
896 /* write 20 bytes. */
898 memset(buf, '\0', 20);
900 if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, 20) != 20) {
901 torture_result(tctx, TORTURE_FAIL, "write failed (%s)\n", smbcli_errstr(cli1->tree));
902 correct = false;
905 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
906 torture_result(tctx, TORTURE_FAIL, "(3) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
907 return false;
910 /* Ensure size == 20. */
911 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
912 torture_result(tctx, TORTURE_FAIL,
913 __location__ ": (3) getatr failed (%s)\n", smbcli_errstr(cli1->tree));
914 CHECK_MAX_FAILURES(error_test3);
915 return false;
918 if (fsize != 20) {
919 torture_result(tctx, TORTURE_FAIL,
920 __location__ ": (3) file size != 20\n");
921 CHECK_MAX_FAILURES(error_test3);
922 return false;
925 /* Now test if we can truncate a file opened for readonly. */
927 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY|O_TRUNC, DENY_NONE);
928 if (fnum1 == -1) {
929 torture_result(tctx, TORTURE_FAIL,
930 __location__ ": (3) open (2) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
931 CHECK_MAX_FAILURES(error_test3);
932 return false;
935 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
936 torture_result(tctx, TORTURE_FAIL,
937 __location__ ": close2 failed (%s)\n", smbcli_errstr(cli1->tree));
938 return false;
941 /* Ensure size == 0. */
942 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
943 torture_result(tctx, TORTURE_FAIL,
944 __location__ ": (3) getatr failed (%s)\n", smbcli_errstr(cli1->tree));
945 CHECK_MAX_FAILURES(error_test3);
946 return false;
949 if (fsize != 0) {
950 torture_result(tctx, TORTURE_FAIL,
951 __location__ ": (3) file size != 0\n");
952 CHECK_MAX_FAILURES(error_test3);
953 return false;
955 torture_comment(tctx, "finished open test 3\n");
956 error_test3:
958 fnum1 = fnum2 = -1;
959 smbcli_unlink(cli1->tree, fname);
962 torture_comment(tctx, "Testing ctemp\n");
963 fnum1 = smbcli_ctemp(cli1->tree, "\\", &tmp_path);
964 if (fnum1 == -1) {
965 torture_result(tctx, TORTURE_FAIL,
966 __location__ ": ctemp failed (%s)\n", smbcli_errstr(cli1->tree));
967 CHECK_MAX_FAILURES(error_test4);
968 return false;
970 torture_comment(tctx, "ctemp gave path %s\n", tmp_path);
972 error_test4:
973 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
974 torture_comment(tctx, "close of temp failed (%s)\n", smbcli_errstr(cli1->tree));
976 if (NT_STATUS_IS_ERR(smbcli_unlink(cli1->tree, tmp_path))) {
977 torture_comment(tctx, "unlink of temp failed (%s)\n", smbcli_errstr(cli1->tree));
980 /* Test the non-io opens... */
982 torture_comment(tctx, "Test #1 testing 2 non-io opens (no delete)\n");
983 fnum1 = fnum2 = -1;
984 smbcli_setatr(cli2->tree, fname, 0, 0);
985 smbcli_unlink(cli2->tree, fname);
987 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
988 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
990 if (fnum1 == -1) {
991 torture_result(tctx, TORTURE_FAIL,
992 __location__ ": Test 1 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
993 CHECK_MAX_FAILURES(error_test10);
994 return false;
997 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
998 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
999 if (fnum2 == -1) {
1000 torture_result(tctx, TORTURE_FAIL,
1001 __location__ ": Test 1 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1002 CHECK_MAX_FAILURES(error_test10);
1003 return false;
1006 torture_comment(tctx, "non-io open test #1 passed.\n");
1007 error_test10:
1009 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1010 torture_comment(tctx, "Test 1 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1012 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1013 torture_comment(tctx, "Test 1 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1016 torture_comment(tctx, "Test #2 testing 2 non-io opens (first with delete)\n");
1017 fnum1 = fnum2 = -1;
1018 smbcli_unlink(cli1->tree, fname);
1020 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1021 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1023 if (fnum1 == -1) {
1024 torture_result(tctx, TORTURE_FAIL,
1025 __location__ ": Test 2 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1026 CHECK_MAX_FAILURES(error_test20);
1027 return false;
1030 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1031 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1033 if (fnum2 == -1) {
1034 torture_result(tctx, TORTURE_FAIL,
1035 __location__ ": Test 2 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1036 CHECK_MAX_FAILURES(error_test20);
1037 return false;
1040 torture_comment(tctx, "non-io open test #2 passed.\n");
1041 error_test20:
1043 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1044 torture_comment(tctx, "Test 1 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1046 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1047 torture_comment(tctx, "Test 1 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1050 fnum1 = fnum2 = -1;
1051 smbcli_unlink(cli1->tree, fname);
1053 torture_comment(tctx, "Test #3 testing 2 non-io opens (second with delete)\n");
1055 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1056 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1058 if (fnum1 == -1) {
1059 torture_result(tctx, TORTURE_FAIL,
1060 __location__ ": Test 3 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1061 CHECK_MAX_FAILURES(error_test30);
1062 return false;
1065 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1066 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1068 if (fnum2 == -1) {
1069 torture_result(tctx, TORTURE_FAIL,
1070 __location__ ": Test 3 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1071 CHECK_MAX_FAILURES(error_test30);
1072 return false;
1075 torture_comment(tctx, "non-io open test #3 passed.\n");
1076 error_test30:
1078 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1079 torture_comment(tctx, "Test 3 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1081 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1082 torture_comment(tctx, "Test 3 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1085 torture_comment(tctx, "Test #4 testing 2 non-io opens (both with delete)\n");
1086 fnum1 = fnum2 = -1;
1087 smbcli_unlink(cli1->tree, fname);
1089 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1090 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1092 if (fnum1 == -1) {
1093 torture_result(tctx, TORTURE_FAIL,
1094 __location__ ": Test 4 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1095 CHECK_MAX_FAILURES(error_test40);
1096 return false;
1099 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1100 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1102 if (fnum2 != -1) {
1103 torture_result(tctx, TORTURE_FAIL,
1104 __location__ ": Test 4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1105 CHECK_MAX_FAILURES(error_test40);
1106 return false;
1109 torture_comment(tctx, "Test 4 open 2 of %s gave %s (correct error should be %s)\n", fname, smbcli_errstr(cli2->tree), "sharing violation");
1111 torture_comment(tctx, "non-io open test #4 passed.\n");
1112 error_test40:
1114 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1115 torture_comment(tctx, "Test 4 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1117 if (fnum2 != -1 && NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1118 torture_comment(tctx, "Test 4 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1121 torture_comment(tctx, "Test #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
1122 fnum1 = fnum2 = -1;
1123 smbcli_unlink(cli1->tree, fname);
1125 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1126 NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1128 if (fnum1 == -1) {
1129 torture_result(tctx, TORTURE_FAIL,
1130 __location__ ": Test 5 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1131 CHECK_MAX_FAILURES(error_test50);
1132 return false;
1135 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1136 NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1138 if (fnum2 == -1) {
1139 torture_result(tctx, TORTURE_FAIL,
1140 __location__ ": Test 5 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1141 CHECK_MAX_FAILURES(error_test50);
1142 return false;
1145 torture_comment(tctx, "non-io open test #5 passed.\n");
1146 error_test50:
1148 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1149 torture_comment(tctx, "Test 5 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1152 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1153 torture_comment(tctx, "Test 5 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1156 torture_comment(tctx, "Test #6 testing 1 non-io open, one io open\n");
1157 fnum1 = fnum2 = -1;
1158 smbcli_unlink(cli1->tree, fname);
1160 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
1161 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1163 if (fnum1 == -1) {
1164 torture_result(tctx, TORTURE_FAIL,
1165 __location__ ": Test 6 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1166 CHECK_MAX_FAILURES(error_test60);
1167 return false;
1170 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1171 NTCREATEX_SHARE_ACCESS_READ, NTCREATEX_DISP_OPEN_IF, 0, 0);
1173 if (fnum2 == -1) {
1174 torture_result(tctx, TORTURE_FAIL,
1175 __location__ ": Test 6 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1176 CHECK_MAX_FAILURES(error_test60);
1177 return false;
1180 torture_comment(tctx, "non-io open test #6 passed.\n");
1181 error_test60:
1183 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1184 torture_comment(tctx, "Test 6 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1187 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1188 torture_comment(tctx, "Test 6 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1191 torture_comment(tctx, "Test #7 testing 1 non-io open, one io open with delete\n");
1192 fnum1 = fnum2 = -1;
1193 smbcli_unlink(cli1->tree, fname);
1195 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
1196 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1198 if (fnum1 == -1) {
1199 torture_result(tctx, TORTURE_FAIL,
1200 __location__ ": Test 7 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1201 CHECK_MAX_FAILURES(error_test70);
1202 return false;
1205 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1206 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1208 if (fnum2 != -1) {
1209 torture_result(tctx, TORTURE_FAIL,
1210 __location__ ": Test 7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1211 CHECK_MAX_FAILURES(error_test70);
1212 return false;
1215 torture_comment(tctx, "Test 7 open 2 of %s gave %s (correct error should be %s)\n", fname, smbcli_errstr(cli2->tree), "sharing violation");
1217 torture_comment(tctx, "non-io open test #7 passed.\n");
1218 error_test70:
1220 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1221 torture_comment(tctx, "Test 7 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1223 if (fnum2 != -1 && NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1224 torture_comment(tctx, "Test 7 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1227 torture_comment(tctx, "Test #8 testing one normal open, followed by lock, followed by open with truncate\n");
1228 fnum1 = fnum2 = -1;
1229 smbcli_unlink(cli1->tree, fname);
1231 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1232 if (fnum1 == -1) {
1233 torture_result(tctx, TORTURE_FAIL, "(8) open (1) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1234 return false;
1237 /* write 20 bytes. */
1239 memset(buf, '\0', 20);
1241 if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, 20) != 20) {
1242 torture_result(tctx, TORTURE_FAIL, "(8) write failed (%s)\n", smbcli_errstr(cli1->tree));
1243 correct = false;
1246 /* Ensure size == 20. */
1247 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
1248 torture_result(tctx, TORTURE_FAIL,
1249 __location__ ": (8) getatr (1) failed (%s)\n", smbcli_errstr(cli1->tree));
1250 CHECK_MAX_FAILURES(error_test80);
1251 return false;
1254 if (fsize != 20) {
1255 torture_result(tctx, TORTURE_FAIL,
1256 __location__ ": (8) file size %lu != 20\n", (unsigned long)fsize);
1257 CHECK_MAX_FAILURES(error_test80);
1258 return false;
1261 /* Get an exclusive lock on the open file. */
1262 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
1263 torture_result(tctx, TORTURE_FAIL,
1264 __location__ ": (8) lock1 failed (%s)\n", smbcli_errstr(cli1->tree));
1265 CHECK_MAX_FAILURES(error_test80);
1266 return false;
1269 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR|O_TRUNC, DENY_NONE);
1270 if (fnum1 == -1) {
1271 torture_result(tctx, TORTURE_FAIL, "(8) open (2) of %s with truncate failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1272 return false;
1275 /* Ensure size == 0. */
1276 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
1277 torture_result(tctx, TORTURE_FAIL,
1278 __location__ ": (8) getatr (2) failed (%s)\n", smbcli_errstr(cli1->tree));
1279 CHECK_MAX_FAILURES(error_test80);
1280 return false;
1283 if (fsize != 0) {
1284 torture_result(tctx, TORTURE_FAIL,
1285 __location__ ": (8) file size %lu != 0\n", (unsigned long)fsize);
1286 CHECK_MAX_FAILURES(error_test80);
1287 return false;
1290 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1291 torture_result(tctx, TORTURE_FAIL, "(8) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
1292 return false;
1295 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum2))) {
1296 torture_result(tctx, TORTURE_FAIL, "(8) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
1297 return false;
1300 error_test80:
1302 torture_comment(tctx, "open test #8 passed.\n");
1304 smbcli_unlink(cli1->tree, fname);
1306 return failures > 0 ? false : correct;
1309 /* FIRST_DESIRED_ACCESS 0xf019f */
1310 #define FIRST_DESIRED_ACCESS SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA|SEC_FILE_APPEND_DATA|\
1311 SEC_FILE_READ_EA| /* 0xf */ \
1312 SEC_FILE_WRITE_EA|SEC_FILE_READ_ATTRIBUTE| /* 0x90 */ \
1313 SEC_FILE_WRITE_ATTRIBUTE| /* 0x100 */ \
1314 SEC_STD_DELETE|SEC_STD_READ_CONTROL|\
1315 SEC_STD_WRITE_DAC|SEC_STD_WRITE_OWNER /* 0xf0000 */
1316 /* SECOND_DESIRED_ACCESS 0xe0080 */
1317 #define SECOND_DESIRED_ACCESS SEC_FILE_READ_ATTRIBUTE| /* 0x80 */ \
1318 SEC_STD_READ_CONTROL|SEC_STD_WRITE_DAC|\
1319 SEC_STD_WRITE_OWNER /* 0xe0000 */
1321 #if 0
1322 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTE| /* 0x80 */ \
1323 READ_CONTROL|WRITE_DAC|\
1324 SEC_FILE_READ_DATA|\
1325 WRITE_OWNER /* */
1326 #endif
1331 Test ntcreate calls made by xcopy
1333 static bool run_xcopy(struct torture_context *tctx,
1334 struct smbcli_state *cli1)
1336 const char *fname = "\\test.txt";
1337 int fnum1, fnum2;
1339 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1340 FIRST_DESIRED_ACCESS,
1341 FILE_ATTRIBUTE_ARCHIVE,
1342 NTCREATEX_SHARE_ACCESS_NONE,
1343 NTCREATEX_DISP_OVERWRITE_IF,
1344 0x4044, 0);
1346 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx,
1347 "First open failed - %s", smbcli_errstr(cli1->tree)));
1349 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1350 SECOND_DESIRED_ACCESS, 0,
1351 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN,
1352 0x200000, 0);
1353 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx,
1354 "second open failed - %s", smbcli_errstr(cli1->tree)));
1356 return true;
1359 static bool run_iometer(struct torture_context *tctx,
1360 struct smbcli_state *cli)
1362 const char *fname = "\\iobw.tst";
1363 int fnum;
1364 size_t filesize;
1365 NTSTATUS status;
1366 char buf[2048];
1367 int ops;
1369 memset(buf, 0, sizeof(buf));
1371 status = smbcli_getatr(cli->tree, fname, NULL, &filesize, NULL);
1372 torture_assert_ntstatus_ok(tctx, status,
1373 talloc_asprintf(tctx, "smbcli_getatr failed: %s", nt_errstr(status)));
1375 torture_comment(tctx, "size: %d\n", (int)filesize);
1377 filesize -= (sizeof(buf) - 1);
1379 fnum = smbcli_nt_create_full(cli->tree, fname, 0x16,
1380 0x2019f, 0, 0x3, 3, 0x42, 0x3);
1381 torture_assert(tctx, fnum != -1, talloc_asprintf(tctx, "open failed: %s",
1382 smbcli_errstr(cli->tree)));
1384 ops = 0;
1386 while (true) {
1387 int i, num_reads, num_writes;
1389 num_reads = random() % 10;
1390 num_writes = random() % 3;
1392 for (i=0; i<num_reads; i++) {
1393 ssize_t res;
1394 if (ops++ > torture_numops) {
1395 return true;
1397 res = smbcli_read(cli->tree, fnum, buf,
1398 random() % filesize, sizeof(buf));
1399 torture_assert(tctx, res == sizeof(buf),
1400 talloc_asprintf(tctx, "read failed: %s",
1401 smbcli_errstr(cli->tree)));
1403 for (i=0; i<num_writes; i++) {
1404 ssize_t res;
1405 if (ops++ > torture_numops) {
1406 return true;
1408 res = smbcli_write(cli->tree, fnum, 0, buf,
1409 random() % filesize, sizeof(buf));
1410 torture_assert(tctx, res == sizeof(buf),
1411 talloc_asprintf(tctx, "read failed: %s",
1412 smbcli_errstr(cli->tree)));
1418 tries variants of chkpath
1420 static bool torture_chkpath_test(struct torture_context *tctx,
1421 struct smbcli_state *cli)
1423 int fnum;
1424 bool ret;
1426 torture_comment(tctx, "Testing valid and invalid paths\n");
1428 /* cleanup from an old run */
1429 smbcli_rmdir(cli->tree, "\\chkpath.dir\\dir2");
1430 smbcli_unlink(cli->tree, "\\chkpath.dir\\*");
1431 smbcli_rmdir(cli->tree, "\\chkpath.dir");
1433 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\chkpath.dir"))) {
1434 torture_result(tctx, TORTURE_FAIL, "mkdir1 failed : %s\n", smbcli_errstr(cli->tree));
1435 return false;
1438 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\chkpath.dir\\dir2"))) {
1439 torture_result(tctx, TORTURE_FAIL, "mkdir2 failed : %s\n", smbcli_errstr(cli->tree));
1440 return false;
1443 fnum = smbcli_open(cli->tree, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1444 if (fnum == -1) {
1445 torture_result(tctx, TORTURE_FAIL, "open1 failed (%s)\n", smbcli_errstr(cli->tree));
1446 return false;
1448 smbcli_close(cli->tree, fnum);
1450 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir"))) {
1451 torture_result(tctx, TORTURE_FAIL, "chkpath1 failed: %s\n", smbcli_errstr(cli->tree));
1452 ret = false;
1455 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\dir2"))) {
1456 torture_result(tctx, TORTURE_FAIL, "chkpath2 failed: %s\n", smbcli_errstr(cli->tree));
1457 ret = false;
1460 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\foo.txt"))) {
1461 ret = check_error(__location__, cli, ERRDOS, ERRbadpath,
1462 NT_STATUS_NOT_A_DIRECTORY);
1463 } else {
1464 torture_result(tctx, TORTURE_FAIL, "* chkpath on a file should fail\n");
1465 ret = false;
1468 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\bar.txt"))) {
1469 ret = check_error(__location__, cli, ERRDOS, ERRbadpath,
1470 NT_STATUS_OBJECT_NAME_NOT_FOUND);
1471 } else {
1472 torture_result(tctx, TORTURE_FAIL, "* chkpath on a non existent file should fail\n");
1473 ret = false;
1476 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\dirxx\\bar.txt"))) {
1477 ret = check_error(__location__, cli, ERRDOS, ERRbadpath,
1478 NT_STATUS_OBJECT_PATH_NOT_FOUND);
1479 } else {
1480 torture_result(tctx, TORTURE_FAIL, "* chkpath on a non existent component should fail\n");
1481 ret = false;
1484 smbcli_rmdir(cli->tree, "\\chkpath.dir\\dir2");
1485 smbcli_unlink(cli->tree, "\\chkpath.dir\\*");
1486 smbcli_rmdir(cli->tree, "\\chkpath.dir");
1488 return ret;
1492 * This is a test to excercise some weird Samba3 error paths.
1495 static bool torture_samba3_errorpaths(struct torture_context *tctx)
1497 bool nt_status_support;
1498 struct smbcli_state *cli_nt = NULL, *cli_dos = NULL;
1499 bool result = false;
1500 int fnum;
1501 const char *os2_fname = ".+,;=[].";
1502 const char *dname = "samba3_errordir";
1503 union smb_open io;
1504 NTSTATUS status;
1506 nt_status_support = lpcfg_nt_status_support(tctx->lp_ctx);
1508 if (!lpcfg_set_cmdline(tctx->lp_ctx, "nt status support", "yes")) {
1509 torture_result(tctx, TORTURE_FAIL, "Could not set 'nt status support = yes'\n");
1510 goto fail;
1513 if (!torture_open_connection(&cli_nt, tctx, 0)) {
1514 goto fail;
1517 if (!lpcfg_set_cmdline(tctx->lp_ctx, "nt status support", "no")) {
1518 torture_result(tctx, TORTURE_FAIL, "Could not set 'nt status support = yes'\n");
1519 goto fail;
1522 if (!torture_open_connection(&cli_dos, tctx, 1)) {
1523 goto fail;
1526 if (!lpcfg_set_cmdline(tctx->lp_ctx, "nt status support",
1527 nt_status_support ? "yes":"no")) {
1528 torture_result(tctx, TORTURE_FAIL, "Could not reset 'nt status support = yes'");
1529 goto fail;
1532 smbcli_unlink(cli_nt->tree, os2_fname);
1533 smbcli_rmdir(cli_nt->tree, dname);
1535 if (!NT_STATUS_IS_OK(smbcli_mkdir(cli_nt->tree, dname))) {
1536 torture_result(tctx, TORTURE_FAIL, "smbcli_mkdir(%s) failed: %s\n", dname,
1537 smbcli_errstr(cli_nt->tree));
1538 goto fail;
1541 io.generic.level = RAW_OPEN_NTCREATEX;
1542 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1543 io.ntcreatex.in.root_fid.fnum = 0;
1544 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1545 io.ntcreatex.in.alloc_size = 1024*1024;
1546 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
1547 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1548 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1549 io.ntcreatex.in.create_options = 0;
1550 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1551 io.ntcreatex.in.security_flags = 0;
1552 io.ntcreatex.in.fname = dname;
1554 status = smb_raw_open(cli_nt->tree, tctx, &io);
1555 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1556 torture_result(tctx, TORTURE_FAIL, "(%s) incorrect status %s should be %s\n",
1557 __location__, nt_errstr(status),
1558 nt_errstr(NT_STATUS_OBJECT_NAME_COLLISION));
1559 goto fail;
1561 status = smb_raw_open(cli_dos->tree, tctx, &io);
1562 if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS, ERRfilexists))) {
1563 torture_result(tctx, TORTURE_FAIL, "(%s) incorrect status %s should be %s\n",
1564 __location__, nt_errstr(status),
1565 nt_errstr(NT_STATUS_DOS(ERRDOS, ERRfilexists)));
1566 goto fail;
1569 status = smbcli_mkdir(cli_nt->tree, dname);
1570 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1571 torture_result(tctx, TORTURE_FAIL, "(%s) incorrect status %s should be %s\n",
1572 __location__, nt_errstr(status),
1573 nt_errstr(NT_STATUS_OBJECT_NAME_COLLISION));
1574 goto fail;
1576 status = smbcli_mkdir(cli_dos->tree, dname);
1577 if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS, ERRnoaccess))) {
1578 torture_result(tctx, TORTURE_FAIL, "(%s) incorrect status %s should be %s\n",
1579 __location__, nt_errstr(status),
1580 nt_errstr(NT_STATUS_DOS(ERRDOS, ERRnoaccess)));
1581 goto fail;
1585 union smb_mkdir md;
1586 md.t2mkdir.level = RAW_MKDIR_T2MKDIR;
1587 md.t2mkdir.in.path = dname;
1588 md.t2mkdir.in.num_eas = 0;
1589 md.t2mkdir.in.eas = NULL;
1591 status = smb_raw_mkdir(cli_nt->tree, &md);
1592 if (!NT_STATUS_EQUAL(status,
1593 NT_STATUS_OBJECT_NAME_COLLISION)) {
1594 torture_comment(
1595 tctx, "(%s) incorrect status %s should be "
1596 "NT_STATUS_OBJECT_NAME_COLLISION\n",
1597 __location__, nt_errstr(status));
1598 goto fail;
1600 status = smb_raw_mkdir(cli_dos->tree, &md);
1601 if (!NT_STATUS_EQUAL(status,
1602 NT_STATUS_DOS(ERRDOS, ERRrename))) {
1603 torture_result(tctx, TORTURE_FAIL, "(%s) incorrect status %s "
1604 "should be ERRDOS:ERRrename\n",
1605 __location__, nt_errstr(status));
1606 goto fail;
1610 io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1611 status = smb_raw_open(cli_nt->tree, tctx, &io);
1612 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1613 torture_result(tctx, TORTURE_FAIL, "(%s) incorrect status %s should be %s\n",
1614 __location__, nt_errstr(status),
1615 nt_errstr(NT_STATUS_OBJECT_NAME_COLLISION));
1616 goto fail;
1619 status = smb_raw_open(cli_dos->tree, tctx, &io);
1620 if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS, ERRfilexists))) {
1621 torture_result(tctx, TORTURE_FAIL, "(%s) incorrect status %s should be %s\n",
1622 __location__, nt_errstr(status),
1623 nt_errstr(NT_STATUS_DOS(ERRDOS, ERRfilexists)));
1624 goto fail;
1628 /* Test an invalid DOS deny mode */
1629 const char *fname = "test.txt";
1631 fnum = smbcli_open(cli_nt->tree, fname, O_RDWR | O_CREAT, 5);
1632 if (fnum != -1) {
1633 torture_result(tctx, TORTURE_FAIL, "Open(%s) with invalid deny mode succeeded -- "
1634 "expected failure\n", fname);
1635 smbcli_close(cli_nt->tree, fnum);
1636 goto fail;
1638 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli_nt->tree),
1639 NT_STATUS_DOS(ERRDOS,ERRbadaccess))) {
1640 torture_result(tctx, TORTURE_FAIL, "Expected DOS error ERRDOS/ERRbadaccess, "
1641 "got %s\n", smbcli_errstr(cli_nt->tree));
1642 goto fail;
1645 fnum = smbcli_open(cli_dos->tree, fname, O_RDWR | O_CREAT, 5);
1646 if (fnum != -1) {
1647 torture_result(tctx, TORTURE_FAIL, "Open(%s) with invalid deny mode succeeded -- "
1648 "expected failure\n", fname);
1649 smbcli_close(cli_nt->tree, fnum);
1650 goto fail;
1652 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli_nt->tree),
1653 NT_STATUS_DOS(ERRDOS,ERRbadaccess))) {
1654 torture_result(tctx, TORTURE_FAIL, "Expected DOS error ERRDOS:ERRbadaccess, "
1655 "got %s\n", smbcli_errstr(cli_nt->tree));
1656 goto fail;
1662 * Samba 3.0.23 has a bug that an existing file can be opened
1663 * as a directory using ntcreate&x. Test this.
1666 const char *fname = "\\test_dir.txt";
1668 fnum = smbcli_open(cli_nt->tree, fname, O_RDWR|O_CREAT,
1669 DENY_NONE);
1670 if (fnum == -1) {
1671 d_printf("(%s) smbcli_open failed: %s\n", __location__,
1672 smbcli_errstr(cli_nt->tree));
1674 smbcli_close(cli_nt->tree, fnum);
1676 io.generic.level = RAW_OPEN_NTCREATEX;
1677 io.ntcreatex.in.root_fid.fnum = 0;
1678 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1679 io.ntcreatex.in.alloc_size = 0;
1680 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
1681 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1682 NTCREATEX_SHARE_ACCESS_WRITE|
1683 NTCREATEX_SHARE_ACCESS_DELETE;
1684 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1685 io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1686 io.ntcreatex.in.impersonation =
1687 NTCREATEX_IMPERSONATION_ANONYMOUS;
1688 io.ntcreatex.in.security_flags = 0;
1689 io.ntcreatex.in.fname = fname;
1690 io.ntcreatex.in.flags = 0;
1692 status = smb_raw_open(cli_nt->tree, tctx, &io);
1693 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_A_DIRECTORY)) {
1694 torture_result(tctx, TORTURE_FAIL, "ntcreate as dir gave %s, "
1695 "expected NT_STATUS_NOT_A_DIRECTORY\n",
1696 nt_errstr(status));
1697 result = false;
1700 if (NT_STATUS_IS_OK(status)) {
1701 smbcli_close(cli_nt->tree, io.ntcreatex.out.file.fnum);
1704 status = smb_raw_open(cli_dos->tree, tctx, &io);
1705 if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS,
1706 ERRbaddirectory))) {
1707 torture_result(tctx, TORTURE_FAIL, "ntcreate as dir gave %s, "
1708 "expected NT_STATUS_NOT_A_DIRECTORY\n",
1709 nt_errstr(status));
1710 result = false;
1713 if (NT_STATUS_IS_OK(status)) {
1714 smbcli_close(cli_dos->tree,
1715 io.ntcreatex.out.file.fnum);
1718 smbcli_unlink(cli_nt->tree, fname);
1721 if (!torture_setting_bool(tctx, "samba3", false)) {
1722 goto done;
1725 fnum = smbcli_open(cli_dos->tree, os2_fname,
1726 O_RDWR | O_CREAT | O_TRUNC,
1727 DENY_NONE);
1728 if (fnum != -1) {
1729 torture_result(tctx, TORTURE_FAIL, "Open(%s) succeeded -- expected failure\n",
1730 os2_fname);
1731 smbcli_close(cli_dos->tree, fnum);
1732 goto fail;
1735 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli_dos->tree),
1736 NT_STATUS_DOS(ERRDOS, ERRcannotopen))) {
1737 torture_result(tctx, TORTURE_FAIL, "Expected DOS error ERRDOS/ERRcannotopen, got %s\n",
1738 smbcli_errstr(cli_dos->tree));
1739 goto fail;
1742 fnum = smbcli_open(cli_nt->tree, os2_fname,
1743 O_RDWR | O_CREAT | O_TRUNC,
1744 DENY_NONE);
1745 if (fnum != -1) {
1746 torture_result(tctx, TORTURE_FAIL, "Open(%s) succeeded -- expected failure\n",
1747 os2_fname);
1748 smbcli_close(cli_nt->tree, fnum);
1749 goto fail;
1752 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli_nt->tree),
1753 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1754 torture_result(tctx, TORTURE_FAIL, "Expected error NT_STATUS_OBJECT_NAME_NOT_FOUND, "
1755 "got %s\n", smbcli_errstr(cli_nt->tree));
1756 goto fail;
1759 done:
1760 result = true;
1762 fail:
1763 if (cli_dos != NULL) {
1764 torture_close_connection(cli_dos);
1766 if (cli_nt != NULL) {
1767 torture_close_connection(cli_nt);
1770 return result;
1774 This checks file/dir birthtime
1776 static void list_fn(struct clilist_file_info *finfo, const char *name,
1777 void *state){
1779 /* Just to change dir access time*/
1780 sleep(5);
1784 static bool run_birthtimetest(struct torture_context *tctx,
1785 struct smbcli_state *cli)
1787 int fnum;
1788 size_t size;
1789 time_t c_time, a_time, m_time, w_time, c_time1;
1790 const char *fname = "\\birthtime.tst";
1791 const char *dname = "\\birthtime";
1792 const char *fname2 = "\\birthtime\\birthtime.tst";
1793 bool correct = true;
1794 uint8_t buf[16];
1797 smbcli_unlink(cli->tree, fname);
1799 torture_comment(tctx, "Testing Birthtime for File\n");
1801 /* Save File birthtime/creationtime */
1802 fnum = smbcli_open(cli->tree, fname, O_RDWR | O_CREAT | O_TRUNC,
1803 DENY_NONE);
1804 if (NT_STATUS_IS_ERR(smbcli_qfileinfo(cli->tree, fnum, NULL, &size,
1805 &c_time, &a_time, &m_time, NULL, NULL))) {
1806 torture_result(tctx, TORTURE_FAIL, "ERROR: qfileinfo failed (%s)\n",
1807 smbcli_errstr(cli->tree));
1808 correct = false;
1810 smbcli_close(cli->tree, fnum);
1812 sleep(10);
1814 /* Change in File attribute changes file change time*/
1815 smbcli_setatr(cli->tree, fname, FILE_ATTRIBUTE_SYSTEM, 0);
1817 fnum = smbcli_open(cli->tree, fname, O_RDWR | O_CREAT , DENY_NONE);
1818 /* Writing updates modification time*/
1819 smbcli_smbwrite(cli->tree, fnum, &fname, 0, sizeof(fname));
1820 /*Reading updates access time */
1821 smbcli_read(cli->tree, fnum, buf, 0, 13);
1822 smbcli_close(cli->tree, fnum);
1824 if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, fname, &c_time1,
1825 &a_time, &m_time, &w_time, &size, NULL, NULL))) {
1826 torture_result(tctx, TORTURE_FAIL, "ERROR: qpathinfo2 failed (%s)\n",
1827 smbcli_errstr(cli->tree));
1828 correct = false;
1829 } else {
1830 fprintf(stdout, "c_time = %li, c_time1 = %li\n",
1831 (long) c_time, (long) c_time1);
1832 if (c_time1 != c_time) {
1833 torture_result(tctx, TORTURE_FAIL, "This system updated file \
1834 birth times! Not expected!\n");
1835 correct = false;
1838 smbcli_unlink(cli->tree, fname);
1840 torture_comment(tctx, "Testing Birthtime for Directory\n");
1842 /* check if the server does not update the directory birth time
1843 when creating a new file */
1844 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, dname))) {
1845 torture_result(tctx, TORTURE_FAIL, "ERROR: mkdir failed (%s)\n",
1846 smbcli_errstr(cli->tree));
1847 correct = false;
1849 sleep(3);
1850 if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, "\\birthtime\\",
1851 &c_time,&a_time,&m_time,&w_time, &size, NULL, NULL))){
1852 torture_result(tctx, TORTURE_FAIL, "ERROR: qpathinfo2 failed (%s)\n",
1853 smbcli_errstr(cli->tree));
1854 correct = false;
1857 /* Creating a new file changes dir modification time and change time*/
1858 smbcli_unlink(cli->tree, fname2);
1859 fnum = smbcli_open(cli->tree, fname2, O_RDWR | O_CREAT | O_TRUNC,
1860 DENY_NONE);
1861 smbcli_smbwrite(cli->tree, fnum, &fnum, 0, sizeof(fnum));
1862 smbcli_read(cli->tree, fnum, buf, 0, 13);
1863 smbcli_close(cli->tree, fnum);
1865 /* dir listing changes dir access time*/
1866 smbcli_list(cli->tree, "\\birthtime\\*", 0, list_fn, cli );
1868 if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, "\\birthtime\\",
1869 &c_time1, &a_time, &m_time,&w_time,&size,NULL,NULL))){
1870 torture_result(tctx, TORTURE_FAIL, "ERROR: qpathinfo2 failed (%s)\n",
1871 smbcli_errstr(cli->tree));
1872 correct = false;
1873 } else {
1874 fprintf(stdout, "c_time = %li, c_time1 = %li\n",
1875 (long) c_time, (long) c_time1);
1876 if (c_time1 != c_time) {
1877 torture_result(tctx, TORTURE_FAIL, "This system updated directory \
1878 birth times! Not Expected!\n");
1879 correct = false;
1882 smbcli_unlink(cli->tree, fname2);
1883 smbcli_rmdir(cli->tree, dname);
1885 return correct;
1889 NTSTATUS torture_base_init(void)
1891 struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "base");
1893 torture_suite_add_2smb_test(suite, "fdpass", run_fdpasstest);
1894 torture_suite_add_suite(suite, torture_base_locktest(suite));
1895 torture_suite_add_1smb_test(suite, "unlink", torture_unlinktest);
1896 torture_suite_add_1smb_test(suite, "attr", run_attrtest);
1897 torture_suite_add_1smb_test(suite, "trans2", run_trans2test);
1898 torture_suite_add_1smb_test(suite, "birthtime", run_birthtimetest);
1899 torture_suite_add_simple_test(suite, "negnowait", run_negprot_nowait);
1900 torture_suite_add_1smb_test(suite, "dir1", torture_dirtest1);
1901 torture_suite_add_1smb_test(suite, "dir2", torture_dirtest2);
1902 torture_suite_add_1smb_test(suite, "deny1", torture_denytest1);
1903 torture_suite_add_2smb_test(suite, "deny2", torture_denytest2);
1904 torture_suite_add_2smb_test(suite, "deny3", torture_denytest3);
1905 torture_suite_add_1smb_test(suite, "denydos", torture_denydos_sharing);
1906 torture_suite_add_smb_multi_test(suite, "ntdeny1", torture_ntdenytest1);
1907 torture_suite_add_2smb_test(suite, "ntdeny2", torture_ntdenytest2);
1908 torture_suite_add_1smb_test(suite, "tcon", run_tcon_test);
1909 torture_suite_add_1smb_test(suite, "tcondev", run_tcon_devtype_test);
1910 torture_suite_add_1smb_test(suite, "vuid", run_vuidtest);
1911 torture_suite_add_2smb_test(suite, "rw1", run_readwritetest);
1912 torture_suite_add_2smb_test(suite, "open", run_opentest);
1913 torture_suite_add_smb_multi_test(suite, "defer_open", run_deferopen);
1914 torture_suite_add_1smb_test(suite, "xcopy", run_xcopy);
1915 torture_suite_add_1smb_test(suite, "iometer", run_iometer);
1916 torture_suite_add_1smb_test(suite, "rename", torture_test_rename);
1917 torture_suite_add_suite(suite, torture_test_delete());
1918 torture_suite_add_1smb_test(suite, "properties", torture_test_properties);
1919 torture_suite_add_1smb_test(suite, "mangle", torture_mangle);
1920 torture_suite_add_1smb_test(suite, "openattr", torture_openattrtest);
1921 torture_suite_add_1smb_test(suite, "winattr", torture_winattrtest);
1922 torture_suite_add_suite(suite, torture_charset(suite));
1923 torture_suite_add_1smb_test(suite, "chkpath", torture_chkpath_test);
1924 torture_suite_add_1smb_test(suite, "secleak", torture_sec_leak);
1925 torture_suite_add_simple_test(suite, "disconnect", torture_disconnect);
1926 torture_suite_add_suite(suite, torture_delay_write());
1927 torture_suite_add_simple_test(suite, "samba3error", torture_samba3_errorpaths);
1928 torture_suite_add_1smb_test(suite, "casetable", torture_casetable);
1929 torture_suite_add_1smb_test(suite, "utable", torture_utable);
1930 torture_suite_add_simple_test(suite, "smb", torture_smb_scan);
1931 torture_suite_add_suite(suite, torture_trans2_aliases(suite));
1932 torture_suite_add_1smb_test(suite, "trans2-scan", torture_trans2_scan);
1933 torture_suite_add_1smb_test(suite, "nttrans", torture_nttrans_scan);
1934 torture_suite_add_1smb_test(suite, "createx_access", torture_createx_access);
1935 torture_suite_add_2smb_test(suite, "createx_sharemodes_file", torture_createx_sharemodes_file);
1936 torture_suite_add_2smb_test(suite, "createx_sharemodes_dir", torture_createx_sharemodes_dir);
1937 torture_suite_add_1smb_test(suite, "maximum_allowed", torture_maximum_allowed);
1939 torture_suite_add_simple_test(suite, "bench-holdcon", torture_holdcon);
1940 torture_suite_add_1smb_test(suite, "bench-holdopen", torture_holdopen);
1941 torture_suite_add_simple_test(suite, "bench-readwrite", run_benchrw);
1942 torture_suite_add_smb_multi_test(suite, "bench-torture", run_torture);
1943 torture_suite_add_1smb_test(suite, "scan-pipe_number", run_pipe_number);
1944 torture_suite_add_1smb_test(suite, "scan-ioctl", torture_ioctl_test);
1945 torture_suite_add_1smb_test(suite, "scan-maxfid", torture_maxfid_test);
1947 suite->description = talloc_strdup(suite,
1948 "Basic SMB tests (imported from the original smbtorture)");
1950 torture_register_suite(suite);
1952 return NT_STATUS_OK;